diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib')
950 files changed, 184076 insertions, 0 deletions
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 = ∅ + 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, "<", -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>>", t - s, s, t - s, s); + s = t + 1; + } + break; + } + else + break; + } + continue; + } + break; + case '>': + if (style == STYLE_html) + { + sfputr(sp, ">", -1); + continue; + } + break; + case '&': + if (style == STYLE_html) + { + sfputr(sp, "&", -1); + continue; + } + break; + case '"': + if (style == STYLE_html) + { + sfputr(sp, """, -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, "<", -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>>", t - s, s, t - s, s); + s = t + 1; + } + break; + } + else + break; + } + continue; + } + break; + case '>': + if (style == STYLE_html) + { + sfputr(sp, ">", -1); + continue; + } + break; + case '&': + if (style == STYLE_html) + { + sfputr(sp, "&", -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 ( %s ) <TH align=center><A href=\".\" title=\"Index\">%s</A><TH align=right>%s ( %s )</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, "[", -1); + else if (c == ']') + sfputr(mp, "]", -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, "[", -1); + else if (c == ']') + sfputr(mp, "]", -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, "[", -1); + c = ';'; + } + else if (c == ']') + { + sfputr(mp, "]", -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 ©", -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 = # + 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, ¬ice->item[SINCE]); + PUT(b, '-'); + } + copy(b, t, 4); + if (notice->item[PARENT].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[PARENT]); + } + if (notice->item[CORPORATION].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[CORPORATION]); + if (notice->item[INCORPORATION].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[INCORPORATION]); + } + } + else if (notice->item[COMPANY].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->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(¬ice, &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(¬ice, &buf, ¬ice.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(¬ice, &buf, &item); + } + else + expand(¬ice, &buf, ¬ice.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(¬ice, &buf, NiL, 1, 0); + comment(¬ice, &buf, NiL, 0, 0); + if (notice.item[PACKAGE].data) + { + copy(&tmp, "This software is part of the ", -1); + expand(¬ice, &tmp, ¬ice.item[PACKAGE]); + copy(&tmp, " package", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + if (notice.type >= OPEN) + { + copyright(¬ice, &tmp); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.type >= SPECIAL) + COMMENT(¬ice, &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(¬ice, &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(¬ice, &tmp, ¬ice.item[VERSION]); + } + comment(¬ice, &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(¬ice, &tmp, ¬ice.item[PARENT]); + copy(&tmp, " ", -1); + } + if (notice.item[CORPORATION].data) + { + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + if (notice.item[INCORPORATION].data) + { + copy(&tmp, " ", -1); + expand(¬ice, &tmp, ¬ice.item[INCORPORATION]); + } + } + else if (notice.item[COMPANY].data) + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "A copy of the License is available at", 0); + if (notice.item[URL].data) + { + expand(¬ice, &tmp, ¬ice.item[URL]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[URLMD5].data) + { + copy(&tmp, "(with md5 checksum ", -1); + expand(¬ice, &tmp, ¬ice.item[URLMD5]); + copy(&tmp, ")", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + } + else if (notice.type == EPL) + COMMENT(¬ice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html", 0); + else + COMMENT(¬ice, &buf, "http://www.opensource.org/licenses/cpl", 0); + comment(¬ice, &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(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[i = CORPORATION].data) + { + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[i = PARENT]); + copy(&tmp, " ", -1); + } + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + else if (notice.item[i = COMPANY].data) + { + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[i = PARENT]); + copy(&tmp, " ", -1); + } + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + else + i = -1; + if (notice.item[URL].data) + { + COMMENT(¬ice, &buf, "A copy of the Source Code Agreement is available", 0); + copy(&tmp, "at the ", -1); + if (i >= 0) + expand(¬ice, &tmp, ¬ice.item[i]); + copy(&tmp, " Internet web site URL", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + comment(¬ice, &buf, NiL, 0, 0); + expand(¬ice, &tmp, ¬ice.item[URL]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[URLMD5].data) + { + copy(&tmp, "(with an md5 checksum of ", -1); + expand(¬ice, &tmp, ¬ice.item[URLMD5]); + copy(&tmp, ")", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + } + COMMENT(¬ice, &buf, "If you have copied or used this software without agreeing", 0); + COMMENT(¬ice, &buf, "to the terms of the license you are infringing on", 0); + COMMENT(¬ice, &buf, "the license and copyright and are violating", 0); + if (i >= 0) + expand(¬ice, &tmp, ¬ice.item[i]); + copy(&tmp, "'s", -1); + if (n >= COMLONG) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + else + PUT(&tmp, ' '); + copy(&tmp, "intellectual property rights.", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == GPL) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "This is free software; you can redistribute it and/or", 0); + COMMENT(¬ice, &buf, "modify it under the terms of the GNU General Public License", 0); + COMMENT(¬ice, &buf, "as published by the Free Software Foundation;", 0); + COMMENT(¬ice, &buf, "either version 2, or (at your option) any later version.", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "This software is distributed in the hope that it", 0); + COMMENT(¬ice, &buf, "will be useful, but WITHOUT ANY WARRANTY;", 0); + COMMENT(¬ice, &buf, "without even the implied warranty of MERCHANTABILITY", 0); + COMMENT(¬ice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.", 0); + COMMENT(¬ice, &buf, "See the GNU General Public License for more details.", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "You should have received a copy of the", 0); + COMMENT(¬ice, &buf, "GNU General Public License", 0); + COMMENT(¬ice, &buf, "along with this software (see the file COPYING.)", 0); + COMMENT(¬ice, &buf, "If not, a copy is available at", 0); + COMMENT(¬ice, &buf, "http://www.gnu.org/copyleft/gpl.html", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == BSD) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "Redistribution and use in source and binary forms, with or", -1); + COMMENT(¬ice, &buf, "without modification, are permitted provided that the following", -1); + COMMENT(¬ice, &buf, "conditions are met:", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 1. Redistributions of source code must retain the above", -1); + COMMENT(¬ice, &buf, " copyright notice, this list of conditions and the", -1); + COMMENT(¬ice, &buf, " following disclaimer.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 2. Redistributions in binary form must reproduce the above", -1); + COMMENT(¬ice, &buf, " copyright notice, this list of conditions and the", -1); + COMMENT(¬ice, &buf, " following disclaimer in the documentation and/or other", -1); + COMMENT(¬ice, &buf, " materials provided with the distribution.", -1); + comment(¬ice, &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(¬ice, &tmp, ¬ice.item[i]); + else + copy(&tmp, "the copyright holder", -1); + copy(&tmp, " nor the", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), -1); + COMMENT(¬ice, &buf, " names of its contributors may be used to endorse or", -1); + COMMENT(¬ice, &buf, " promote products derived from this software without", -1); + COMMENT(¬ice, &buf, " specific prior written permission.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND", -1); + COMMENT(¬ice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,", -1); + COMMENT(¬ice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF", -1); + COMMENT(¬ice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE", -1); + COMMENT(¬ice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS", -1); + COMMENT(¬ice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,", -1); + COMMENT(¬ice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED", -1); + COMMENT(¬ice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,", -1); + COMMENT(¬ice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON", -1); + COMMENT(¬ice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,", -1); + COMMENT(¬ice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY", -1); + COMMENT(¬ice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE", -1); + COMMENT(¬ice, &buf, "POSSIBILITY OF SUCH DAMAGE.", -1); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == ZLIB) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "This software is provided 'as-is', without any express or implied", -1); + COMMENT(¬ice, &buf, "warranty. In no event will the authors be held liable for any", -1); + COMMENT(¬ice, &buf, "damages arising from the use of this software.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "Permission is granted to anyone to use this software for any", -1); + COMMENT(¬ice, &buf, "purpose, including commercial applications, and to alter it and", -1); + COMMENT(¬ice, &buf, "redistribute it freely, subject to the following restrictions:", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 1. The origin of this software must not be misrepresented;", -1); + COMMENT(¬ice, &buf, " you must not claim that you wrote the original software. If", -1); + COMMENT(¬ice, &buf, " you use this software in a product, an acknowledgment in the", -1); + COMMENT(¬ice, &buf, " product documentation would be appreciated but is not", -1); + COMMENT(¬ice, &buf, " required.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 2. Altered source versions must be plainly marked as such,", -1); + COMMENT(¬ice, &buf, " and must not be misrepresented as being the original", -1); + COMMENT(¬ice, &buf, " software.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 3. This notice may not be removed or altered from any source", -1); + COMMENT(¬ice, &buf, " distribution.", -1); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == MIT) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "Permission is hereby granted, free of charge, to any person", 0); + COMMENT(¬ice, &buf, "obtaining a copy of this software and associated", 0); + COMMENT(¬ice, &buf, "documentation files (the \"Software\"), to deal in the", 0); + COMMENT(¬ice, &buf, "Software without restriction, including without limitation", 0); + COMMENT(¬ice, &buf, "the rights to use, copy, modify, merge, publish, distribute,", 0); + COMMENT(¬ice, &buf, "sublicense, and/or sell copies of the Software, and to", 0); + COMMENT(¬ice, &buf, "permit persons to whom the Software is furnished to do so,", 0); + COMMENT(¬ice, &buf, "subject to the following conditions:", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "The above copyright notice and this permission notice shall", 0); + COMMENT(¬ice, &buf, "be included in all copies or substantial portions of the", 0); + COMMENT(¬ice, &buf, "Software.", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY", 0); + COMMENT(¬ice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE", 0); + COMMENT(¬ice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR", 0); + COMMENT(¬ice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS", 0); + COMMENT(¬ice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR", 0); + COMMENT(¬ice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR", 0); + COMMENT(¬ice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE", 0); + COMMENT(¬ice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", 0); + comment(¬ice, &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(¬ice, &tmp, ¬ice.item[i]); + copy(&tmp, " - ", -1); + } + else + i = -1; + copy(&tmp, "Proprietary", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + comment(¬ice, &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(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[PARENT]); + copy(&tmp, " ", -1); + } + if (notice.item[CORPORATION].data) + { + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + } + else if (notice.item[COMPANY].data) + { + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + } + } + else + { + copy(&tmp, "This is unpublished proprietary source code", -1); + if (i >= 0) + copy(&tmp, " of", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data) + expand(¬ice, &tmp, ¬ice.item[i]); + if (notice.item[COMPANY].data) + { + if (SIZ(&tmp)) + PUT(&tmp, ' '); + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + } + if (SIZ(&tmp)) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + COMMENT(¬ice, &buf, "and is not to be disclosed or used except in", 1); + COMMENT(¬ice, &buf, "accordance with applicable agreements", 1); + } + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == NONEXCLUSIVE) + { + COMMENT(¬ice, &buf, "For nonexclusive individual use", 1); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == NONCOMMERCIAL) + { + COMMENT(¬ice, &buf, "For noncommercial use", 1); + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.type >= PROPRIETARY && !notice.item[URL].data) + { + COMMENT(¬ice, &buf, "Unpublished & Not for Publication", 0); + comment(¬ice, &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(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + else + PUT(&tmp, ' '); + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[PARENT]); + copy(&tmp, " ", -1); + } + if (notice.item[CORPORATION].data) + { + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + if (notice.item[INCORPORATION].data) + { + copy(&tmp, " ", -1); + expand(¬ice, &tmp, ¬ice.item[INCORPORATION]); + } + } + else if (notice.item[COMPANY].data) + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + } + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + COMMENT(¬ice, &buf, "under the terms and conditions of the license in", 0); + expand(¬ice, &tmp, ¬ice.item[URL]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[URLMD5].data) + { + copy(&tmp, "(with an md5 checksum of ", -1); + expand(¬ice, &tmp, ¬ice.item[URLMD5]); + copy(&tmp, ")", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == PROPRIETARY) + { + COMMENT(¬ice, &buf, "The copyright notice above does not evidence any", 0); + COMMENT(¬ice, &buf, "actual or intended publication of such source code", 0); + comment(¬ice, &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(¬ice, &tmp, &item); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), h); + } while (v++ < x); + if (item.size) + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.item[ORGANIZATION].data) + { + expand(¬ice, &tmp, ¬ice.item[ORGANIZATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data) + expand(¬ice, &tmp, ¬ice.item[i]); + if (notice.item[COMPANY].data) + { + if (SIZ(&tmp)) + PUT(&tmp, ' '); + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + } + if (SIZ(&tmp)) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[LOCATION].data) + { + expand(¬ice, &tmp, ¬ice.item[LOCATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &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(¬ice, &buf, ¬ice.id[i].value); + PUT(&buf, ']'); + } + else + { + if (k < 0) + { + COMMENT(¬ice, &buf, "CONTRIBUTORS", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + k = 1; + expand(¬ice, &tmp, ¬ice.id[i].value); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + if (!q) + break; + } + if (q) + break; + if (!h) + { + if (notice.type == USAGE) + { + copy(&buf, "[-author?", -1); + expand(¬ice, &buf, &item); + PUT(&buf, ']'); + } + else + { + if (k < 0) + { + COMMENT(¬ice, &buf, "CONTRIBUTORS", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + k = 1; + expand(¬ice, &tmp, &item); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + } + } + if (k > 0) + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.type == USAGE) + { + copy(&buf, "[-copyright?", -1); + copyright(¬ice, &buf); + PUT(&buf, ']'); + if (notice.item[URL].data) + { + copy(&buf, "[-license?", -1); + expand(¬ice, &buf, ¬ice.item[URL]); + PUT(&buf, ']'); + } + PUT(&buf, '\n'); + } + else + comment(¬ice, &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; +} |