troffcvt-1.04.orig/ 40775 1750 1750 0 6431756061 12004 5ustar blpblptroffcvt-1.04.orig/tarballs/ 40775 1750 1750 0 6431756103 13605 5ustar blpblptroffcvt-1.04.orig/tarballs/MemMgr-1.04.tar100644 1750 1750 214000 6431756100 16206 0ustar blpblpmemmgr-1.04/004077500017710000151000000000000634123112700144505ustar00junkyarddatamgmt00000400000027memmgr-1.04/Makefile010066400017710000151000000341040634123112200161020ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 10 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = Memory Management Library PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = $(LOADERLIBPREFIX)$(TOP)/libmemmgr.a DEPMEMMGRLIB = $(TOP)/libmemmgr.a NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # Memory Allocation Library Imakefile # Use "make World" to build the distribution. But before you do that, # look at the files in the config subdirectory to see if you want # to change anything. # Requires the WRPRC2 imake configuration files. DEFINES = $(ALLOC_DEFINES) LIBSRCS = \ alloc.c \ allocnp.c \ stralloc.c \ strallocnp.c \ realloc.c \ reallocnp.c \ valloc.c \ vallocnp.c \ free.c LIBOBJS = \ alloc.o \ allocnp.o \ stralloc.o \ strallocnp.o \ realloc.o \ reallocnp.o \ valloc.o \ vallocnp.o \ free.o MZSRCS = malloc0.c MZOBJS = malloc0.o SRCS = $(LIBSRCS) $(MZSRCS) .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libmemmgr.a libmemmgr.a: $(LIBOBJS) $(RM) $@ $(AR) $@ $(LIBOBJS) clean:: $(RM) libmemmgr.a lint:: lint.libmemmgr.a lint.libmemmgr.a: $(LINT) $(LINTFLAGS) $(LIBSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.libmemmgr.a"' to "lint sources for libmemmgr.a help_aux:: @echo "'make "libmemmgr.a"' to "build the libmemmgr.a library install:: i.libmemmgr.a help_aux:: @echo "'make "i.libmemmgr.a"' to "install libmemmgr.a i.libmemmgr.a:: libmemmgr.a @if [ -d $(LOCALUSRLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALUSRLIBDIR)); fi $(INSTALL) $(INSTLIBFLAGS) libmemmgr.a $(LOCALUSRLIBDIR)/libmemmgr.a lintlib:: llib-lmemmgr.ln llib-lmemmgr.ln:: $(LIBSRCS) $(RM) $@ $(LINT) $(LINTLIBFLAG)memmgr $(LINTFLAGS) $(LIBSRCS) clean:: $(RM) llib-lmemmgr.ln help_aux:: @echo "'make "llib-lmemmgr.ln"' to "build the llib-lmemmgr.ln lint library install.lint:: i.llib-lmemmgr.ln help_aux:: @echo "'make "i.llib-lmemmgr.ln"' to "install llib-lmemmgr.ln i.llib-lmemmgr.ln:: llib-lmemmgr.ln @if [ -d $(LOCALLINTLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALLINTLIBDIR)); fi $(INSTALL) $(INSTLIBFLAGS) llib-lmemmgr.ln $(LOCALLINTLIBDIR)/llib-lmemmgr.ln install:: i.memmgr.h help_aux:: @echo "'make "i.memmgr.h"' to "install memmgr.h i.memmgr.h:: memmgr.h @if [ -d $(LOCALINCLUDEROOT) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALINCLUDEROOT)); fi $(INSTALL) $(INSTINCFLAGS) memmgr.h $(LOCALINCLUDEROOT)/memmgr.h all:: malloc0 help_aux:: @echo "'make "malloc0"' to "build malloc0 malloc0: $(MZOBJS) $(DEPMZLIBS) $(RM) $@ $(CC) -o $@ $(MZOBJS) $(LDOPTS) $(MZLIBS) $(EXTRA_LDLIBS) clean:: $(RM) malloc0 lint:: lint.malloc0 lint.malloc0: $(LINT) $(LINTFLAGS) $(MZSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.malloc0"' to "lint sources for malloc0 install:: i.malloc0 i.malloc0:: @echo malloc0 is not installed anywhere. depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) all:: World:: @echo "Building "$(PROJECTNAME)", Release "$(PROJECTRELEASE) @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean $(MAKE) $(MFLAGS) depend $(MAKE) $(MFLAGS) all @echo "" @date @echo "" @echo "Done building "$(PROJECTNAME) help_aux:: @echo "'make "World"' to "build the entire $(PROJECTNAME) distribution # documentation memmgr.ps:: memmgr.ms $(SOELIM) memmgr.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > memmgr.ps clean:: $(RM) memmgr.ps help_aux:: @echo "'make "memmgr.ps"' to "format memmgr.ps in PostScript # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE alloc.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h alloc.o: /usr/local/include/etm.h memmgr.internal.h memmgr.h allocnp.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h allocnp.o: memmgr.internal.h memmgr.h stralloc.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h stralloc.o: /usr/local/include/etm.h memmgr.internal.h memmgr.h strallocnp.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h strallocnp.o: memmgr.internal.h memmgr.h realloc.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h realloc.o: /usr/local/include/etm.h memmgr.internal.h memmgr.h reallocnp.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h reallocnp.o: memmgr.internal.h memmgr.h valloc.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h valloc.o: /usr/local/include/etm.h memmgr.internal.h memmgr.h vallocnp.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h vallocnp.o: memmgr.internal.h memmgr.h free.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h free.o: memmgr.internal.h memmgr.h malloc0.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h malloc0.o: memmgr.internal.h memmgr.h = -I. PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) memmgr-1.04/Imakefile010064400017710000151000000022410621410363700162560ustar00junkyarddatamgmt00000400000027XCOMM Memory Allocation Library Imakefile XCOMM Use "make World" to build the distribution. But before you do that, XCOMM look at the files in the config subdirectory to see if you want XCOMM to change anything. XCOMM Requires the WRPRC2 imake configuration files. #if Malloc0ReturnsNull ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL #endif DEFINES = $(ALLOC_DEFINES) LIBSRCS = \ alloc.c \ allocnp.c \ stralloc.c \ strallocnp.c \ realloc.c \ reallocnp.c \ valloc.c \ vallocnp.c \ free.c LIBOBJS = \ alloc.o \ allocnp.o \ stralloc.o \ strallocnp.o \ realloc.o \ reallocnp.o \ valloc.o \ vallocnp.o \ free.o MZSRCS = malloc0.c MZOBJS = malloc0.o SRCS = $(LIBSRCS) $(MZSRCS) NormalLibraryObjectRule() BuildNormalLibrary(memmgr,$(LIBSRCS),$(LIBOBJS)) InstallLibrary(memmgr,$(LOCALUSRLIBDIR)) BuildLintLibrary(memmgr,$(LIBSRCS)) InstallLintLibrary(memmgr,$(LOCALLINTLIBDIR)) InstallIncludeFile (memmgr.h,$(LOCALINCLUDEROOT)) BuildProgram(malloc0,$(MZSRCS),$(MZOBJS),$(MZLIBS),$(DEPMZLIBS)) FakeInstallFile(malloc0) DependTarget() SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) XCOMM documentation TroffMsToPostScript(memmgr.ps,memmgr.ms,NullArg,NullArg) memmgr-1.04/memmgr.h010064400017710000151000000013300625157622300161060ustar00junkyarddatamgmt00000400000027/* * memmgr.h - memory management library header file */ #ifndef _MEMMGR_H #define _MEMMGR_H /* * These defines cause failure at link time if this header * file wasn't included in each source file using MemMgr * functions. */ # define AllocNP AllocNP_ # define Alloc Alloc_ # define StrAllocNP StrAllocNP_ # define StrAlloc StrAlloc_ # define VAllocNP VAllocNP_ # define VAlloc VAlloc_ # define ReallocNP ReallocNP_ # define Realloc Realloc_ # define Free Free_ extern char *AllocNP (); extern char *Alloc (); extern char *StrAlloc (); extern char *StrAllocNP (); extern char *VAllocNP (); extern char *VAlloc (); extern char *Realloc (); extern char *ReallocNP (); extern void Free (); #endif /* _MEMMGR_H */ memmgr-1.04/README010064400017710000151000000013630616203017600153300ustar00junkyarddatamgmt00000400000027This directory contains source and documentation for the MemMgr memory management library. You need the Exception and Termination Manager (ETM) distribution to use MemMgr. If you use the Imakefile, you must obtain the WRPRC Release 2 imake configuration files. If you just use the Makefile you will have to edit some of the variable definitions. Use "make -n" and "make -n install" to see what will happen on your machine first! The document memmgr.ms is formatted with the -ms macros. The ETM and WRPRC2 configuration distributions are available via anonymous ftp to host ftp.primate.wisc.edu under ~ftp/pub. 16 Oct 91 Paul DuBois dubois@primate.wisc.edu 16 Oct 91 Release 1.00 20 Oct 91 Release 1.01 25 Oct 91 Release 1.02 01 Sep 93 Release 1.03 onfiguration files. If you just use the Makefile you will have to edit some of the variable definitions. Use "make -n" and "make -n install" to see what will happen on your machine first! The document memmgr.ms is formatted with the -ms macros. The ETM and WRPRC2 comemmgr-1.04/config/004077500017710000151000000000000621410740100157115ustar00junkyarddatamgmt00000400000027memmgr-1.04/config/Imake.p-params010064400017710000151000000012570634123076700204160ustar00junkyarddatamgmt00000400000027#ifndef ProjectName #define ProjectName Memory Management Library #endif #ifndef ProjectMajorRelease #define ProjectMajorRelease 1 #endif #ifndef ProjectMinorRelease #define ProjectMinorRelease 04 #endif /* * Override default values of MemMgrLib/DepMemMgrLib, since they refer * to the already-installed library. */ #ifndef MemMgrLib #define MemMgrLib $(LOADERLIBPREFIX)$(TOP)/libmemmgr.a #endif #ifndef DepMemMgrLib #define DepMemMgrLib $(TOP)/libmemmgr.a #endif #ifndef ProjectIncludes #define ProjectIncludes -I. #endif /* * Override as YES in a project-specific vendor file if malloc(0) returns * NULL. */ #ifndef Malloc0ReturnsNull #define Malloc0ReturnsNull NO #endif memmgr-1.04/memmgr.ms010064400017710000151000000120700616203017600162720ustar00junkyarddatamgmt00000400000027.\" .\" xroff -ms % | lpr .\" .\" revision date - change whenever this file is edited .ds RD 25 October 1991 .nr PO 1.2i \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance .\" .EH 'Memory Manager Library'- % -'' .OH ''- % -'Memory Manager Library' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .\" I - italic font (taken from -ms and changed) .de I .nr PQ \\n(.f .if t \&\\$3\\f2\\$1\\fP\&\\$2 .if n .if \\n(.$=1 \&\\$1 .if n .if \\n(.$>1 \&\\$1\c .if n .if \\n(.$>1 \&\\$2 .. .de IS \" interface routine description header start .DS L .ta .8i .ft B .. .de IE \" interface routine description header end .DE .ft R .. .TL MemMgr \*- A Simple Memory Management Library .sp .5v .ps -2 Release 1.02 .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Revision date:\0\0\*(RD .NH Introduction .LP .I MemMgr is a fairly trivial memory management library. There is little it does that cannot be done using routines in the C library. (In fact, allocation and disposal is implemented using C library routines.) The purposes of .I MemMgr are two-fold. .IP (i) Minimize configuration burden on applications that dynamically allocate memory. For instance, .I malloc() on some systems returns a .I char pointer; on others it returns a .I void pointer. The .I MemMgr library routines encapsulate system-specific configuration differences and exports a fixed interface which is system-independent. Once you compile and install it, you just use it without thinking about whether your UNIX is System V or BSD inspired. .IP (ii) Provide two parallel sets of allocation routines which either return NULL (for applications which want to check) or panic (for applications which simply want to die) on allocation failures. Panicking is implemented using the ETM library, which introduces a dependency on the ETM distribution. So be it. I use ETM for all my programs anyway. .NH Installation .LP This release of .I MemMgr is configured using .I imake and the standard WRPRC multiple-project configuration files, so you also need to obtain the WRPRC configuration distribution (version 1.03 or higher) if you want to build it the usual way. (If you want to avoid .I imake , the .I Makefile is simple enough that you should be able to tweak it by hand.) .LP You also need to obtain and install the Exception/Termination Manager (ETM) library to build this distribution. .LP If you are using .I imake , take a look at the files in the .I config directory and change things if you want. Then build the distribution with ``make World'' or: .LP .DS make Bootstrap make depend make make install .DE .NH Programming Interface .LP Source files for applications using .I MemMgr routines should include .I memmgr.h . .LP Applications using .I MemMgr should be linked with .I "\-lmemmgr \-letm" . .IS char *AllocNP (size) int size; .IE Allocate .I size bytes of memory and return a pointer to it, or NULL if insufficient memory is available. The memory is not guaranteed to be zeroed. .IS char *Alloc (size) int size; .IE Like .I Alloc() , but panics if insuffient memory is available. .IS char *StrAllocNP (s) char *s; .IE Allocates space for the string pointed to by .I s (including a null byte at the end), copies the string into it, and returns a pointer to the copy. Returns NULL if .I s is NULL or insufficient memory is available. .IS char *StrAlloc (s) char *s; .IE Like .I StrAllocNP() , but panics if .I s is NULL or insuffient memory is available. .IS char *VAllocNP (count, size) int count, size; .IE Allocate .I count objects of .I size bytes of memory and return a pointer to it, or NULL if insufficient memory is available. The memory is not guaranteed to be zeroed. .IS char *VAlloc (count, size) int count, size; .IE Like .I VAlloc() , but panics if insuffient memory is available. .IS char *ReallocNP (p, size) char *p; int size; .IE Reallocate the block of memory pointed to by .I p to be .I size bytes long, free .I p and return a pointer to the new block. .I p should have been allocated by one of the other .I MemMgr routines. Returns NULL if insufficient memory is available; in this case the block pointed to by .I p is .B not freed. Also returns NULL if .I p is NULL. .IS char *Realloc (p, size) char *p; int size; .IE Like .I Realloc() , but panics if .I p is NULL or insuffient memory is available. .IS void Free (p) char *p; .IE Frees the chunk of memory pointed to by .I p ; the memory should have been allocated by one of the other .I MemMgr routines, with the exception that it is safe to pass NULL to .I Free() . .NH Distribution and Update Availability .LP The .I MemMgr distribution may be freely circulated and is available for anonymous FTP access under the .I ~ftp/pub directory on host .I ftp.primate.wisc.edu . Updates appear there as they become available. .LP The ETM and WRPRC configuration distributions are available on .I ftp.primate.wisc.edu as well. .LP If you do not have FTP access, send requests to the address .I software@primate.wisc.edu . Bug reports, questions, suggestions and comments may be sent to this address as well. memmgr-1.04/memmgr.internal.h010064400017710000151000000011450625157630500177260ustar00junkyarddatamgmt00000400000027#ifndef _MEMMGR_INTERNAL_H #define _MEMMGR_INTERNAL_H extern char *strcpy (); # if defined(__STDC__) || defined(THINK_C) # include # define allocPtrType void # define allocSizeType size_t # else /* !THINK_C */ # ifdef SYSV # include # define allocPtrType void # define allocSizeType size_t # else /* !SYSV */ # define allocPtrType char # define allocSizeType unsigned extern allocPtrType *calloc (); extern allocPtrType *malloc (); extern allocPtrType *realloc (); # endif /* SYSV */ # endif /* THINK_C */ #ifndef allocSiz #define allocSiz 1024 #endif #endif /* _MEMMGR_INTERNAL_H */ memmgr-1.04/Changes-1.01010064400017710000151000000001740616203017600163170ustar00junkyarddatamgmt00000400000027Changes to MemMgr distribution for release 1.01. Fixed bug in ReallocNP() - it was freeing memory it shouldn't have been. memmgr-1.04/valloc.c010064400017710000151000000004430616203017600160720ustar00junkyarddatamgmt00000400000027/* Panic version of VAllocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *VAlloc (count, size) int count, size; { char *p; if ((p = VAllocNP (count, size)) == (char *) NULL) ETMPanic ("VAlloc: out of memory"); return (p); } memmgr-1.04/vallocnp.c010064400017710000151000000005140616203017600164270ustar00junkyarddatamgmt00000400000027/* Allocate a piece of memory to hold "count" elements of size "size", and return a pointer to it, or NULL if insufficient memory is available. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *VAllocNP (count, size) int count, size; { return ((char *) calloc (count, (allocSizeType) size)); } memmgr-1.04/alloc.c010064400017710000151000000004120616203017600157000ustar00junkyarddatamgmt00000400000027/* Panic version of AllocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *Alloc (size) int size; { char *p; if ((p = AllocNP (size)) == (char *) NULL) ETMPanic ("Alloc: out of memory"); return (p); } memmgr-1.04/allocnp.c010064400017710000151000000004710621410367600162470ustar00junkyarddatamgmt00000400000027/* Allocate a piece of memory and return a pointer to it, or NULL if insufficient memory is available. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *AllocNP (size) int size; { #ifdef MALLOC_0_RETURNS_NULL ++size; #endif return ((char *) malloc ((allocSizeType) size)); } memmgr-1.04/stralloc.c010064400017710000151000000005360616203017700164410ustar00junkyarddatamgmt00000400000027/* Panic version of StrAllocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *StrAlloc (s) char *s; { char *p; if (s == (char *) NULL) ETMPanic ("StrAlloc: trying to copy null pointer"); if ((p = StrAllocNP (s)) == (char *) NULL) ETMPanic ("StrAlloc: out of memory"); return (p); } memmgr-1.04/strallocnp.c010064400017710000151000000006270616203017700170000ustar00junkyarddatamgmt00000400000027/* Allocate space for a string, copy the string into it, and return a pointer to the copy, or NULL if couldn't get the memory. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *StrAllocNP (s) char *s; { char *p; if (s == (char *) NULL) return ((char *) NULL); if ((p = AllocNP (strlen (s) + 1)) == (char *) NULL) return ((char *) NULL); return (strcpy (p, s)); } memmgr-1.04/realloc.c010064400017710000151000000005260616203017700162360ustar00junkyarddatamgmt00000400000027/* Panic version of ReallocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *Realloc (p, size) char *p; int size; { if (p == (char *) NULL) ETMPanic ("Realloc: null pointer"); if ((p = ReallocNP (p, size)) == (char *) NULL) ETMPanic ("Realloc: out of memory"); return (p); } memmgr-1.04/reallocnp.c010064400017710000151000000007170616203017700165760ustar00junkyarddatamgmt00000400000027/* Reallocate p to size, free old memory and return pointer to new. If can't allocate the memory, returns NULL, and the old memory is NOT freed. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *ReallocNP (p, size) char *p; int size; { char *s; if (p == (char *) NULL) return ((char *) NULL); if ((s = (char *) realloc (p, size)) == (char *) NULL) return ((char *) NULL); /*Free (p);*/ /* <- whoops! */ return (s); } memmgr-1.04/free.c010064400017710000151000000004270616203020000155210ustar00junkyarddatamgmt00000400000027/* Free a hunk of memory returned by one of the other MemMgr routines. It's safe to pass NULL to this routine. */ # include # include "memmgr.internal.h" # include "memmgr.h" void Free (p) char *p; { if (p != (char *) NULL) (void) free ((allocPtrType *) p); } memmgr-1.04/Changes-1.02010064400017710000151000000001640616203020000163030ustar00junkyarddatamgmt00000400000027Changes to MemMgr distribution for release 1.02. Added Valloc() and VAllocNP() for allocating vectors of objects. memmgr-1.04/junk2010066400017710000151000000577770616203020000154360ustar00junkyarddatamgmt00000400000027:::::::::::::: Changes-1.01 :::::::::::::: Changes to MemMgr distribution for release 1.01. Fixed bug in ReallocNP() - it was freeing memory it shouldn't have been. :::::::::::::: Changes-1.02 :::::::::::::: Changes to MemMgr distribution for release 1.02. Added Valloc() and VAllocNP() for allocating vectors of objects. :::::::::::::: Changes-1.03 :::::::::::::: Changes to MemMgr distribution for release 1.03. Now configured with WRPRC2 imake configuration files. Most important code change: All functions are #define'd as "# define f f_" in memmgr.h. This causes failure at link time if memmgr.h wasn't included everywhere it should have been. This can help a lot on compilers such as THINK C. It means, however, that libraries that use MemMgr should be recompiled and reinstalled, or programs using those libraries will get "undefined symbol" errors for MemMgr function names. memmgr.h now idempotent; may be included more than once safely. :::::::::::::: Imakefile :::::::::::::: XCOMM Memory Allocation Library Imakefile XCOMM Use "make World" to build the distribution. But before you do that, XCOMM look at the files in the config subdirectory to see if you want XCOMM to change anything. XCOMM Requires the WRPRC2 imake configuration files. SRCS = \ alloc.c \ allocnp.c \ stralloc.c \ strallocnp.c \ realloc.c \ reallocnp.c \ valloc.c \ vallocnp.c \ free.c OBJS = \ alloc.o \ allocnp.o \ stralloc.o \ strallocnp.o \ realloc.o \ reallocnp.o \ valloc.o \ vallocnp.o \ free.o NormalLibraryObjectRule() BuildNormalLibrary(memmgr,$(SRCS),$(OBJS)) InstallLibrary(memmgr,$(LOCALUSRLIBDIR)) BuildLintLibrary(memmgr,$(SRCS)) InstallLintLibrary(memmgr,$(LOCALLINTLIBDIR)) InstallIncludeFile (memmgr.h,$(LOCALINCLUDEROOT)) DependTarget() SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) XCOMM documentation TroffMsToPostScript(memmgr.ps,memmgr.ms,NullArg,NullArg) :::::::::::::: Makefile :::::::::::::: # Makefile generated by imake - do not edit! # $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $ # # The cpp used on this machine replaces all newlines and multiple tabs and # spaces in a macro expansion with a single space. Imake tries to compensate # for this, but is not always successful. # # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 93/06/30 # operating system: SunOS 4.1.1 # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 04 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = $(USRLIBDIR)/config # Project identfication - name and release level PROJECTNAME = Memory Management Library PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 03 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/local USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp LOCALROOTDIR = /usr/local LOCALBINDIR = /usr/local LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MANLSUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar clq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -C LINTOPTS = -axz LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RANLIB = ranlib RANLIBINSTFLAGS = RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = STD_LDLIBS = STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(STD_LDLIBS) $(PROJECT_LDLIBS) $(LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = install INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = $(LOADERLIBPREFIX)$(TOP)/libmemmgr.a DEPMEMMGRLIB = $(TOP)/libmemmgr.a NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TSLIB = -ltokenscan DEPTSLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # Memory Allocation Library Imakefile # Use "make World" to build the distribution. But before you do that, # look at the files in the config subdirectory to see if you want # to change anything. # Requires the WRPRC2 imake configuration files. SRCS = \ alloc.c \ allocnp.c \ stralloc.c \ strallocnp.c \ realloc.c \ reallocnp.c \ valloc.c \ vallocnp.c \ free.c OBJS = \ alloc.o \ allocnp.o \ stralloc.o \ strallocnp.o \ realloc.o \ reallocnp.o \ valloc.o \ vallocnp.o \ free.o .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libmemmgr.a libmemmgr.a: $(OBJS) $(RM) $@ $(AR) $@ $(OBJS) $(RANLIB) $@ clean:: $(RM) libmemmgr.a lint:: lint.libmemmgr.a lint.libmemmgr.a: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) install:: i.libmemmgr.a i.libmemmgr.a:: libmemmgr.a @if [ -d $(LOCALUSRLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALUSRLIBDIR)); fi $(INSTALL) -c $(INSTLIBFLAGS) libmemmgr.a $(LOCALUSRLIBDIR)/libmemmgr.a $(RANLIB) $(LOCALUSRLIBDIR)/libmemmgr.a lintlib:: llib-lmemmgr.ln llib-lmemmgr.ln:: $(SRCS) $(RM) $@ $(LINT) $(LINTLIBFLAG)memmgr $(LINTFLAGS) $(SRCS) clean:: $(RM) llib-lmemmgr.ln install.lint:: i.llib-lmemmgr.ln i.llib-lmemmgr.ln:: llib-lmemmgr.ln @if [ -d $(LOCALLINTLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALLINTLIBDIR)); fi $(INSTALL) -c $(INSTLIBFLAGS) llib-lmemmgr.ln $(LOCALLINTLIBDIR)/llib-lmemmgr.ln install:: i.memmgr.h i.memmgr.h:: memmgr.h @if [ -d $(LOCALINCLUDEROOT) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALINCLUDEROOT)); fi $(INSTALL) -c $(INSTINCFLAGS) memmgr.h $(LOCALINCLUDEROOT)/memmgr.h depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) all:: World:: @echo "Building "$(PROJECTNAME)", Release "$(PROJECTRELEASE) @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean $(MAKE) $(MFLAGS) depend $(MAKE) $(MFLAGS) all @echo "" @date @echo "" @echo "Done building "$(PROJECTNAME) # documentation memmgr.ps:: memmgr.ms $(SOELIM) memmgr.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > memmgr.ps clean:: $(RM) memmgr.ps # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE alloc.o: /usr/include/stdio.h /usr/local/include/etm.h memmgr.internal.h alloc.o: memmgr.h allocnp.o: /usr/include/stdio.h memmgr.internal.h memmgr.h stralloc.o: /usr/include/stdio.h /usr/local/include/etm.h memmgr.internal.h stralloc.o: memmgr.h strallocnp.o: /usr/include/stdio.h memmgr.internal.h memmgr.h realloc.o: /usr/include/stdio.h /usr/local/include/etm.h memmgr.internal.h realloc.o: memmgr.h reallocnp.o: /usr/include/stdio.h memmgr.internal.h memmgr.h valloc.o: /usr/include/stdio.h /usr/local/include/etm.h memmgr.internal.h valloc.o: memmgr.h vallocnp.o: /usr/include/stdio.h memmgr.internal.h memmgr.h free.o: /usr/include/stdio.h memmgr.internal.h memmgr.h :::::::::::::: README :::::::::::::: This directory contains source and documentation for the MemMgr memory management library. You need the Exception and Termination Manager (ETM) distribution to use MemMgr. If you use the Imakefile, you must obtain the WRPRC Release 2 imake configuration files. If you just use the Makefile you will have to edit some of the variable definitions. Use "make -n" and "make -n install" to see what will happen on your machine first! The document memmgr.ms is formatted with the -ms macros. The ETM and WRPRC2 configuration distributions are available via anonymous ftp to host ftp.primate.wisc.edu under ~ftp/pub. 16 Oct 91 Paul DuBois dubois@primate.wisc.edu 16 Oct 91 Release 1.00 20 Oct 91 Release 1.01 25 Oct 91 Release 1.02 01 Sep 93 Release 1.03 :::::::::::::: alloc.c :::::::::::::: /* Panic version of AllocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *Alloc (size) int size; { char *p; if ((p = AllocNP (size)) == (char *) NULL) ETMPanic ("Alloc: out of memory"); return (p); } :::::::::::::: allocnp.c :::::::::::::: /* Allocate a piece of memory and return a pointer to it, or NULL if insufficient memory is available. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *AllocNP (size) int size; { return ((char *) malloc ((allocSizeType) size)); } :::::::::::::: free.c :::::::::::::: /* Free a hunk of memory returned by one of the other MemMgr routines. It's safe to pass NULL to this routine. */ # include # include "memmgr.internal.h" # include "memmgr.h" void Free (p) char *p; { if (p != (char *) NULL) (void) free ((allocPtrType *) p); } :::::::::::::: memmgr.h :::::::::::::: /* memmgr.h - memory management library header file */ /* These defines cause failure at link time if this header file wasn't included in each source file using MemMgr functions. */ # define AllocNP AllocNP_ # define Alloc Alloc_ # define StrAllocNP StrAllocNP_ # define StrAlloc StrAlloc_ # define VAllocNP VAllocNP_ # define VAlloc VAlloc_ # define ReallocNP ReallocNP_ # define Realloc Realloc_ # define Free Free_ extern char *AllocNP (); extern char *Alloc (); extern char *StrAlloc (); extern char *StrAllocNP (); extern char *VAllocNP (); extern char *VAlloc (); extern char *Realloc (); extern char *ReallocNP (); extern void Free (); :::::::::::::: memmgr.internal.h :::::::::::::: extern char *strcpy (); # if defined(__STDC__) || defined(THINK_C) # include # define allocPtrType void # define allocSizeType size_t # else /* !THINK_C */ # ifdef SYSV # include # define allocPtrType void # define allocSizeType size_t # else /* !SYSV */ # define allocPtrType char # define allocSizeType unsigned extern allocPtrType *calloc (); extern allocPtrType *malloc (); extern allocPtrType *realloc (); # endif /* SYSV */ # endif /* THINK_C */ # define allocSiz 1024 :::::::::::::: memmgr.ms :::::::::::::: .\" .\" xroff -ms % | lpr .\" .\" revision date - change whenever this file is edited .ds RD 25 October 1991 .nr PO 1.2i \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance .\" .EH 'Memory Manager Library'- % -'' .OH ''- % -'Memory Manager Library' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .\" I - italic font (taken from -ms and changed) .de I .nr PQ \\n(.f .if t \&\\$3\\f2\\$1\\fP\&\\$2 .if n .if \\n(.$=1 \&\\$1 .if n .if \\n(.$>1 \&\\$1\c .if n .if \\n(.$>1 \&\\$2 .. .de IS \" interface routine description header start .DS L .ta .8i .ft B .. .de IE \" interface routine description header end .DE .ft R .. .TL MemMgr \*- A Simple Memory Management Library .sp .5v .ps -2 Release 1.02 .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Revision date:\0\0\*(RD .NH Introduction .LP .I MemMgr is a fairly trivial memory management library. There is little it does that cannot be done using routines in the C library. (In fact, allocation and disposal is implemented using C library routines.) The purposes of .I MemMgr are two-fold. .IP (i) Minimize configuration burden on applications that dynamically allocate memory. For instance, .I malloc() on some systems returns a .I char pointer; on others it returns a .I void pointer. The .I MemMgr library routines encapsulate system-specific configuration differences and exports a fixed interface which is system-independent. Once you compile and install it, you just use it without thinking about whether your UNIX is System V or BSD inspired. .IP (ii) Provide two parallel sets of allocation routines which either return NULL (for applications which want to check) or panic (for applications which simply want to die) on allocation failures. Panicking is implemented using the ETM library, which introduces a dependency on the ETM distribution. So be it. I use ETM for all my programs anyway. .NH Installation .LP This release of .I MemMgr is configured using .I imake and the standard WRPRC multiple-project configuration files, so you also need to obtain the WRPRC configuration distribution (version 1.03 or higher) if you want to build it the usual way. (If you want to avoid .I imake , the .I Makefile is simple enough that you should be able to tweak it by hand.) .LP You also need to obtain and install the Exception/Termination Manager (ETM) library to build this distribution. .LP If you are using .I imake , take a look at the files in the .I config directory and change things if you want. Then build the distribution with ``make World'' or: .LP .DS make Bootstrap make depend make make install .DE .NH Programming Interface .LP Source files for applications using .I MemMgr routines should include .I memmgr.h . .LP Applications using .I MemMgr should be linked with .I "\-lmemmgr \-letm" . .IS char *AllocNP (size) int size; .IE Allocate .I size bytes of memory and return a pointer to it, or NULL if insufficient memory is available. The memory is not guaranteed to be zeroed. .IS char *Alloc (size) int size; .IE Like .I Alloc() , but panics if insuffient memory is available. .IS char *StrAllocNP (s) char *s; .IE Allocates space for the string pointed to by .I s (including a null byte at the end), copies the string into it, and returns a pointer to the copy. Returns NULL if .I s is NULL or insufficient memory is available. .IS char *StrAlloc (s) char *s; .IE Like .I StrAllocNP() , but panics if .I s is NULL or insuffient memory is available. .IS char *VAllocNP (count, size) int count, size; .IE Allocate .I count objects of .I size bytes of memory and return a pointer to it, or NULL if insufficient memory is available. The memory is not guaranteed to be zeroed. .IS char *VAlloc (count, size) int count, size; .IE Like .I VAlloc() , but panics if insuffient memory is available. .IS char *ReallocNP (p, size) char *p; int size; .IE Reallocate the block of memory pointed to by .I p to be .I size bytes long, free .I p and return a pointer to the new block. .I p should have been allocated by one of the other .I MemMgr routines. Returns NULL if insufficient memory is available; in this case the block pointed to by .I p is .B not freed. Also returns NULL if .I p is NULL. .IS char *Realloc (p, size) char *p; int size; .IE Like .I Realloc() , but panics if .I p is NULL or insuffient memory is available. .IS void Free (p) char *p; .IE Frees the chunk of memory pointed to by .I p ; the memory should have been allocated by one of the other .I MemMgr routines, with the exception that it is safe to pass NULL to .I Free() . .NH Distribution and Update Availability .LP The .I MemMgr distribution may be freely circulated and is available for anonymous FTP access under the .I ~ftp/pub directory on host .I ftp.primate.wisc.edu . Updates appear there as they become available. .LP The ETM and WRPRC configuration distributions are available on .I ftp.primate.wisc.edu as well. .LP If you do not have FTP access, send requests to the address .I software@primate.wisc.edu . Bug reports, questions, suggestions and comments may be sent to this address as well. :::::::::::::: realloc.c :::::::::::::: /* Panic version of ReallocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *Realloc (p, size) char *p; int size; { if (p == (char *) NULL) ETMPanic ("Realloc: null pointer"); if ((p = ReallocNP (p, size)) == (char *) NULL) ETMPanic ("Realloc: out of memory"); return (p); } :::::::::::::: reallocnp.c :::::::::::::: /* Reallocate p to size, free old memory and return pointer to new. If can't allocate the memory, returns NULL, and the old memory is NOT freed. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *ReallocNP (p, size) char *p; int size; { char *s; if (p == (char *) NULL) return ((char *) NULL); if ((s = (char *) realloc (p, size)) == (char *) NULL) return ((char *) NULL); /*Free (p);*/ /* <- whoops! */ return (s); } :::::::::::::: stralloc.c :::::::::::::: /* Panic version of StrAllocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *StrAlloc (s) char *s; { char *p; if (s == (char *) NULL) ETMPanic ("StrAlloc: trying to copy null pointer"); if ((p = StrAllocNP (s)) == (char *) NULL) ETMPanic ("StrAlloc: out of memory"); return (p); } :::::::::::::: strallocnp.c :::::::::::::: /* Allocate space for a string, copy the string into it, and return a pointer to the copy, or NULL if couldn't get the memory. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *StrAllocNP (s) char *s; { char *p; if (s == (char *) NULL) return ((char *) NULL); if ((p = AllocNP (strlen (s) + 1)) == (char *) NULL) return ((char *) NULL); return (strcpy (p, s)); } :::::::::::::: valloc.c :::::::::::::: /* Panic version of VAllocNP(). */ # include # include "etm.h" # include "memmgr.internal.h" # include "memmgr.h" char *VAlloc (count, size) int count, size; { char *p; if ((p = VAllocNP (count, size)) == (char *) NULL) ETMPanic ("VAlloc: out of memory"); return (p); } :::::::::::::: vallocnp.c :::::::::::::: /* Allocate a piece of memory to hold "count" elements of size "size", and return a pointer to it, or NULL if insufficient memory is available. */ # include # include "memmgr.internal.h" # include "memmgr.h" char *VAllocNP (count, size) int count, size; { return ((char *) calloc (count, (allocSizeType) size)); } ememmgr-1.04/Changes-1.03010064400017710000151000000011140616203020000163000ustar00junkyarddatamgmt00000400000027Changes to MemMgr distribution for release 1.03. Now configured with WRPRC2 imake configuration files. Most important code change: All functions are #define'd as "# define f f_" in memmgr.h. This causes failure at link time if memmgr.h wasn't included everywhere it should have been. This can help a lot on compilers such as THINK C. It means, however, that libraries that use MemMgr should be recompiled and reinstalled, or programs using those libraries will get "undefined symbol" errors for MemMgr function names. memmgr.h now idempotent; may be included more than once safely. memmgr-1.04/Changes-1.04010064400017710000151000000002630621410232300163110ustar00junkyarddatamgmt00000400000027Changes to MemMgr distribution for release 1.04 Fixed allocation functions to not return NULL on a zero-byte request. Some systems do this for malloc(0) (HP-UX, for instance.) memmgr-1.04/malloc0.c010064400017710000151000000004420621410340400161310ustar00junkyarddatamgmt00000400000027/* * malloc0 * * Test whether or not a zero-size allocation returns NULL. */ # include # include "memmgr.internal.h" # include "memmgr.h" int main (argc, argv) int argc; char *argv[]; { char *p; p = malloc ((allocSizeType) 0); printf ("malloc(0) returns %#lx\n", p); } troffcvt-1.04.orig/tarballs/TS-1.08.tar100644 1750 1750 170000 6431756100 15355 0ustar blpblptokenscan/004075500017710000151000000000000617062533100145565ustar00junkyarddatamgmt00000000000000tokenscan/config/004075500017710000151000000000000616203024600160175ustar00junkyarddatamgmt00000000000000tokenscan/config/Imake.p-params000064400017710000151000000006260617062530700205160ustar00junkyarddatamgmt00000000000000# ifndef ProjectName # define ProjectName TokenScan Library # endif # ifndef ProjectMajorRelease # define ProjectMajorRelease 1 # endif # ifndef ProjectMinorRelease # define ProjectMinorRelease 08 # endif #ifndef TsLib #define TsLib $(LOADERLIBPREFIX)$(TOP)/libtokenscan.a #endif #ifndef DepTsLib #define DepTsLib $(TOP)/libtokenscan.a #endif #ifndef ProjectIncludes #define ProjectIncludes -I. #endif tokenscan/Changes-1.02000064400017710000151000000004150616203024700164200ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for release 1.02 Parameterized the quote and escape characters so they may be modified. Added TSIsScanQuote() and TSIsScanEscape() functions. Added a small test program. Tried to revise document for clarity again. I still despise it. tokenscan/Makefile000066400017710000151000000265620617062532100162260ustar00junkyarddatamgmt00000000000000# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/88 1995/12/08 16:33:13 gildea $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit hp.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit hp.cf to change # platform: hp.cf 95/07/15 # operating system: HP-UX 9.05 # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / MFLAGS = -$(MAKEFLAGS) SHELL = /bin/sh VARARGS_DEFINES = -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 07 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = TokenScan Library PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 08 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp LOCALROOTDIR = /usr/local LOCALBINDIR = /usr/local/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar clq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -ax -DSYSV LINTLIBS = LN = ln -s MAKE = make MV = mv -f CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -DSYSV STD_LDLIBS = STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(STD_LDLIBS) $(PROJECT_LDLIBS) $(LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = install.sh INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = $(LOADERLIBPREFIX)$(TOP)/libtokenscan.a DEPTSLIB = $(TOP)/libtokenscan.a # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # Token scanning library Makefile # Use "make World" to build this project. # Requires the WRPRC2 configuration files. # Look at the files in the config subdirectory to see if you want # to change anything. # where to install tokenscan.h LIBSRCS = tokenscan.c LIBOBJS = tokenscan.o TESTSRCS = tstest.c TESTOBJS = tstest.o SRCS = $(LIBSRCS) $(TESTSRCS) .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libtokenscan.a libtokenscan.a: $(LIBOBJS) $(RM) $@ $(AR) $@ $(LIBOBJS) clean:: $(RM) libtokenscan.a lint:: lint.libtokenscan.a lint.libtokenscan.a: $(LINT) $(LINTFLAGS) $(LIBSRCS) $(LINTLIBS) install:: i.libtokenscan.a i.libtokenscan.a:: libtokenscan.a @if [ -d $(LOCALUSRLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALUSRLIBDIR)); fi $(INSTALL) $(INSTLIBFLAGS) libtokenscan.a $(LOCALUSRLIBDIR)/libtokenscan.a install:: i.tokenscan.h i.tokenscan.h:: tokenscan.h @if [ -d $(LOCALINCLUDEROOT) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALINCLUDEROOT)); fi $(INSTALL) $(INSTINCFLAGS) tokenscan.h $(LOCALINCLUDEROOT)/tokenscan.h all:: tstest tstest: $(TESTOBJS) $(DEPTSLIB) $(RM) $@ $(CC) -o $@ $(TESTOBJS) $(LDOPTS) $(TSLIB) $(EXTRA_LDLIBS) clean:: $(RM) tstest lint:: lint.tstest lint.tstest: $(LINT) $(LINTFLAGS) $(TESTSRCS) $(LINTLIBS) install:: i.tstest i.tstest:: @echo tstest is not installed anywhere. test:: tstest ./tstest testin1 ./tstest -s testin2 regression:: tstest ./tstest testin1 | diff testout1 - ./tstest -s testin2 | diff testout2 - depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) all:: World:: @echo "Building "$(PROJECTNAME)", Release "$(PROJECTRELEASE) @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean $(MAKE) $(MFLAGS) depend $(MAKE) $(MFLAGS) all @echo "" @date @echo "" @echo "Done building "$(PROJECTNAME) tokenscan.ps:: tokenscan.ms $(SOELIM) tokenscan.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > tokenscan.ps clean:: $(RM) tokenscan.ps # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE tokenscan.o: /usr/include/stdio.h /usr/include/sys/stdsyms.h tokenscan.h tstest.o: /usr/include/stdio.h /usr/include/sys/stdsyms.h tokenscan.h --------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in tokenscan/tstest.c000064400017710000151000000041500616203024700162410ustar00junkyarddatamgmt00000000000000/* * tstest - tokenscan library test program * * Syntax: tstest [ -dstr ] [ -estr ] [ -qstr ] [ -s ] [ file ] * * 25 Sep 91 Paul DuBois dubois@primate.wisc.edu * * 25 Sep 91 Version 1.00. Created. */ # include # include "tokenscan.h" #ifndef bufSiz #define bufSiz 1024 #endif #define maxPtr 100 static char *usage = "tstest [ -dstr ] [ -estr ] [ -qstr ] [ -s ] [ file ]"; int main (argc, argv) int argc; char **argv; { TSScanner scanner; char buf[bufSiz]; char *p; char *ptr[maxPtr]; int nPtrs; int i; --argc; ++argv; while (argc > 0 && argv[0][0] == '-') { if (strncmp (argv[0], "-d", 2) == 0) { TSGetScanner (&scanner); scanner.scanDelim = &argv[0][2]; TSSetScanner (&scanner); --argc; ++argv; } else if (strncmp (argv[0], "-e", 2) == 0) { TSGetScanner (&scanner); scanner.scanEscape = &argv[0][2]; TSSetScanner (&scanner); --argc; ++argv; } else if (strncmp (argv[0], "-q", 2) == 0) { TSGetScanner (&scanner); scanner.scanQuote = &argv[0][2]; TSSetScanner (&scanner); --argc; ++argv; } else if (strcmp (argv[0], "-s") == 0) { TSGetScanner (&scanner); scanner.scanFlags |= tsNoConcatDelims; TSSetScanner (&scanner); --argc; ++argv; } else { fprintf (stderr, "unknown flag: %s\n", argv[0]); fprintf (stderr, "%s\n", usage); exit (1); } } if (argc == 0) fprintf (stderr, "Reading standard input:\n"); else if (argc == 1) { if (freopen (argv[0], "r", stdin) == (FILE *) NULL) { fprintf (stderr, "cannot open: %s\n", argv[0]); exit (1); } } else { fprintf (stderr, "%s\n", usage); exit (1); } while (fgets (buf, (int) sizeof (buf), stdin) != (char *) NULL) { if (buf[0] == '#') /* comment; just echo */ { fputs (buf, stdout); continue; } printf ("Input:\t%s", buf); TSScanInit (buf); for (nPtrs = 0; nPtrs < maxPtr; nPtrs++) { if ((p = TSScan ()) == (char *) NULL) break; ptr[nPtrs] = p; } printf ("%d token%s:", nPtrs, nPtrs == 1 ? "" : "s"); for (i = 0; i < nPtrs; i++) { putchar (' '); printf ("<%s>", ptr[i]); } putchar ('\n'); } exit (0); } ); } while (fgets (buf, (int) sizeof (buf), stdin) != (char *) NULL) { if (buf[0] == '#') /* comment; just echo */ { fputs (buf, stdout); continue; } printf ("Input:\t%s", buf); TSScanInit (buf); for (nPtrs = 0; nPtrs < maxPtr; nPtrs++) { if ((p = TSScan ()) == (char *) NULL) break; ptr[nPtrs] = p; } printf ("%d token%s:", nPtrs, nPtrs == 1 ? "" : "s"); for (i = 0; tokenscan/Imakefile000064400017710000151000000017140616203054400163630ustar00junkyarddatamgmt00000000000000/* Token scanning library Imakefile */ XCOMM Token scanning library Makefile XCOMM Use "make World" to build this project. XCOMM Requires the WRPRC2 configuration files. XCOMM Look at the files in the config subdirectory to see if you want XCOMM to change anything. XCOMM where to install tokenscan.h LIBSRCS = tokenscan.c LIBOBJS = tokenscan.o TESTSRCS = tstest.c TESTOBJS = tstest.o SRCS = $(LIBSRCS) $(TESTSRCS) NormalLibraryObjectRule() BuildNormalLibrary(tokenscan,$(LIBSRCS),$(LIBOBJS)) InstallLibrary(tokenscan,$(LOCALUSRLIBDIR)) InstallIncludeFile(tokenscan.h,$(LOCALINCLUDEROOT)) BuildProgram(tstest,$(TESTSRCS),$(TESTOBJS),$(TSLIB),$(DEPTSLIB)) FakeInstallFile(tstest) test:: tstest ./tstest testin1 ./tstest -s testin2 regression:: tstest ./tstest testin1 | diff testout1 - ./tstest -s testin2 | diff testout2 - DependTarget () SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) TroffMsToPostScript(tokenscan.ps,tokenscan.ms,|$(TBL),NullArg) ibrary(tokenscan,$(LIBSRCS),$(LIBOBJS)) InstallLibratokenscan/README000064400017710000151000000024320616203024700154300ustar00junkyarddatamgmt00000000000000tokenscan distribution This directory contains source and documentation for a library implementing a simple token scanner. These were originally part of NIO, my Network I/O library, but were removed since I eventually ended up using them in non-networking applications as well. If you use the Imakefile, you must obtain the WRPRC2 imake configuration files. If you just use the Makefile you will have to edit some of the variable definitions. Use "make -n" and "make -n install" first to see what will happen on your machine! The document tokenscan.ms is formatted with the -ms macros and tbl. The WRPRC2 configuration file distribution is available at: http://www.primate.wisc.edu/software/imake-stuff or ftp://ftp.primate.wisc.edu/software/imake-stuff If you don't have imake and you need that too, you can get it at: http://www.primate.wisc.edu/software/imake-book or ftp://ftp.primate.wisc.edu/software/imake-book 26 Oct 90 Paul DuBois dubois@primate.wisc.edu 26 Oct 90 Release 1.0. 02 Jan 91 Release 1.01. Document revisions. 26 Sep 91 Release 1.02. See Changes-1.02. 01 Sep 93 Release 1.03. See Changes-1.03. 18 Sep 93 Release 1.04. See Changes-1.04. 06 Oct 93 Release 1.05. See Changes-1.05. 18 Oct 93 Release 1.06. See Changes-1.06. 22 Mar 96 Release 1.07. See Changes-1.07. ou need that too, you can get it at: http://www.primate.wisc.edu/software/imake-book or ftp://ftp.primate.wisc.edu/software/imake-book 26 Oct 90 Paul DuBois dubois@primate.wisc.edu 26 Oct 90 Release 1.0. 02 Jan 91 Release 1.0tokenscan/tokenscan.h000064400017710000151000000011170616203024700167050ustar00junkyarddatamgmt00000000000000/* * tokenscan.h - token scanning library stuff */ /* * Flags for scanFlags field */ #define tsNoConcatDelims 0x01 /* all delimiters are significant */ typedef struct TSScanner TSScanner; struct TSScanner { void (*scanInit) (); char *(*scanScan) (); char *scanDelim; char *scanQuote; char *scanEscape; char *scanEos; int scanFlags; }; void TSScanInit (); char *TSScan (); void TSSetScanner (); void TSGetScanner (); void TSSetScanPos (); char *TSGetScanPos (); int TSIsScanDelim (); int TSIsScanQuote (); int TSIsScanEscape (); int TSIsScanEos (); int TSTestScanFlags (); s field */ #define tsNoConcatDelims 0x01 /* all delimiters are significant */ typedef struct TSScanner TSScanner; struct TSScanner { void (*scanInit) (); char *(*scanScan) (); char *scanDelim; char *scanQuote; char *scanEscape; char *scanEos; int scanFlags; }; void TSScanInit (); char *TSScan (); void TSSetScanner (); void TSGetScanner (); void TSSetScanPos (); char *TSGetScanPos (); int TSIsScanDelim (); int TSIsSctokenscan/tokenscan.ms000064400017710000151000000266500616203024700171060ustar00junkyarddatamgmt00000000000000.\" .\" troff -ms % | lpr .\" .\" revision date - change whenever this file is edited .ds RD 18 October 1993 .nr PO 1.2i \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance .\" .EH 'Token Scanning Library'- % -'' .OH ''- % -'Token Scanning Library' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .\" I - italic font (taken from -ms and changed) .de I .nr PQ \\n(.f .if t \&\\$3\\f2\\$1\\fP\&\\$2 .if n .if \\n(.$=1 \&\\$1 .if n .if \\n(.$>1 \&\\$1\c .if n .if \\n(.$>1 \&\\$2 .. .de IS \" interface routine description header start .DS L .ta .8i .ft B .. .de IE \" interface routine description header end .DE .ft R .. .TL TS \*- A Simple Token Scanning Library .sp .5v .ps 10 Release 1.06 .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Revision date:\0\0\*(RD .LP Applications often wish to pull strings apart into individual tokens. This document describes TS, a library consisting of an unsophisticated set of routines providing simple token scanning operations. .LP String tokenizing can often be done satisfactorily using .I strtok() or equivalent function from the C library. When such routines are insufficient, the routines described here may be useful. They offer, for example, quote and escape character parsing, and configurability of underlying scanning properties, within the confines of a fixed interface. TS provides a simple built-in scanner, which may be replaced by alternate routines as desired. Applications may switch back and forth between scanners on the fly. .NH Installation .LP This release of TS is configured using .I imake and the WRPRC2 configuration files, so you also need to obtain the WRPRC2 configuration distribution if you want to build it the usual way. (If you want to avoid .I imake , the .I Makefile is simple enough that you should be able to tweak it by hand.) .LP There is one library to be built, .I libtokenscan.a . That library should be installed in a system library directory. The header file .I tokenscan.h should be installed in a system header file directory. .NH Example .LP The canonical method of tokenizing a string with TS is as follows: .LP .DS char buf[size], *p; /* \fI...initialize contents of buf here...\fP */ TSScanInit (buf); /* initialize scanner */ while ((p = TSScan ()) != (char *) NULL) { /* \fI...do something here with token pointed to by p here...\fP */ } .DE .LP The scanner is initialized by passing the string to be scanned to .I TSScanInit() and .I TSScan() is called to get pointers to successive tokens. .I TSScan() returns NULL when there are no more. .NH Behavior of the Default Scanner .LP The default scanner is destructive in that it modifies the string scanned (it writes nulls at the end of each token found), so make a copy of the scanned string if you need to maintain an intact version. .LP The scanner is controlled by delimiter, quote, escape, and end-of-string (EOS) characters. The defaults for each of these are given below. .LP .TS center tab(:); l l . delimiter:space tab quote:" ' escape:\e EOS:null linefeed carriage-return .TE .LP In the simplest case, tokens are sequences of characters between delimiters. Since the default delimiters are the whitespace characters space and tab, tokens are sequences of non-whitespace characters. .LP .DS .ta 1.5i 2i This is a line \(-> .DE .LP Quotes may be used to include whitespace within a token. Quotes must match; hence one quote character may be used to quote another kind of quote character, if there is more than one. .LP .DS .ta 1.5i 2i "This is" a line \(-> This" "is a line \(-> "'"\0'"' \(-> <'> <"> "'"'"' \(-> <'"> .DE .LP The escape character turns off any special meaning of the next character, including another escape character. .LP .DS .ta 1.5i 2i What\e's up \(-> \e\e is the escape \(-> <\e> .DE .LP The EOS characters tell the scanner when to quit scanning. A null character always terminates the scan. In the default case, linefeed and carriage return do as well. .LP You can replace the delimiter, quote, escape, or EOS character sets. This changes the particular characters that trigger the above behaviors, without changing the way the default scan algorithm works. Or you can replace the scan routine to make the scanner behave in entirely different ways. .LP By default, multiple consecutive delimiter characters are treated as a single delimiter. A flag may be set in the scanner structure to suppress delimiter concatenation, so that every delimiter character is significant. This is useful for tokenizing strings in which empty fields are allowed: two consecutive delimiters are considered to have an empty token between them, and delimiters appearing at the beginning or end of a string signify an empty token at the beginning end of the string. .LP The difference in treatment of strings when delimiters are concatenated versus when they are not is illustrated below. Suppose the delimiter is colon (:) and the string to be tokenized is: .DS :a:b::c: .DE When delimiters are concatenated, the string contains three tokens: .LP .DS .ta 1.5i 2i :a:b::c: \(-> .DE .LP When all delimiters are significant, string contains three empty tokens in addition: .LP .DS .ta 1.5i 2i :a:b::c: \(-> <> <> <> .DE .NH Programming Interface .LP Source files using TS routines should include .I tokenscan.h and executables should be linked with .I "\-ltokenscan" . .LP A scanner is described by a data structure: .LP .DS typedef struct TSScanner TSScanner; struct TSScanner { void (*scanInit) (); char *(*scanScan) (); char *scanDelim; char *scanQuote; char *scanEscape; char *scanEos; int scanFlags; } .DE .LP Scanner structures may be obtained or installed with .I TSGetScanner() and .I TSSetScanner() . .LP For each string to be scanned, the application passes a pointer to it to .I TSScanInit() , which takes care of scan initialization. If the application requires initialization to be performed in addition to that done internally by TS, a pointer to a routine that does so should be installed in the .I scanInit field of the scanner data structure. It takes one argument, a pointer to the string to be scanned. The default .I scanInit is NULL, which does nothing. .LP .I scanDelim , .I scanQuote , .I scanEscape , and .I scanEos are pointers to null-terminated strings consisting of the set of characters to be considered delimiter, quote, escape, and EOS characters, respectively. The default values were described previously. .LP .I scanScan points to the routine that does the actual scanning. It is called by .I TSScan() and should be declared to take no arguments and return a character pointer to the next token in the current scan buffer. Normally, this routine does the following: call .I TSGetScanPos() to get the current scan position, scan the token, call .I TSSetScanPos() to update the scan position, then return a pointer to the beginning of the token. If there are no more tokens in the scan buffer, the routine should return NULL, and should continue to do so until .I TSScanInit() is called again. .LP .I scanFlags contains flags that modify the scanner's behavior. For the default scanner, the default is zero. If the .I tsNoConcatDelims flag is set, the scanner stops on every delimiter rather than treating sequences of contiguous delimiters as a single delimiter. .LP The public routines in the TS library are described below. .IS void TSScanInit (p) char *p; .IE Initializes the scanning routines to make the character string pointed to by .I p the current scan buffer. .IS char *TSScan () .IE Returns a pointer to the next token in the current scan buffer, NULL if there are no more. The token is terminated by a null byte. Scan behavior may be modified by substituting alternate scan routines. .LP Once .I TSScan() returns NULL, it continues to do so until the scanner is reinitialized with another call to .I TSScanInit() . .IS void TSGetScanner (p) TSScanner *p; .IE Gets the current scanner information (initialization and scan procedures; delimiter, quote, escape, and EOS character sets; and scanner flags) into the structure pointed to by .I p . .IS void TSSetScanner (p) TSScanner *p; .IE Installs a scanner. If .I p itself if NULL, all default scanner values are reinstalled. Otherwise, any pointer field in .I p with a NULL value causes the corresponding value from the default scanner to be reinstalled, and if .I p\->scanFlags is zero, the scanner flags are set to the default (also zero). .IS void TSGetScanPos (p) char **p; .IE Puts the current position within the current scan buffer into the argument, which should be passed as the address of a character pointer. This is useful when you want to scan only enough of the buffer to partially classify it, then use the rest in some other way. .IS void TSSetScanPos (p) char *p; .IE Set the current scan position to .I p . .IS int TSIsScanDelim (c) char c; .IE Returns non-zero if .I c is a member of the current delimiter character set, zero otherwise. .IS int TSIsScanQuote (c) char c; .IE Returns non-zero if .I c is a member of the current quote character set, zero otherwise. .IS int TSIsScanEscape (c) char c; .IE Returns non-zero if .I c is a member of the current escape character set, zero otherwise. .IS int TSIsScanEos (c) char c; .IE Returns non-zero if .I c is an end-of-string character, zero otherwise. .IS int TSTestScanFlags (flags) int flags .IE Returns non-zero if all bits in .I flags are set for the current scanner, zero otherwise. .NH 2 Overriding Scanning Routines .LP It is possible to switch back and forth between scan procedures on the fly, even in the middle of scanning a string. The general procedure is to use .I TSGetScanner() to get the current scanner information, and .I TSSetScanner() to install a new one and reinstall the old one when done with the new. If you switch between more than two scanners, another method may be necessary. .LP It is possible to modify the default scanner without replacing it. For instance, you could change the default delimiter set but leave everything else the same, as follows: .LP .DS TSScanner scanStruct; TSGetScanner (&scanStruct); scanStruct.scanDelim = " \et:;?,!"; TSSetScanner (&scanStruct); .DE .NH Miscellaneous .LP A scanner can be nondestructive with respect to the line being scanned by using a scan routine that copies characters out of the scanned line into a second buffer and returning a pointer to the second buffer. The second buffer must be large enough to hold the largest possible token, of course. If the second buffer is a fixed area, the host application must be careful not to call .I TSScan() again until it is done with the current token, or else make a copy of it first. If the second buffer is dynamically allocated, the application must be ready to do storage management of the tokens returned. .LP Some scanners might not need delimiter, quote, escape, or EOS characters at all, particularly if token boundaries are context sensitive. .NH Distribution and Update Availability .LP The TS distribution may be freely circulated and is available for anonymous FTP access in the .I /pub/TS directory on host .I ftp.primate.wisc.edu . Updates appear there as they become available. .LP The WRPRC2 .I imake configuration file distribution is available on .I ftp.primate.wisc.edu as well, in .I /pub/imake-stuff. .LP If you do not have FTP access, send requests to .I software@primate.wisc.edu . Bug reports, questions, suggestions and comments may be sent to this address as well. Availability .LP The TS distribution may be freely circulated and is available for anontokenscan/tokenscan.c000066400017710000151000000134530616203024700167100ustar00junkyarddatamgmt00000000000000/* TSScanInit() - initialize scanner to scan a buffer. TSScan() - pull successive tokens out of a character. Returns NULL when there are no more. Has the property that once it returns NULL, succeeding calls continue to return NULL until TSScanInit() is called again. Default behavior is that tokens are sequences of non-blank characters, or quotes can be used to allow whitespace characters in the token. The '\' character turns off any special meaning of the following character. TSSetScanner () - install scanner. TSGetScanner () - get current scanner. TSSetScanPos() - set current position within scan buffer. TSGetScanPos() - get current position within scan buffer. TSIsScanDelim() - test whether character is in current delimiter set. TSIsScanQuote() - test whether character is in current quote set. TSIsScanEscape() - test whether character is in current escape set. TSIsScanEos() - test whether character is in current EOS set. TSTestScanFlags() - test whether scanner flags are set. The original buffer is destroyed by scanning, since null bytes are placed after each token as they are found. 12 Apr 90 Created (as part of NIO). 25 Sep 90 Reorganized to allow accommodating alternate scanners while preserving current scan position within buffer. 26 Oct 90 Removed from NIO and made into separate library. 25 Sep 91 Parameterized the quote and escape characters. 06 Oct 93 Added scanFlags field to scanner structure. Only flag so far is to allow all delimiter characters to be significant (so scanner stops on each one, rather than treating sequences of contiguous delimiters as one delimiter). 14 Oct 93 Parameterized the end-of-string characters. */ # include # include "tokenscan.h" typedef void (*VoidProc) (); typedef char * (*CharPtrProc) (); static int Search (); static char *CanonScan (); static TSScanner defScan = { (VoidProc) NULL, CanonScan, " \t", "\"'", "\\", "\n\r", 0 }; static TSScanner curScan = { (VoidProc) NULL, CanonScan, " \t", "\"'", "\\", "\n\r", 0 }; static char *curPos; static int emptyToken; void TSScanInit (p) char *p; { curPos = p; emptyToken = 0; if (curScan.scanInit != (VoidProc) NULL) (*curScan.scanInit) (p); } void TSSetScanner (p) TSScanner *p; { if (p == (TSScanner *) NULL || p->scanInit == (VoidProc) NULL) curScan.scanInit = defScan.scanInit; else curScan.scanInit = p->scanInit; if (p == (TSScanner *) NULL || p->scanScan == (CharPtrProc) NULL) curScan.scanScan = defScan.scanScan; else curScan.scanScan = p->scanScan; if (p == (TSScanner *) NULL || p->scanDelim == (char *) NULL) curScan.scanDelim = defScan.scanDelim; else curScan.scanDelim = p->scanDelim; if (p == (TSScanner *) NULL || p->scanQuote == (char *) NULL) curScan.scanQuote = defScan.scanQuote; else curScan.scanQuote = p->scanQuote; if (p == (TSScanner *) NULL || p->scanEscape == (char *) NULL) curScan.scanEscape = defScan.scanEscape; else curScan.scanEscape = p->scanEscape; if (p == (TSScanner *) NULL || p->scanEos == (char *) NULL) curScan.scanEos = defScan.scanEos; else curScan.scanEos = p->scanEos; if (p == (TSScanner *) NULL || p->scanFlags == 0) curScan.scanFlags = defScan.scanFlags; else curScan.scanFlags = p->scanFlags; } void TSGetScanner (p) TSScanner *p; { p->scanInit = curScan.scanInit; p->scanScan = curScan.scanScan; p->scanDelim = curScan.scanDelim; p->scanQuote = curScan.scanQuote; p->scanEscape = curScan.scanEscape; p->scanEos = curScan.scanEos; p->scanFlags = curScan.scanFlags; } void TSSetScanPos (p) char *p; { curPos = p; } char * TSGetScanPos () { return (curPos); } /* * Search a (possibly NULL) string for a character. */ static int Search (s, c) char *s; char c; { char c2; if (s != (char *) NULL) { while ((c2 = *s++) != '\0') { if (c == c2) return (1); } } return (0); } int TSIsScanDelim (c) char c; { return (Search (curScan.scanDelim, c)); } int TSIsScanQuote (c) char c; { return (Search (curScan.scanQuote, c)); } int TSIsScanEscape (c) char c; { return (Search (curScan.scanEscape, c)); } int TSIsScanEos (c) char c; { if (c == '\0') /* null character ALWAYS terminates string */ return (1); return (Search (curScan.scanEos, c)); } int TSTestScanFlags (flags) int flags; { return ((curScan.scanFlags & flags) == flags); } char * TSScan () { return ((*curScan.scanScan) ()); } static char * CanonScan () { char *pos, *start, *p, c, quote = 0; int escape = 0, haveToken = 0; if (emptyToken) /* fix to point into buffer */ { emptyToken = 0; return (""); } pos = TSGetScanPos (); if (!TSTestScanFlags (tsNoConcatDelims)) { while (TSIsScanDelim (*pos)) /* skip delimiters */ ++pos; } start = p = pos; /* start of token */ while (!TSIsScanEos (c = *pos)) /* eos terminates any token */ { haveToken = 1; if (escape) /* previous char was escape; */ { /* pass this one literally */ *p++ = *pos++; escape = 0; } else if (TSIsScanEscape (c)) /* this char is escape; */ { /* pass next one literally */ ++pos; escape = 1; } else if (quote) /* in quote mode */ { if (c == quote) /* end quote mode */ quote = 0; else /* no end quote yet */ *p++ = *pos; /* add char */ ++pos; /* skip to next char */ } else if (TSIsScanQuote (c)) /* begin quote mode */ { ++pos; quote = c; } else if (TSIsScanDelim (c)) /* end of token */ { ++pos; /* skip past delimiter */ /* * If also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able to tell that from looking at the string itself, * so set a flag for next call. */ if (TSIsScanEos (*pos) && TSTestScanFlags (tsNoConcatDelims)) ++emptyToken; break; } else *p++ = *pos++; } *p = '\0'; TSSetScanPos (pos); return (haveToken ? start : (char *) NULL); } sScanDelim (c)) /* end of token */ { ++pos; /* skip past delimiter */ /* * If also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/testin2000066400017710000151000000002370616203024700160660ustar00junkyarddatamgmt00000000000000Line with multiple delimiters between tokens. Next line is empty Line with empty fields: "" '' ""''""'' Line with more empty fields: "" '' ""''""'' ++emptyToken; break; } else *p++ = *pos++; } *p = '\0'; TSSetScanPos (pos); return (haveToken ? start : (char *) NULL); } sScanDelim (c)) /* end of token */ { ++pos; /* skip past delimiter */ /* * If also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/Changes-1.05000066400017710000151000000006050616203024700164260ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.05 Added scanFlags field to TSScanner structure. Only flag so far is to allow all delimiter characters to be significant (so scanner stops on each one, rather than treating sequences of contiguous delimiters as one delimiter). This allows tokenizing of lines for which some fields might be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/Changes-1.03000066400017710000151000000001540616203024700164230ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.03 The distribution is configured using the WRPRC2 files now. o far is to allow all delimiter characters to be significant (so scanner stops on each one, rather than treating sequences of contiguous delimiters as one delimiter). This allows tokenizing of lines for which some fields might be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/testin1000064400017710000151000000004520616203025000160540ustar00junkyarddatamgmt00000000000000This is a line of text. "This is a line of text." "This" "is" "a" "line" "of" "text." Test quotes: "'" '"' "two words" two" "words Test continguous quotes: "'"'"' Test escape: \\ \" \' Line with multiple delimiters between tokens. Next line is empty Line with empty fields: "" '' ""''""'' of lines for which some fields might be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/Changes-1.04000066400017710000151000000005200616203025000164130ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.04 Fixed bug: A string such as "'"'"' should be tokenized as '" - however, the scanner wasn't picking up on the fact that right after the second double-quote, there was another quote character so that it needed to go right back into quote mode. Revised the test program tstest a little. be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/Changes-1.06000066400017710000151000000020660616203025000164240ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.06 Revised the test program tstest some more. Added -d, -e, -q flags to allow more extensive testing. Added scanEos field to scanner structure for explicit listing of characters that terminate the scanned string. This fixes the following problem: I had \n listed in the default scanDelim string (so that \n would implicitly terminate scans). That wasn't a problem for the default scanDelim but if the host program replaced the default with a different set of delimiter characters, scanning didn't always work correctly at the ends of strings unless \n \n was included in the set. Having an explicit EOS set fixes this problem so the scanner doesn't have to be tricked into thinking \n is a delimiter. This helps applications that replace default delimiter sets. Added TSIsScanEos() function that tests for end-of-string characters. Fixed some erroneous argument declarations in TSIsScanXXX() function descriptions in tokenscan.ms. (Had c as a char *, not char.) Changed name of tsStopOnAllDelims flag to tsNoConcatDelims. tly at the ends of strings unless \n \n was included in the set. Having an explicit EOS set fixes this problem so the scanner doesn't have to be tricked into thinking \n is a delimiter. This helps applications that replace default delimiter sets. Added TSIsScanEos() function that tests for end-of-string characters. Fixed some erroneous argument declarations in TSIsScanXXX() function descriptions in tokenscan.ms. (Had c as a char *, not char.) Changetokenscan/testout1000066400017710000151000000014450616203025000162620ustar00junkyarddatamgmt00000000000000Input: This is a line of text. 6 tokens: Input: "This is a line of text." 1 token: Input: "This" "is" "a" "line" "of" "text." 6 tokens: Input: Test quotes: "'" '"' "two words" two" "words 6 tokens: <'> <"> Input: Test continguous quotes: "'"'"' 4 tokens: <'"> Input: Test escape: \\ \" \' 5 tokens: <\> <"> <'> Input: Line with multiple delimiters between tokens. 6 tokens: Input: Next line is empty 4 tokens: Input: 0 tokens: Input: Line with empty fields: "" '' ""''""'' 7 tokens: <> <> <> s: <'> <"> Input: Test continguous quotes: "'"'"' 4 tokens: <'"> Input: Test escape: \\ \" \' 5 tokens: <\> <"> <'> Input: Line wtokenscan/testout2000066400017710000151000000007020616203025000162560ustar00junkyarddatamgmt00000000000000Input: Line with multiple delimiters between tokens. 14 tokens: <> <> <> <> <> <> <> <> Input: Next line is empty 4 tokens: Input: 0 tokens: Input: Line with empty fields: "" '' ""''""'' 7 tokens: <> <> <> Input: Line with more empty fields: "" '' ""''""'' 10 tokens: <> <> <> <> <> \\ \" \' 5 tokens: <\> <"> <'> Input: Line wtokenscan/Changes-1.07000066400017710000151000000001570616203025000164240ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.07 Revised Imakefile to refer to tstest in commands as ./tstest. miters> <> <> <> <> <> Input: Next line is empty 4 tokens: Input: 0 tokens: Input: Line with empty fields: "" '' ""''""'' 7 tokens: <> <> <> Input: Line with more empty fields: "" '' ""''""'' 10 tokens: <> <> <> <> <> \\ \" \' 5 tokens: <\> <"> <'> Input: Line wtokenscan/Changes-1.08000066400017710000151000000002330617062527700164420ustar00junkyarddatamgmt00000000000000Changes to the TS distribution -- Release 1.08 Removed line from Imakefile that caused a target conflict (libtokenscan.a had targets with both :: and :). nput: Next line is empty 4 tokens: Input: 0 tokens: Input: Line with empty fields: "" '' ""''""'' 7 tokens: <> <> <> Input: Line with more empty fields: "" '' ""''""'' 10 tokens: <> <> <> <> <> \\ \" \' 5 tokens: <\> <"> <'> Input: Line wChanges to the TS distribution for Release 1.03 The distribution is configured using the WRPRC2 files now. o far is to allow all delimiter characters to be significant (so scanner stops on each one, rather than treating sequences of contiguous delimiters as one delimiter). This allows tokenizing of lines for which some fields might be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/testin1000064400017710000151000000004520616203025000160540ustar00junkyarddatamgmt00000000000000This is a line of text. "This is a line of text." "This" "is" "a" "line" "of" "text." Test quotes: "'" '"' "two words" two" "words Test continguous quotes: "'"'"' Test escape: \\ \" \' Line with multiple delimiters between tokens. Next line is empty Line with empty fields: "" '' ""''""'' of lines for which some fields might be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/Changes-1.04000066400017710000151000000005200616203025000164130ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.04 Fixed bug: A string such as "'"'"' should be tokenized as '" - however, the scanner wasn't picking up on the fact that right after the second double-quote, there was another quote character so that it needed to go right back into quote mode. Revised the test program tstest a little. be empty. Revised the test program tstest a little. f also end of string and all delims are significant, * there's an implicit empty token at end. We won't be * able tokenscan/Changes-1.06000066400017710000151000000020660616203025000164240ustar00junkyarddatamgmt00000000000000Changes to the TS distribution for Release 1.06 Revised the test program tstest some more. Added -d, -e, -q flags to allow more extensive testing. Added scanEos field to scanner structure for explicit listing of characters that terminate the scanned string. This fixes the following problem: I had \n listed in the default scanDelim string (so that \n would implicitly terminate scans). That wasn't a problem for the default scanDelim but if the host program replaced the default with a different set of delimiter characters, scanning didn't always work correctly at the ends of strings unless \n \n was included in the set. Having an explicit EOS set fixes this problem so the scanner doesn't have to be tricked into thinking \n is a delimiter. This helps applications that replace default delimiter sets. Added TSIsScanEos() function that tests for end-of-string characters. Fixed some erroneous argument declarations in TSIsScanXXX() function descriptions in tokenscan.ms. (Had c as a char *, not char.) Changed name of tsStopOnAllDelims flag to tsNoConcatDelims. tly at the ends of strings unless \n \n was included in the set. Having an explicit EOS set fixes this problem so the scanner doesn't have to be tricked into thinking \n is a delimiter. This helps applications that replace default delimiter sets. Added TSIsScanEos() function that tests for end-of-string characters. Fixed some erroneous argument declarations in TSIsScanXXX() function descriptions in tokenscan.ms. (Had c as a char *, not char.) Changetokenscan/testout1000066400017710000151000000014450616203025000162620ustar00junkyarddatamgmt00000000000000Input: This is a line of text. 6 tokens: Input: "This is a line of text." 1 token: Input: "This" "is" "a" "line" "of" "text." 6 tokens: Input: Test quotes: "'" '"' "two words" two" "words 6 tokens: <'> <"> Input: Test continguous quotes: "'"'"' 4 tokens: <'"> Input: Test escape: \\ \" \' 5 tokens: <\> <"> <'> Input: Line with multiple delimiters between tokens. 6 tokens: Input: Next line is empty 4 tokens: Input: 0 tokens: Input: Line with empty fields: "" '' ""''""'' 7 tokens: <> <> <> s: <'> <"> Input: Test continguous quotes: "'"'"' 4 tokens: <'"> Input: Test escape: \\ \" \' 5 tokens: <\> <"> <'> Input: Line wtroffcvt-1.04.orig/tarballs/WRPRC-2.11.tar100644 1750 1750 1652000 6431756100 15745 0ustar blpblpWRPRC-2.11/004077500017710000151000000000000634140472000140615ustar00junkyarddatamgmt00000400000027WRPRC-2.11/README010066400017710000151000000237670634140471600147620ustar00junkyarddatamgmt00000400000027WRPRC2 Configuration File Distribution Release 2.10 13 December 1996 Paul DuBois dubois@primate.wisc.edu http://www.primate.wisc.edu/people/dubois NOTE: xmkmf is NEVER used to build ANYTHING in this distribution. NOTE: it's assumed you have a version of imake from X11R6 or higher. If not, see the note about XCOMM at the top of config/Imake.tmpl. This distribution contains the WRPRC2 imake configuration files, i.e., Release 2 of the Wisconsin Regional Primate Research Center configuration files. The Release 2 configuration files are not upward-compatible with the Release 1 files. Changes for each release of this distribution are listed in the Changes-2.xx files. If you need information about imake, see the "boa book": Software Portability with imake, 2nd edition Paul DuBois O'Reilly & Associates ISBN: 1-56592-226-3 URL: http://www.ora.com/catalog/imake2 Email: books@ora.com There are also some shorter imake-related papers available at: http://www.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ The WRPRC2 distribution does not contain source for the configuration programs imboot, imake, mkdirhier, or makedepend. You'll need those programs to use the WRPRC2 files. If you don't have them, retrieve the itools distribution from the imake-book archive using one of the locators below: http://www.primate.wisc.edu/software/imake-book/ ftp://ftp.primate.wisc.edu/software/imake-book/ Instructions for building the itools distribution are available in Appendix B of the boa book. If you don't have the book, this appendix is available online in the imake-book archive. ------------------------------------------------------------------------------- Configuring and Installing the Distribution ------------------------------------------------------------------------------- Instructions for building the distribution are given below. If the instructions don't work for you, let me know. - The distribution consists of a main directory WRPRC2, a config directory containing the configuration files, and an examples directory containing some sample Imakefiles. R1-docs contains the Release 1 documents, which may be of some historical interest. - You should review the configuration files first to see whether the parameter values are appropriate for your system. You may find it helpful to read the reference document, reference.ms. - You may need to modify your vendor file and/or site.def file (located in the config directory). If you have installed an earlier release of the WRPRC2 files before, you may already have modified the vendor and site.def files from that release. If so, consult them so you know what changes you'll have to make to the corresponding files in this distribution. (Don't just install the new files on top of the old ones without looking.) - If there's no vendor-specific file for your system in this distribution, you'll have to write one. These are the files ending in .cf. Use the ones provided as a guide and read "Using the WRPRC2 Configuration Files On a New Platform" below. Also, contact me if you'd like some advice. - Modify site.def. Use it to specify site-specific preferences for which the defaults aren't suitable for your site. For instance, if you want to use /usr/local for the value of LocalBinDir rather than the default of /usr/local/bin, put the following in site.def: #ifndef LocalBinDir #define LocalBinDir /usr/local #endif Similarly, if you want to use groff instead of troff, write this: #ifndef TroffCmd #define TroffCmd groff #endif Determine the value that imboot uses for the configuration root (take a look at the imboot script on your machine). The value of ConfigRootDir must match what your copy of imboot uses. By default this value is /usr/local/lib/config. If it's different on your machine (for instance, /var/lib/config), put the following in site.def to override the default: #ifndef ConfigRootDir #define ConfigRootDir /var/lib/config #endif This is to make sure that "make install" installs the configuration files into the right place, i.e., where imboot can find them. Pay particular attention to the LocalXXXDir parameters. They're set up as counterparts to several standard system directories, but they're all located under /usr/local by default. Imakefiles written for the WRPRC2 configuration files will often use the LocalXXXDir parameters as installation destintations, so you should make sure they point to where you want locally installed files to go. To move the local directories to a different root point, define LocalRootDir as that root point. To relocate individual local directories, define individual LocalXXXDir parameters. To make the local directories the same as the standard directories, define LocalBinDir as $(BINDIR), LocalIncludeRoot as $(INCLUDEROOT), etc. Take a look at the other comments in site.def to see if there are other parameters you might want to set. When you decide to override a parameter in site.def , take a look at your vendor file. If the vendor file overrides the parameter, that takes precedence over a definition in the site file. In that case, modify the vendor file instead. - Note for Cray systems: InstallCmd is defined as install.sh in cray.cf. For this to work, install.sh must be installed on your system. If you don't have it, get it from the itools distribution mentioned above (or from the X11 distribution if you have it) and install it as install.sh in some directory that's in your path. (Don't forget to make install.sh executable.) - Note for HP systems: InstallCmd is defined as install.sh. See above note for Cray systems, or change InstallCmd to bsdinst if you like. I find that install.sh works better than bsdinst on HP systems (fewer useless warning messages). Now follow the steps below in the WRPRC2 distribution top-level directory to configure the Makefiles for this distribution. 1) Type: % make World This should rebuild the Makefiles properly for your system. If "make World" dies, try bootstrapping the Makefiles like this: % imboot % make Makefiles 2) If you want to see what values are actually chosen on your machine for the configuration parameters, change into the config directory and run the following command: % make test | more The make command shows you many of the configuration parameter values. This can be useful for determining whether or not you need to override values in the vendor or site files. You can change parameters, rebuild the Makefile with "make Makefile", and then run "make test" again to check your changes. When you're done in the config directory, change back into project root. 3) If you want to verify that the files will be installed into the correct directory, use this command: % make -n install 4) To actually install the distribution, do this (you may need to become root first): % make install 5) Some filenames changed between Release 2.00 and Release 2.01. If you have files named Project.tmpl, Project.p-tmpl, System.tmpl, and System.p-tmpl in your installation directory, you can remove them. ------------------------------------------------------------------------------- Configuring Projects with the WRPRC2 Configuration Files ------------------------------------------------------------------------------- Read the tutorial document for general information about writing Imakefiles for use with the WRPRC2 files. When you have a project that has Imakefiles written for use with the WRPRC2 files, build the project's Makefiles using the following commands in the project root directory: % imboot -C WRPRC2 % make Makefiles (if the project has subdirectories) Thereafter, you can build the Makefiles like this: % make Makefile % make Makefiles (if the project has subdirectories) ------------------------------------------------------------------------------- Using the WRPRC2 Configuration Files On a New Platform ------------------------------------------------------------------------------- This release has been tested on at least the following platforms: SunOS 4.1.1B Solaris 2.5.1 (SunOS 5.5) RISC/os 4.01 HP-UX 9.05 MkLinux DR2 FreeBSD 2.1.5 It should not be difficult to port the distribution to a new platform, although you'll need to build imake if you don't already have it. For general information on building imake, see Appendix B of the boa book, or retrieve the file appb.ps from the same place you get the itools distribution mentioned above. Briefly, you'll need to do four things: 1) Determine an appropriate vendor symbol that uniquely identifies your platform. There may be one already -- check Imake.cf from a recent X11 distribution, or from the itools distribution. 2) Build imake so it defines the vendor symbol when it invokes cpp. 3) Put a vendor block for your platform in Imake.cf. (Check whether there is one already; if not, write one using those already there as a pattern.) 4) Write a vendor.cf file for your system, and create an empty vendor.p-cf file. The config/untested directory contains some *.cf vendor files for various platforms. You may be able to use one of them as a basis for your system. (These files are from an older release of X11 and should be considered only as an approximation to what you'll need.) If you port the WRPRC2 files to a new platform, please send me the changes. ------------------------------------------------------------------------------- Mips Compatibility Problem with Release 1. ------------------------------------------------------------------------------- Release 1 used "mipsriscos" as the vendor symbol for Mips machines running RISC/os. Release 2 uses "Mips", to be consistent with the X11R5 configuration files. If you're using the Release 1 configuration files to configure projects on a Mips machine, and you want to continue to use them after installing the Release 2 files, you'll need to build a version of imake that defines both symbols. In a source distribution that builds imake, the value of BOOTSTRAPCFLAGS should include both "-DMips" and "-Dmipsriscos", and the predefs[] table in imakemdep.h should have entries for both symbols when Mips is defined. ftp://ftWRPRC-2.11/Imakefile010066400017710000151000000026630634140471600157030ustar00junkyarddatamgmt00000400000027XCOMM WRPRC2 (WRPRC Release 2) imake configuration file distribution #define IHaveSubdirs #define PassCDebugFlags SUBDIRS = config R1-docs all:: @echo "run 'make World' to build the distribution" World:: @echo "" @echo "Building WRPRC $(CONFIGRELEASE) imake configuration file distribution" @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean @echo "" @date @echo "" @echo "Build of WRPRC2 configuration distribution complete." @echo "Now you can run 'make install'" @echo "" HelpAuxTarget(World,build the WRPRC2 distribution) DISTFILES = \ README Imakefile Makefile Changes-* Comparison ReleaseDates \ *.ms tmac.* config examples R1-docs DISTDIR = WRPRC-$(CONFIGRELEASE) Distribution:: $(MAKE) $(MFLAGS) clean -$(RM) -r $(DISTDIR) MakeDir($(DISTDIR)) $(CP) -r $(DISTFILES) $(DISTDIR) tar cf $(DISTDIR).tar $(DISTDIR) gzip $(DISTDIR).tar StuffToClean($(DISTDIR).tar.gz) clean:: $(RM) -r $(DISTDIR) XCOMM Documents XCOMM Release 2 documents documents-ps: tutorial.ps reference.ps p-s.ps limits.ps XCOMM Tutorial user manual TroffMsToPostScript(tutorial.ps,tutorial.ms,|$(TBL),NullArg) XCOMM Reference manual TroffMsToPostScript(reference.ps,reference.ms,|$(TBL),NullArg) XCOMM Writing project-specific config files TroffMsToPostScript(p-s.ps,p-s.ms,NullArg,NullArg) XCOMM WRPRC2 architecture limitations TroffMsToPostScript(limits.ps,limits.ms,|$(TBL),NullArg) WRPRC-2.11/Makefile010066400017710000151000000325100634140471600155240ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = no-project-name PROJECTMAJORRELEASE = 0 PROJECTMINORRELEASE = 00 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # WRPRC2 (WRPRC Release 2) imake configuration file distribution SUBDIRS = config R1-docs all:: @echo "run 'make World' to build the distribution" World:: @echo "" @echo "Building WRPRC $(CONFIGRELEASE) imake configuration file distribution" @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean @echo "" @date @echo "" @echo "Build of WRPRC2 configuration distribution complete." @echo "Now you can run 'make install'" @echo "" help_aux:: @echo "'make "World"' to "build the WRPRC2 distribution DISTFILES = \ README Imakefile Makefile Changes-* Comparison ReleaseDates \ *.ms tmac.* config examples R1-docs DISTDIR = WRPRC-$(CONFIGRELEASE) Distribution:: $(MAKE) $(MFLAGS) clean -$(RM) -r $(DISTDIR) @if [ -d $(DISTDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DISTDIR)); fi $(CP) -r $(DISTFILES) $(DISTDIR) tar cf $(DISTDIR).tar $(DISTDIR) gzip $(DISTDIR).tar clean:: $(RM) $(DISTDIR).tar.gz clean:: $(RM) -r $(DISTDIR) # Documents # Release 2 documents documents-ps: tutorial.ps reference.ps p-s.ps limits.ps # Tutorial user manual tutorial.ps:: tutorial.ms $(SOELIM) tutorial.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > tutorial.ps clean:: $(RM) tutorial.ps help_aux:: @echo "'make "tutorial.ps"' to "format tutorial.ps in PostScript # Reference manual reference.ps:: reference.ms $(SOELIM) reference.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > reference.ps clean:: $(RM) reference.ps help_aux:: @echo "'make "reference.ps"' to "format reference.ps in PostScript # Writing project-specific config files p-s.ps:: p-s.ms $(SOELIM) p-s.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > p-s.ps clean:: $(RM) p-s.ps help_aux:: @echo "'make "p-s.ps"' to "format p-s.ps in PostScript # WRPRC2 architecture limitations limits.ps:: limits.ms $(SOELIM) limits.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > limits.ps clean:: $(RM) limits.ps help_aux:: @echo "'make "limits.ps"' to "format limits.ps in PostScript # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # rules for building in SUBDIRS all:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "making" all "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) all); \ done depend:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "depending" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) depend); \ done install:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "installing" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) install); \ done install.man:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "installing man pages" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) install.man); \ done clean:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "cleaning" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) RM_CMD='$(RM_CMD)' clean); \ done tags:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "tagging" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) TAGS='$(TAGS)' tags); \ done Makefiles:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \ case "$$i" in \ ./?*/?*/?*/?*) parent=../../../../;; \ ./?*/?*/?*) parent=../../../;; \ ./?*/?*) parent=../../;; \ ./?*) parent=../;; \ */?*/?*/?*) parent=../../../../;; \ */?*/?*) parent=../../../;; \ */?*) parent=../../;; \ *) parent=../;; \ esac; \ case "$(TOP)" in \ /?*) topadj= ;; \ *) topadj=$$parent ;; \ esac; \ ($(CHDIR) $$i ; \ $(IMBOOT_CMD) $$topadj$(TOP) $(CURRENT_DIR)/$$i ; \ $(MAKE) $(MFLAGS) Makefiles ) ; \ done # ------------------------------------------------------------------------- # dependencies generated by makedepend WRPRC-2.11/Changes-1.01010066400017710000151000000003720634140471600157350ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 1.01 26 July 1990 Fixed some things in config/imakemdep.h for MIPS systems. Corrected minor problems in top Imakefile. Changed names of Project.{tmpl,ptmpl} to ProjectGroup.{tmpl,ptmpl}. WRPRC-2.11/Changes-1.02010066400017710000151000000001410634140471600157300ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 1.02 25 May 1991 Added Sun support. WRPRC-2.11/Changes-1.03010066400017710000151000000044440634140471600157430ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 1.03 1 July 1991 o There is now an installation document. o Some Sun support was added, as I now have a Sun SPARCstation 2. o A small amount of largely untested HP-UX support was added. This was done some time ago, however, on a pre-snake machine. o StdConfigDir/STDCONFIGDIR and ProjConfigDir/PROJCONFIGDIR were renamed PubConfigDir/PUBCONFIGFIR and PrivConfigDir/PRIVCONFIGDIR to better reflect their functions as directories holding public (system-wide) and private (project-specific) configuration files. Once the distribution has been built and installed, there should be no impact on any other projects. o No longer uses a modified xmkmf. imkmf is used instead, which allows xmkmf from X11R4 to exist unmolested on machines which have it. o Some additional rules and symbols were defined. Of these, the most important is probably BootstrapTarget(). If the WRPRC configuration tools and files are installed, ``make Bootstrap'' should be reasonably portable across platforms and allow bootstrapping even with a Makefile that was configured on some other system. o Default owner and group names used to be defined in the site.def file with the intentions that this would select the defaults for system-owned files and that it could it be modified on a project-specific basis in site.pdef. The problem with this is that system ownership varies on a platform basis, not a site basis. Now the names are defined in platform.cf and can be overridden in platform.pcf. o Further experience with the WRPRC configuration files led to some other changes to imkmf. The original version (mimicking X11R4 xmkmf), tried to determine whether to define UseInstalled based on its arguments. However, sometimes it's useful to be able to force UseInstalled on or off unconditionally, so a -d option was added to force use of the installed programs with -DUseInstalled, and a -u option to force UseInstalled to be undefined. This allows some ugly bootstrapping difficulties to be worked around. imkmf can still be used to bootstrap Makefiles for X programs built outside of the X source tree, provided the compatibility hacks described in the installation document are followed. imkmf was also modified to pass through -D and -U options unchanged. WRPRC-2.11/Changes-1.04010066400017710000151000000005450634140471600157420ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 1.04 16 Dec 1992 o Added -I to imkmf so you can specify project-specific configuration directory other than default of ${TOP}/config. o -d is always the default for imkmf now. Use -u to turn it off. This results in a slight incompatibility with xmkmf (see man page). o Some other stuff. :-) WRPRC-2.11/Changes-1.05010066400017710000151000000022240634140471700157400ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 1.05 28 August 1993 This is the final distribution for Release 1 of the WRPRC imake configuration files. The last distribution that was released for public use was 1.03. I've used 1.04 privately for a while, but now Release 2 has superceded Release 1. The purpose of the current distribution (1.05) is to clean up the configuration files and documents a little, and in general to lay Release 1 to rest. I suppose that in some respects this is an academic exercise. IMPORTANT: the documents, and the configuration files in the config directory are really the central focus of this distribution. All of the programs have been improved elsewhere: - imake and makedepend here are from X11R4; the X11R5 versions are better. - imkmf is now completely obsolete, having been replaced by imboot. - A newer and completely rewritten msub is also now available. The older programs in this distribution have been left as is, to serve as historical curiosities. DO NOT USE THEM! All of the newer programs are available from ftp.primate.wisc.edu in the pub/imake-book directory (get the imake.tar.Z distribution). WRPRC-2.11/Changes-2.00010066400017710000151000000044100634140471700157330ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.00 8 July 1993 The changes from the 1.XX versions of these configuration files are myriad. Some of them are: o Renamed imkmf to imboot to eliminate incompatibility with imkmf program distributed with Khoros. o The distribution no longer builds any programs, and they're all assumed to be already installed. If you need them, there's another distribition you can use to build and install them. This includes imake, xmkmf, imboot, makedepend, soelim, bsdinst, mkdirhier. o Renaming of all private (project-specific) configuration files. For example, site.pdef -> site.p-def, Imake.prules -> Imake.p-rules. Also the ProjectGroup.* files are now Project.* files. o Pulled the system parameters out of Imake.tmpl and created System.tmpl for them. o Pulled the vendor blocks out of Imake.tmpl and created Imake.vb for them. o Yet more renaming of configuration group related parameters. GroupConfigPath -> ConfigRootDir o BootstrapTarget() is invoked near the end of Imake.tmpl to make sure every Makefile has a Bootstrap target. Also, "all" and "depend" targets are generated by default in every Makefile to make it easier to write Makefiles in multiple-directory projects. o Lots of parameters for libraries commonly used at WRPRC. This helps shrink the project-specific Project.p-tmpl files. o Lots of things taken from X11R5: - Uses XCOMM for make-comments, not "/**/#" - Symbol for Mips systems running RISC/os is now Mips, not mipsriscos. Vendor files are Mips.cf/Mips.pcf, not mipsriscos.cf/mipsriscos.pcf. This conforms to X11R5. - Concat(), Concat3(), and Concat4() macros. o Document production rules have been revised. None of them send output directly to the printer anymore. They all write output to a file, which can be previewed and/or printed. Some incompatibities: o ExtraStuffToClean() is obsolete. Use StuffToClean(). o NormalProgramTarget() is being phased out as the general program-building rule. Use BuildProgram() instead. o Installation rules and parameters are different. They're more general, and they work better. Installation rules call mkdirhier first to make sure the directory exists. o InstallUIDProgram() is now InstallUidProgram(). Ditto for the GID and UGID rules. WRPRC-2.11/Changes-2.01010066400017710000151000000033250634140471700157400ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.01 10 August 1993 Some of these changes involve incompatibilities with Release 2.00. I judge that a minor inconvenience since propagation of 2.00 has been minimal. Merged System.tmpl and Project.tmpl into a single file Imake.params. Reorganized Imake.rules to reflect rule grouping a bit better. Eliminated superfluous rules ("superfluous" means I've never used them to configure any WRPRC project). Revision to simplify MakefileSubdirs(), the rule that generates the "Makefiles" target entry. Also fixed a couple of bugs. Dumped the last argument to NamedTargetSubdirs(). In this ruleset it was always the same as the first argument, and therefore superfluous. This makes the 2.00 rule incompatible with the 2.01 rule. BuildNormalLibrary() now takes a source file argument, and generates lint-related target entries. This makes the 2.00 rule incompatible with the 2.01 rule. Renamed UpdateIfChanged() to UpdateIfDifferent(). This makes the 2.00 rule incompatible with the 2.01 rule. RemoveTargetByMoving is no more; thus RemoveTarget() always removes (rather than renames) the target. Added BuildLintLibrary() and InstallLintLibrary() for lint library support. Wrote some documentation describing how to write Imakefiles using these configuration files (tutorial.ms) and a reference to the configuration files themselves (reference.ms). These are still somewhat incomplete, particularly the latter. Added osf1.cf/osf1.p-cf for OSF/1 support. Added testcf directory with Imakefile that can be used to see what kind of configuration values actually get selected on your machine. Build the Makefile with "imboot .." and then type "make". (This is still preliminary.) been minimal. Merged System.tmpl and Project.tmpl into a single file Imake.params. Reorganized Imake.rules to reflect rule grouping a bit better. Eliminated superfluous rules ("superfluous" means I've never used them to configure any WRPRC project). Revision to simplify MakefileSubdirs(), the WRPRC-2.11/Changes-2.02010066400017710000151000000002520634140471700157350ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.02 11 August 1993 Improved reference.ms some. It still has major gaps in the description of Imake.params. WRPRC-2.11/Changes-2.03010066400017710000151000000045300634140471700157410ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.03 22 August 1993 Changed InstLibMode from -m 0444 to -m 0644 since ranlib fails on some systems if library not writable. Changed LDOPTIONS to LDOPTS in Imake.params (since BuildProgram() uses the latter). Revised a bunch of the loader flag variables to allow the STD_XXX, PROJECT_XXX, XXX tertiarity. Involves many changes, such as nuking SYS_LIBRARIES and renaming EXTRA_LIBRARIES and EXTRA_LOAD_FLAGS to STD_EXTRA_LIBS and STD_LDFLAGS. The Makefile-generating rules were changed: - Changed the MakefileSubdirs() rule to run imake in the subdirectory by invoking imboot there rather than make. The latter involves a lot of messing around to set TOP and CURDIR properly. This version is simpler than in 2.02. - Also changed the MakefileTarget() rule to invoke imboot rather than imake. This is essentially what BootstrapTarget() was doing, so the latter has been eliminated. This makes "make Makefile" more portable (particularly when you try to rebuild the Makefiles after moving a distribution to another machine) and there is no longer any need for "make Bootstrap" as a special case. Converting the Makefile-generating rules to use imboot rather than imake has some significant simplifying effects on Imake.params. In particular, since no raw imake commands are generated, it's possible to eliminate the make variables IMAKE, IMAKE_CMD, IMAKE_DEFINES, PUBCONFIGDIR, PRIVCONFIGDIR, and the cpp macros associated with them. Thus, we have a set of imake configuration files that make no explicit reference to imake anywhere! New parameters LocalXXXDir allow specifying local directories in system layout separately from the standard system directories. Thus if you have /usr/local/include, /usr/local/usr/lib, etc., in addition to /usr/include, /usr/lib, etc., you can specify that. For one thing, this allows you to install things in the local directories, but still specify search paths that include the standard directories. Dumped LocalIncludeInstallDir since LocalIncludeRoot now has that function. UpdateIfDifferent() is now an inline macro and is called from the new rule FileFromIntermediar(). Filled in some more gaps in reference.ms. Revised mmf.ms. Relegated the Release 1 documents to R1-docs directory. They're still worth reading, but a bit out of date with respect to Release 2. WRPRC-2.11/Changes-2.04010066400017710000151000000016600634140471700157430ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.04 31 August 1993 Dumped the testcf directory and moved the function of that Imakefile into config/Imakefile. You assess it with "make test" in the config directory. Dumped PreProcessCmd/PREPROCESSCMD. Appears to be vestigial. (Only used a single time in X11R5, and I've never used it in my projects.) CppCmd/CPP is a reasonable substitute. Decoupled ALLINCLUDES from ALLDEFINES. This necessitated a redefinition of LINTFLAGS, CFLAGS, and DependTarget(), all of which reference ALLDEFINES. Changed names of SimscrLib, DepSimscrLib, SeqnumLib, DepSeqnumLib to SimScrLib, DepSimScrLib, SeqNumLib, DepSeqNumLib. Added SpecialCObjectCompile() rule for specifying special compile flags for compiling particular object files. Most of the old tertiary.ms has been absorbed into reference.ms. The remainder was renamed limits.ms. Renamed config/unsupported to config/untested. WRPRC-2.11/Changes-2.05010066400017710000151000000002270634140471700157420ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.05 9 September 1993 Added parameters AWK, SED, COMM, CAT, UNIQ, SORT, CHMOD, and CHDIR. WRPRC-2.11/Changes-2.06010066400017710000151000000017760634140471700157550ustar00junkyarddatamgmt00000400000027Changes to the WRPRC configuration distribution for Release 2.06 26 October 1993 install commands all had -c hardcoded into them. This is now controlled by a parameter InstCopy/INSTCOPY that has a default value of -c, but that can be turned off by redefining InstCopy with an empty value. INSTCOPY is a part of all the install flag combination parameters. Added parameters for TFM (WRPRC Temporary File Manager) library. FakeInstallFile() and FakeInstallLibrary() were changed to not depend on the non-installed target. Otherwise "make install" goes through the work of building the target only to not bother installing it anyway. FakeBuildTarget() added to generate a target entry that just says "This target is not built here." Useful for writing Imakefiles when a target might be built on some machines but not others, e.g.,: #if ServerHost BuildProgram(serverprogram,srcs,objs,libs,deplibs) InstallProgram(serverprogram,$(LOCALETCDIR)) #else FakeBuildFile(serverprogram) FakeInstallFile(serverprogram) #endif WRPRC-2.11/Changes-2.07010066400017710000151000000114700634140471700157460ustar00junkyarddatamgmt00000400000027Changes to the WRPRC2 configuration file distribution -- Release 2.07 16 July 1996 There are some changes to parameters that may affect you in incompatible ways: - Changed ConfigRootDir in config/Imake.params from /usr/lib/config to /usr/local/lib/config. You'll need to change it back if you want to retain the old setting. If you elect to use the changed location, you might want to cp -r /usr/lib/config /usr/local/lib. Then, for each directory under /usr/local/lib/config that isn't a symlink, make sure the value of the ConfigRootDir is changed to /usr/local/lib/config (or, if the files have only ConfigDir, change its value to the new pathname of the directory in which the files are installed). Also, don't forget to change the path to the config root in your installed copy of imboot! - Removed setting of LocalBinDir to /usr/local from config/site.def, so LocalBinDir now reverts to the default value of /usr/local/bin. - Added overrides in site.def for ManRoot and ManSuffix so that man pages are installed under the /usr/local/man hierarchy and the default directory is /usr/local/man/man1. This really doesn't quite square with the comments in Imake.params about the man page parameters describing where the "system" manual pages are located, so I suppose there should be a set of LocalManXXX symbols in addition to the ManXXX symbols. But there isn't, yet. (Also, for systems that put stuff in weird arrangements, like Mips, ManRoot has to be left at /usr/man.) - Renamed vendor-block files Imake.vb and Imake.p-vb to Imake.cf and Imake.p-cf, which is more like the X11R6 conventions. - Renamed the OSMinorMinorVersion symbol to OSTeenyVersion, which is like the X11R6 convention. Other changes either fix bugs or add functionality: - Set the value of StandardLibraries to -lsocket -lnsl -lw on SystemV4 systems by default. This helps more programs compile on such machines without having to add those libraries explicitly in Imakefiles. - Modified Imake.cf and added a mklinuxppc.cf vendor file for MkLinux (Linux on Power Macintosh) support. NOTE: the linux vendor block refers to linux.cf (since I simply copied it out of the MkLinux distribution), but there is no such file here because I have no Linux-on-Intel box to test it on. - Modified Imake.cf and added a Next.cf vendor file for NeXT support. This is supplied by Daniel Green, based on Douglas Scott's work for X11. - Better gcc support, specfically, addition of HasGcc2 macro to distinguish gcc 2.x from earlier versions, and testing of HasGcc* macros in sun.cf. - Added support in sun.cf for SunOS 5.x (Solaris 2.x), which, unlike earlier SunOS versions, is SVR4-based rather than BSD-based. The proper definitions are selected depending on whether or not SVR4 is defined (the SunOS 5.x imake should be built with -DSVR4 in BOOTSTRAPCFLAGS). Can be told to use the SunPro C compiler if you have it. - Added Perl5Cmd, PERL5CMD, Perl5Path and PERL5PATH symbols to config/Imake.params. I also set the local value of Perl5Path to /usr/local/bin/perl5 in site.def. - Reordered the components of EXTRA_LDLIBS to reflect more likely order in which libraries should actually be listed. - Added FiFiiSuffixRule() to config/Imake.rules. - Added FileFromMsubTemplateWithFlags() rule to config/Imake.rules. Complements FileFromMsubTemplate(). - Added HasStdarg macro in Imake.params (similar to HasVarargs). If defined as YES, has the effect of causing -DSTDARG to be added to the value of the VARARGS_DEFINES make variable. Thus, this variable can now be empty, or contain -DSTDARG or -DVARARGS, or both, to indicate the availability of stdarg.h and varargs.h. In general, if both are available, stdarg.h should be preferred over varargs.h. - Added HasUnistdH macro in Imake.params. The unistd.h header file is an ANSI thing, but its presence is independent of whether or not you're using an ANSI compiler. - Modified InstallMultipleDataFiles() rule to concatenate the filename onto the directory name to produce the pathname of the installed file, which is consistent with how the other installation rules work. - Fixed definition of InstallManPage() rule in Mips.cf, which was generating a target of the form i.pagename.dstsuffix, rather than i.pagename.man. - Excised LibraryCcCmd, LibraryCCOptions, LibraryDefines, and OptimizedCDebugFlags macros because they were not being used anywhere. - Wrote a HelpAuxTarget() rule that is invoked from within several target-building rules. HelpAuxTarget() generates a help_aux target that prints a message describing the make command that builds a particular target. Modified the default "help" target in Imake.tmpl to run "make help_aux" to print these messages, and added an empty help_aux target in case there are no others generated by HelpAuxTarget(). The net effect is that "make help" will tell you a lot about how to build the targets listed in the Imakefile. WRPRC-2.11/Changes-2.08010066400017710000151000000027500634140471700157500ustar00junkyarddatamgmt00000400000027Changes to the WRPRC2 configuration file distribution -- Release 2.08 19 July 1996 - Modified Imake.cf and added an ibm.cf vendor file for AIX support. This is based on work done by Shaul Wallach (although (1) he did it some time ago for a different release, and (2) I took out much of the X11-specific stuff, so (3) I'm not sure if I broke anything. I'd like to hear from anyone who uses this distribution under AIX about any successes or failures.) - INCOMPATIBLE CHANGE. Downgraded the SpecialCObjectCompile() rule. It was originally supposed to be modeled after the X11 SpecialCObjectRule() rule, but wasn't really done correctly. (My rule required the object file name (including suffix), the X11 rule didn't.) For now, there is a definition of SpecialCObjectCompile() that maps onto its replacement (see next item). This is for backward compatibility, but the mapping rule will be removed eventually. If you have Imakefiles that use SpecialCObjectCompile(), you should change them. - New rule SpecialObjectTarget() for compiling object files with special flags. It replaces SpecialCObjectTarget(). - New rule SpecialCObjectTarget() for compiling object files from C source with special flags. It doesn't assume a .o suffix, so may be used on non-UNIX systems. - New macro Osuf for specifying a system's object file suffix. The default is "o", as for UNIX. The intent is to help make it easier to write Imakefiles for non-UNIX systems, though there isn't much other support for that here yet. WRPRC-2.11/Changes-2.09010066400017710000151000000050570634140471700157540ustar00junkyarddatamgmt00000400000027Changes to the WRPRC2 configuration file distribution -- Release 2.09 13 December 1996 - Modified Imake.cf and added a FreeBSD.cf vendor file for FreeBSD support. - Modified Imake.cf and added a mklinuxppc.cf vendor file for MkLinux support. - Imake.cf defines SVR4Architecture for Sun now if SVR4 is defined. This can be used to help distinguish SysV vs. BSD Sun systems in sun.p-cf files (can't test OS{Major,Minor,Teeny}Version there because those are set in sun.cf, which is processed after sun.p-cf). - HelpAuxTarget() invocations are now used everywhere it makes sense in Imake.rules. For Makefiles generated using the WRPRC2 configuration files, running "make help" should tell you a lot about what targets can be built and the commands to build them. - INCOMPATIBLE CHANGE. Removed the SpecialCObjectCompile() rule from Imake.rules, as threatened in Changes-2.08. Use SpecialObjectTarget() or SpecialCObjectTarget() instead. - Added PortLib and DepPortLib macros and PORTLIB and DEPPORTLIB variables for the Portability Library. This library provides a consistent interface across systems to operations that tend to vary in ugly ways for different UNIX systems, such as file locking and directory reading. By using the library, programs can use a set of function names that don't vary across systems. - Added SpoolRootDir macro and SPOOLROOTDIR variable. These are usually set to /usr/spool or /var/spool. They make it easier to refer to directories that are located under /usr/spool on some systems and /var/spool on others, by using $(SPOOLROOTDIR). The default is /usr/spool, which is overridden for most newer systems. - Added SendmailPath macro and SENDMAILPATH variable describing the full pathname of sendmail. - Added HasStringH macro. Value is YES if system has string.h, NO if it doesn't (in which case strings.h is assumed to be present). The default value is YES, since most systems have it. (However, I don't know the values for NeXT, Cray, IBM, or OSF/1 systems. If you do, please let me know.) This macro can be used to determine which should be included. E.g., if you define DEFINES in an Imakefile like this: DEFINES = -DHAS_STRING_H=HasStringH Then you can include the correct file like this: #if HAS_STRING_H #include #else #include #endif Alternatively, define the name of the include file in an Imakefile like this: #if HAS_STRING_H STRING_H_FILE= #else STRING_H_FILE= #endif DEFINES = -D'STRING_H_FILE=$(STRING_H_FILE)' In source files, reference the file like this: #include STRING_H_FILE WRPRC-2.11/Changes-2.10010066400017710000151000000044060634140471700157410ustar00junkyarddatamgmt00000400000027Changes to the WRPRC2 configuration file distribution -- Release 2.10 23 May 1997 - INCOMPATIBLE CHANGE: mklinuxppc.{cf,p-cf} are now linux-pmac.{cf,p-cf}. This follows the work of the Linux/PPC folks who now have an X11R6.3 port that works under both MkLinux and Linux/PPC. Any projects that have a private mklinuxppc.p-cf should rename them to linux-pmac.p-cf. Also modified the Linux vendor block in Imake.cf accordingly. - INCOMPATIBLE CHANGE: The TroffToPostScript() macro now has the $(TROFF) and $(TROFFOPTS) variables embedded in the rule, rather than those variables being passed in by the TroffMxxxToPostScript() rules. The third argument therefore is now "flags" rather than "formatter". Actually, this shouldn't cause much problem since the TroffToPostScript() rule should be invoked mainly only through the TroffMxxToPostScript() rules anyway. - Updated OS{Major,Minor,Teeny}Version macros in linux-pmac.cf to reflect that the current Linux/PPC server version is 2.0.28. - Changed Perl5Path in linux-pmac.cf from /usr/local/bin/perl to /usr/bin/perl. - Modified tmac.wrprc since it was causing problems with some versions of groff (e.g., under FreeBSD, MkLinux). - Added MdocMacros macro and MDOCMACROS variable to Imake.params, TroffMdocToPostScript() rule to Imake.rules for -mdoc support. - Added macros and variables for the troffcvt programs. Added rules for converting troff documents to RTF and HTML using the troffcvt programs. - Define PerlPath as /usr/bin/perl in FreeBSD.cf. - Modified Mips.cf to allow usual setting of CcCmd to be overridden if HasGcc2 is YES. - Modified Imake.tmpl to set OSName, OS{Major,Minor,Teeny}Version of DefaultOSName, DefaultOS{Major,Minor,Teeny}Version are set. This may occur if the X11R6.3 version of imake is used, which tries to set those macros by running uname to find out system name and version information. There's no guarantee that version of imake will be the one that's used, but if the information is available, might as well use it. - Top-level Imakefile now has a documents-ps target so that "make documents-ps" generates PostScript versions of all the main documents. - Imake.params defines ProjectWRPRC symbol so that Imakefiles can test it to see whether or not they're being configured with the WRPRC configuration files. WRPRC-2.11/Changes-2.11010066400017710000151000000012120634140471700157320ustar00junkyarddatamgmt00000400000027Changes to the WRPRC2 configuration file distribution -- Release 2.11 23 May 1997 - Added NetBSD support: created NetBSD.cf and NetBSD.p-cf and modified Imake.cf to add a NetBSD vendor block. - Added ColCmd macro and COL variable to support NetBSD's use of col in processing manual pages, which must be installed preformatted. (Actually, they *don't* need to be, at least for NetBSD 1.2.1; but if you install them that way, col is useful.) - Deleted OSVendor from a few vendor.cf files that had it. This got carried in from X11 config files, but the WRPRC files don't use it. - Changed MkdirhierCmd to MkdirHierCmd, which is how X11 spells it. WRPRC-2.11/Comparison010066400017710000151000000005760634140471700161310ustar00junkyarddatamgmt00000400000027Some general improvements of the Release 2 files over the Release 1 files SVR4 support. Better installation support - finer control of installation parameters, support for installing manual pages. Lint support. Lint library support. Better document formatting rules. Better rules for generating targets from templates. Unified interface for building programs. XCOMM support. WRPRC-2.11/ReleaseDates010066400017710000151000000005320634140471700163500ustar00junkyarddatamgmt0000040000002713 Dec 96 Release 2.09 19 Jul 96 Release 2.08 16 Jul 96 Release 2.07 26 Oct 93 Release 2.06 09 Sep 93 Release 2.05 31 Aug 93 Release 2.04 23 Aug 93 Release 2.03 11 Aug 93 Release 2.02 10 Aug 93 Release 2.01 16 Jul 93 Release 2.00 16 Dec 92 Release 1.04 20 Jun 91 Release 1.03 25 May 91 Release 1.02 26 Jul 90 Release 1.01 25 Jul 90 Release 1.00. WRPRC-2.11/limits.ms010066400017710000151000000067710634140471700157410ustar00junkyarddatamgmt00000400000027.\" .\" these macros are used in addition to the -ms macros. .so tmac.wrprc .\" .\" .Ah "Limitations of the WRPRC2 Architecture" .\" .LP The WRPRC2 configuration file architecture explicitly allows for two levels at which configuration information may be specified. However, there are certain limitations inherent to the architecture. It allows no way to specify information that applies only to a given subtree of a project, for instance. And there's no acknowledgment that more than two levels of configuration files might be needed. .LP A fixed number of levels of specification can be implemented using a static structure. For instance, if rule macros can be specified on two levels, you can process two files, one that's specific to the project being configured, and one that provides the general baseline set of rules: .Ps #include \fIProject-specific rule information\fP #include \fIBaseline rule information\fP .Pe However, we don't have a way to dynamically extend the number of levels of file inclusion. We could do so if we could do the following: .B "Describe." .LP But this doesn't work. .B "Say why." .LP .B "Similar problems for make variables (below)." .LP The notion of levels of configuration information specification can be considered more generally. That is, how many and which levels should there be? .LP But the more general problem is more difficult, i.e., how to allow a variable, or arbitrary, number of levels of specification, such that you may not know in advance how many levels there are. You may want to access a set of files, which themselves access other files. You don't necessarily want to know or care about what those other files are. .LP To illustrate: The X11R5 configuration file architecture allows for one level of configuration files. If your project wants to provide its own configuration information, to extend or override the X11 information, that can be difficult. To circumvent this, the X11 architecture can be converted to a two-level architecture similar to that used by the WRPRC2 files. Thus an X project can use the X11 configuration files and provide its own files, too. .LP Motif can be thought of as ``an X project''. And the Motif distribution can then provide its own extension of the baseline X11 configuration information. But what if you're writing a project that uses Motif? Now you have a third level. Hm. What to do? Convert the X11 architecture to allow three levels? That's not a solution, since your project may be intended for use by yet other projects, and then you have four levels. .LP There are similar problems with respect to variable values. For a given number of levels, you can concatenate a fixed number of subsidiary variables: .Ps ALLINCLUDES = $(PROJECT_INCLUDES) $(STD_INCLUDES) .sp .3v ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) .Pe The order of information in variable assignments depends on how the information is used. For .I \-I 's, the parameters are given most-specific first. For .I \-D 's, the parameters are given most-specific last. .LP This illustrates two kinds of information ``stacking'': .Ls B .Li Specification of files to be processed: .Ps #include most-specific \&... #include least-specific .Pe 0 .Li Specification of .I make variable values: .Ps VAR = least-specific ... most-specific .sp .3v VAR = most-specific ... least-specific .Pe 0 .Le .LP Problems. No good mechanism for dynamic extension of file inclusion (late binding). No good mechanism for dynamic extension of variable values (can't redefine in terms of current value). WRPRC-2.11/p-s.ms010066400017710000151000000074410634140471700151320ustar00junkyarddatamgmt00000400000027.\" .\" these macros are used in addition to the -ms macros. .so tmac.wrprc .\" .\" ${TROFF} ${MSMACROS} thisfile | ${PRINTER} .\" .\" revision date - change whenever this file is edited .ds RD 18 June 1996 .\" .EH 'WRPRC2 \fIImakefile\fP Writing'- % -'' .OH ''- % -'WRPRC2 \fIImakefile\fP Writing' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .TL Writing Project-Specific Configuration Files .sp .3v (WRPRC2 imake Configuration Files) .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Revision date:\0\0\*(RD .LP This document describes how to provide project-specific configuration information to extend or override the standard configuration provided by the WRPRC2 configuration files. .LP A separate document serves as a reference describing the contents of the shared configuration files. .\" .Ah "Using Project-Specific Configuration Files" .\" .LP The WRPRC2 configuration files provide ``standard'' configuration rules and parameters by means of a set of files shared among all projects that use them. Sometimes the standard information provided by these files is insufficient to configure a project. The WRPRC2 architecture allows you to provide project-specific information. This is done by allowing projects to create a directory under the project root in which another set of configuration files may be placed as necessary. This section describes some of the ways in which you can use project-specific configuration files to extend or override the base configuration capabilities provided by the shared files. .LP To use project-specific configuration files, create a directory named .I config under the project root. You can then create one or more of the following files in .I config : .Ps Imake.p-params \fRSystem and project parameters\fP site.p-def \fRSite parameters\fP vendor.p-cf \fRVendor parameters\fP Imake.p-rules \fRRule macros\fP Imake.p-cf \fRVendor blocks\fP .Pe If you add a parameter to .I Imake.p-params , you may need to override it for particular systems in the .I *.p-cf files. .\" .Bh "BuildProgram() as a Basis for Other Rules" .\" .LP If you find that you tend to invoke .Cw BuildProgram() in a stereotypical way for several targets within a project, you can use the project's .I Imake.p-rules file to define a new rule that invokes .Cw BuildProgram() for you, perhaps supplying some of the arguments for you. .Cw BuildSimpleProgram() is in fact implemented as an invocation of .Cw BuildProgram() and some other rules. Take a look at its definition to see how you can use .Cw BuildProgram() as a basis for other rules. .LP Do you want installed binaries stripped? If not, override .Cw InstStrip : .Ps #ifndef InstStrip #define InstStrip /**/ #endif .Pe Do you want to specify a particular owner and/or group for installed files? If so, define .Cw InstOwner and/or .Cw InstGroup : .Ps #ifndef InstOwner #define InstOwner -o \f(CIname\fP #endif #ifndef InstGroup #define InstGroup -g \f(CIname\fP #endif .Pe .\" .Ah "Interaction Problems To Watch Out For" .\" .LP You can't set macros in .I vendor.p-cf based on .Cw OSMajorVersion , .Cw OSMinorVersion , or .Cw OSTeenyVersion , because they're not set until after .I vendor.cf is processed. If you .I must make decisions based on the version numbers in .I vendor.p-cf , you must set the version numbers in that file before you test them. Your project instructions should note that people who use the project should verify that the version numbers are set correctly on their own machine. .LP Specifying a parameter in the .Cw After\%VendorCF part of .I site.def is ineffective if vendor files also set the parameter. In such cases, it's better to modify the vendor file, or perhaps to set the parameter in the .Cw Before\%VendorCF part of .I site.def . WRPRC-2.11/reference.ms010066400017710000151000001630140634140471700163700ustar00junkyarddatamgmt00000400000027.\" .\" these macros are used in addition to the -ms macros. .so tmac.wrprc .\" .\" $(TBL) thisfile | $(TROFF) $(MSMACROS) > output .\" .\" revision date - change whenever this file is edited .ds RD 13 December 1996 .\" .EH 'WRPRC2 Configuration File Reference'- % -'' .OH ''- % -'WRPRC2 Configuration File Reference' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .TL WRPRC2 imake Configuration File Reference .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Revision date:\0\0\*(RD .\" .LP This document describes in some detail the contents of the Release 2 WRPRC .I imake configuration files. The first part of this document describes the contents of each of the configuration files. The second part discusses various aspects of their use. A tutorial document is also available that describes how to write Imakefiles that use the WRPRC2 configuration files. .\" .Ah "Imake.tmpl" .\" .LP .I Imake.tmpl is a template file that defines the architecture of the configuration files. It serves to .Cw #include the other configuration files in the correct order, as well as the .I Imakefile from the current directory, and it adds some default .I Makefile target entries. .I Imake.tmpl looks like this: .sp .5v .\".nr PS \n(PS-2 .\".nr VS \n(VS-2 .ps -2 .vs -2 .TS box tab (%) ; l _ l l | l | l l | l | l l _ l l _ l l | l | l l | l | l l | l | l l | l | l l _ l l _ l l | l | l l | l | l l _ l l _ l l | l | l l | l | l l | l | l l | l | l l _ l l _ l l | l | l l | l | l l _ l l _ l l | l | l l | l | l l _ l l _ l l | l | l l _ l l lw(2.2i) s . % .Cw %#include %#include % % %#define BeforeVendorCF %#include %#include %#undef BeforeVendorCF % % %#include ProjectVendorIncludeFile %#include VendorIncludeFile % % %#define AfterVendorCF %#include %#include %#undef AfterVendorCF % % %#include %#include % % %#include %#include % % %#include INCLUDE_IMAKEFILE % .R %default \fIMakefile\fP target entries .TE .br .\".nr PS \n(PS+2 .\".nr VS \n(VS+2 .vs .ps .LP .Cw Project\%Vendor\%Include\%File and .Cw Vendor\%Include\%File are defined in .I Imake.cf as the names of the vendor-specific configuration files appropriate for your system, e.g., .I sun.p-cf and .I sun.cf . .Cw INCLUDE_IMAKEFILE represents the .I Imakefile . .LP Configuration files are processed in pairs. The second member of each pair is a file located in the public configuration directory (e.g., .I /usr/local/lib/config/WRPRC2 ), and is shared among all projects that use the WRPRC2 files. These shared files define the standard baseline configuration provided by the WRPRC2 files. .LP The first member of each pair is a project-specific file. When a project has configuration requirements such that it needs to override (or extend) the baseline information in the public file, it provides the necessary information in the project-specific file in its private .I config directory under the project root (the root directory of the project source tree). To prevent file inclusion errors when a project doesn't provide particular project-specific files, the public directory also contains empty dummy copies of these files. That way, the project provides only those files it needs, and any it does provide take precedence over the dummy copies. .LP The following sections describe primarily the shared files because the default project-specific files are all empty. However, when it's likely you may want to override something in the shared files, that's pointed out. This means that you create a .I *.p-* file in the project's .I config directory and put the information there. You do .I not modify the dummy copy in the public configuration file directory. For instance, if you need to specify HP-specific information for your project, create .I hp.p-cf in your project's .I config directory. Don't modify the .I hp.p-cf file in the .I /usr/local/lib/config/WRPRC2 directory. .\" .Ah "Imake.cf" .\" .LP .I Imake.cf contains vendor blocks that determine the type of system you're using and define the macros .Cw Vendor\%Include\%File and .Cw Project\%Vendor\%Include\%File as the names of the vendor-specific configuration files appropriately. They also define symbols you can test to determine software and/or hardware type if necessary (e.g., in an .I Imakefile ). .LP For instance, the Sun vendor block defines the vendor file names as .I sun.cf and .I sun.p-cf . It defines .Cw Sun\%Architecture (meaning the software is SunOS), and, depending on the hardware type, defines one of the symbols .Cw Sparc\%Architecture , .Cw Sun3\%Architecture , or .Cw i386\%Architecture . .LP If you port the WRPRC2 configuration files to a new platform, you must make sure there's an appropriate vendor block in .I Imake.cf and write a vendor file. .\" .Ah "site.def" .\" .LP .I site.def contains site-specific definitions. This file is the primary candidate for modification when you install the WRPRC2 files, because you use it to express preferences for parameters such as your usual directory for installing user programs, etc. (You leave most of the other configuration files alone.) .LP The project-specific file .I site.p-def can be used when you want to override parameters on a site-specific basis for a particular project. Example: If .Cw Local\%Bin\%Dir is set in .I site.def at your site to .I /usr/local/bin , but you want to install programs built by a particular project into your own .I bin directory .I /u/you/bin instead, you could put the following in the project's .I site.p-def : .Ps #ifndef LocalBinDir #define LocalBinDir /u/you/bin #endif .Pe 0 .\" .Bh "Overriding Values in site.def" .\" .LP .I site.def and .I site.p-def are each split into two parts, like this: .Ps #ifdef BeforeVendorCF /* stuff processed before vendor file */ #endif /* BeforeVendorCF .sp .3v #ifdef AfterVendorCF /* stuff processed after vendor file */ #endif /* AfterVendorCF .Pe Definitions are usually added to the .Cw After\%VendorCF part of the site files. However, if you're trying to specify a parameter that's already defined in a vendor file, a definition in the .Cw After\%VendorCF part of a site file will be overridden by the definition in the vendor file. Consider whether or not this is what you want. If not, then perhaps you should specify the parameter in the .Cw Before\%VendorCF part of the site file instead. Alternatively, modify the value in the vendor file. .\" .Ah "vendor.cf" .\" .LP Other than .I Imake.cf , files with names of the form .I *.cf are vendor-specific files, e.g., .I sun.cf , .I ultrix.cf , .I osf1.cf . They're used to override the defaults for parameters specified in .I Imake.params when those defaults are incorrect. .LP A vendor file might also override the default definition of rules specified in .I Imake.rules if rules don't work properly on a given system. For example, .I Mips.cf overrides .Cw Install\%Man\%File() , the rule that installs manual pages. Under Mips RISC/os, manual pages must be installed already .I nroff 'ed, rather than in source form. So the rule is defined to run the manual page through .I nroff and install the result. An additional complication is that .I nroff does not by default come with RISC/os. Consequently, the rule is defined as a null operation if .I nroff isn't present on the system. .LP Project-specific .I *.p-cf files are usually used when you define new project parameters in .I Imake.p-params but need to override defaults for a particular platform. This is analogous to the way .I *.cf files override defaults specified in .I Imake.params . .\" .Ah "Imake.params" .\" .LP This file specifies default values for the general system and project parameters. Usually a parameter value is expressed as a .I cpp macro set to a default value that can be overridden in vendor or site files, and a .I make variable set to the value of the macro. For example: .Ps #ifndef MvCmd #define MvCmd mv #endif .sp .3v MV = MvCmd .Pe .I Imake.params contains several kinds of information, described in the following sections. .\" .Bh "General System Characteristics, Feature Symbols" .\" .LP This section describes the system type in broad terms and lists some particular features the system either does or doesn't have. The symbols .Cw SystemV and .Cw SystemV4 indicate whether or not your system is based on System V Release 2 or 3, or System V Release 4. The default for both is .Cw NO (i.e., not based on System V at all). If that is incorrect for your system, override the defaults by defining the appropriate symbol as .Cw YES in the vendor file. .LP The .Cw Has\fIXXX\fP symbols indicate whether or not your system possesses certain capabilities or features. The defaults should be overridden in the vendor file as necessary. .\" .Bh "Configuration File and Project Information" .\" .LP The symbols in this section describe the name, location, and release number of the WRPRC2 configuration files, the name and release number of the project, and the location of the project's private configuration files. .LP .Cw Config\%Root\%Dir must be the same as the value used by .I imboot for the configuration file root directory (the directory under which sets of configuration files are installed). Check your copy of .I imboot to see where it expects this directory to be. If .Cw Config\%Root\%Dir in .I Imake.params is incorrect for your system, override it in .I site.def . .LP The project name and release defaults are meaningless .Cw no-project-name "" ( and .Cw 0 ). Override them in the project's private .I Imake.p-params if you want them to be accurate for your project. .\" .Bh "General System Layout" .\" .LP This section defines things such as program, library, and administrative directories. One set of parameters describes the standard system layout \*- where such things as libraries, administrative files, user programs, and temporary files are found or created. However, many sites maintain a second set of directories into which locally installed files are put. For instance, you may put locally installed libraries and header files into .I /usr/local/lib and .I /usr/local/include . To accommodate this, another set of parameters describes the ``local'' system layout. .LP In general, when you write Imakefiles, you should use the local parameters because you can redefine them on a per-project basis in .I Imake.p-params or .I site.p-def without changing where the standard system directories are expected to be. .LP .Cw Adm\%Dir .IP Directory for administrative programs and files. Default .I /usr/adm . .LP .Cw Bin\%Dir .IP The usual user program directory, default .I /usr/bin . .LP .Cw Etc\%Dir .IP Directory for servers and system maintenance tools. Default .I /usr/etc ; likely override value .I /etc . .LP .Cw Include\%Root .IP Top of system include file hierarchy. Default .I /usr/include . .LP .Cw Lint\%Lib\%Dir .IP Directory for lint libraries. Default .I /usr/lib/lint . .LP .Cw Tmp\%Dir .IP Directory for creation of temporary files. Default .I /tmp ; likely override values are .I /usr/tmp or .I /var/tmp . .LP .Cw UsrLibDir .IP Directory for libraries and library files. Default .I /usr/lib . .LP .Cw LocalRootDir .br .Cw LocalAdmDir .br .Cw LocalBinDir .br .Cw LocalEtcDir .br .Cw LocalIncludeRoot .br .Cw LocalLintLibDir .br .Cw LocalUsrLibDir .IP Local directories corresponding to standard system directories. .Cw Local\%Root\%Dir is the root of the local directory hierarchy. The others are defined in terms of it, so you can move all of them by redefining it. To move just some of them, redefine individual .Cw Local\%\fIXXX\fP\%Dir parameters. If you want to make these directories equivalent to the corresponding standard system directories, define .Cw Local\%Bin\%Dir as .Cw $(BINDIR) , .Cw Local\%Usr\%Lib\%Dir as .Cw $(USRLIBDIR) , etc. .\" .Bh "Manual Page Directory Layout" .\" .LP The parameters in this section define the layout of the manual page hierarchy on your system. In the simplest (default) case, this consists simply of the .I man? directories under .I /usr/man . Some systems are more complex; see .I Mips.cf for an example. .LP .Cw Man\%Root defines the root of the manual page hierarchy. .Cw Man\%Source\%Path defines the name used to construct manual page section directories. The names of the individual directories are constructed by concatenating .Cw Man\%Source\%Path with a suffix. The suffixes are given by the .Cw Man?Suffix parameters, and the directory names are given by the .Cw Man?Dir parameters, where .I ? is 1, 2, 3, 4, 5, 6, 7, 8, .I l (el), or .I n . The parameters .Cw Man\%Suffix and .Cw Man\%Dir indicate the ``usual'' suffix and directory (where user program manual pages are typically installed on your system. .LP There is no .Cw Local\%Man\%Root , just .Cw Man\%Root . This is because the manual page hierarchy already includes sections for local stuff .I manl "" ( and .I mann ). On the other hand, you may want to install local stuff into an entirely separate manual page hierarchy, e.g., under .I /usr/local/man . If so, override .Cw Man\%Root in .I site.def and set .Cw Man\%Suffix to .Cw $(MANSUFFIX) . .\" .Bh "Programs and Flags" .\" .LP This section defines parameters for programs like the C compiler, the loader, .I rm , etc., and flags that they use. .LP The complexity of .Cw CFLAGS is worthy of note; its structure is discussed a bit in the section "The Program-Building Model." .\" .Bh "Installation Support" .\" .LP This section defines parameters for installing various kinds of files. .Cw Install\%Cmd is the name of the program for installing things. By default it's .I install . That's suitable if your .I install is the BSD version, but if you have a System V .I install , .Cw Install\%Cmd is overridden as .I bsdinst or .I install.sh (shell scripts that emulate BSD behavior). .LP The other installation parameters define install flags and combinations of flags. The single flags are listed below. These are all .I cpp macros and all have corresponding uppercase .I make variables. .LP .Cw InstCopy .IP Flag for whether to copy file without removing original. Default is .I \-c ; override as the empty value if you want originals removed. This takes less disk space, but forces more rebuilds after install operations. .LP .Cw InstStrip .IP Flag for stripping executable binaries. Default is .I \-s ; override as the empty value if you don't want binaries stripped (which takes more space, but allows better debugging). .LP .Cw InstOwner .br .Cw InstGroup .IP Owner and group names of installed files. The defaults are empty, since it's hard to choose good default ownerships that make sense across different systems. If you want files to be owned by a particular user or group, override the defaults. Note that you must include the .I \-o or .I \-g options with the name if you specify non-empty values: .Ps #ifndef InstOwner #define InstOwner -o \f(CIname\fP #endif #ifndef InstGroup #define InstGroup -g \f(CIname\fP #endif .Pe Also note that ownership specifications likely will be ineffective if you're not .I root when you install files. .LP .Cw InstProgMode .br .Cw InstUidProgMode .br .Cw InstGidProgMode .br .Cw InstUGidProgMode .br .Cw InstScriptMode .br .Cw InstLibMode .br .Cw InstDatMode .br .Cw InstManMode .br .Cw InstIncMode .IP Mode flags for installing programs, setuid programs, setgid programs, setuid/setgid programs, executable scripts, libraries, data (non-executable) files, manual pages, and include (header) files. Installation of setuid and/or setgid programs may be ineffective unless you are .I root if you are not the installed owner and/or group. .LP The parameters below specify combinations of flags and provide a convenience notation for concatenating common groups of flags. All of them reference .Cw INST\%OWNER and .Cw INST\%GROUP , and all the flags for executable binaries reference .Cw INST\%STRIP . In addition, each references a mode parameter for the appropriate type of file. .LP .Cw InstProgFlags .br .Cw InstUidProgFlags .br .Cw InstGidProgFlags .br .Cw InstUGidProgFlags .br .Cw InstScriptFlags .br .Cw InstLibFlags .br .Cw InstDatFlags .br .Cw InstManFlags .br .Cw InstIncFlags .IP Installation flags for installing programs, setuid programs, setgid programs, setuid/setgid programs, executable scripts, libraries, data (non-executable) files, manual pages, and include (header) files. .\" .Bh "Document Preparation" .\" .LP This section defines parameters for programs used to format documents, such as .I troff , .I tbl , and .I soelim , and parameters for common .I troff macro packages. .\" .Bh "WRPRC Libraries" .\" .LP At WRPRC, several locally-developed libraries are commonly used to build programs. The WRPRC2 configuration files provide link and dependency specifiers for them. The following table lists the specifiers provided by the WRPRC2 configuration files. For every library .Ci XXX , there is an .Ci XXX\f(CWLib\fP variable for link purposes and a .Ci \f(CWDep\fPXXX\f(CWLib\fP variable for dependency purposes. There are .I make variables corresponding to each of these, which is what you refer to in Imakefiles. .br .ne 1.5i .ps -1 .vs -1 .TS tab(:); lfB | lfB | lfB lfB | lfB | lfB l | lfCW | lfCW . Library:Link:Dependency Name:Specifier:Specifier _ \fIrefer\fP record manipulation library:BibStuffLib:DepBibStuffLib Exception and termination manager library:EtmLib:DepEtmLib Form processing library:FplLib:DepFplLib Form query library:FqlLib:DepFqlLib GECOS library:GecosLib:DepGecosLib Simple log manager library:LogMgrLib:DepLogMgrLib Simple memory manager library:MemMgrLib:DepMemMgrLib Network database service library:NdsLib:DepNdsLib Network I/O library:NioLib:DepNioLib Order processing library:OrderLib:DepOrderLib Sequence number library:SeqNumLib:DepSeqNumLib Simple screen-management library:SimScrLib:DepSimScrLib Temporary file manager library:TfmLib:DepTfmLib Token scanning library:TsLib:DepTsLib _ .TE .vs +1 .ps +1 .sp .5v By default, the link specifiers are of the form .I \-lname and the dependency specifiers are empty. This reflects the assumption that all the libraries are installed in a system directory (e.g., .Cw LOCAL\%USR\%LIB\%DIR ) on your machine. If you have a project that builds one of these libraries, you'll notice that it has an .I Imake.p-params file that overrides the specifiers for that particular library to point into the project tree. That's because the project can't assume the library is installed, and if it also builds applications that use the library, it must find the library within the project. .LP You'll also notice that the link specifier includes a reference to .Cw LOADER\%LIB\%PREFIX . Link libraries are typically specified in one of two ways, either by pathname or using .I \-l notation (e.g., .I \-lmylib ). When a library is specified using a pathname, on most systems the pathname is sufficient. However, on Cray systems running UNICOS, it's necessary to use .I \-l even for libraries specified by pathname. Thus, to write a reference to a library specified by pathname, you write it like this: .Ps $(LOADERLIBPREFIX)$(TOP)/lib/libmylib.a .Pe The variable .Cw LOADER\%LIB\%PREFIX gets its value from the macro .Cw Loader\%Lib\%Prefix , which is normally empty. The default reflects that no prefix to the pathname is necessary in most cases. But .I cray.cf defines the macro as .I \-l so the proper flag precedes the path. This is a good example of how the exigencies of one kind of system can affect the way you write configuration files. .\" .Ah "Imake.rules" .\" .LP The main function of .I Imake.rules is to define macros that generate .I Makefile target entries. .LP One motif that appears throughout the WRPRC2 rules is the implementation of rules in terms of other rules. One form of this is the construction of a rule as a concatentation of invocations of other rules. Another form is the implementation of groups of similar rules in terms of a single underlying general-purpose rule. An example of rule concatenation is .Cw Build\%Program() , which invokes .Cw All\%Target() , .Cw Remove\%Target() , .Cw Stuff\%To\%Clean() , and .Cw Lint\%Sources() . An example of use of a general-purpose rule is .Cw Install\%Man\%File() , which provides a general interface to manual page installation. All the other man page installation rules are defined in terms of .Cw Install\%Man\%File() . .LP The reasons this technique is used so much are: (i) to avoid writing a construct as the same literal text over and over when a rule is simpler to invoke; (ii) when a bug is found in a construct, it's easier to fix the rule that generates it than to fix multiple literal instances of the text; (iii) it's easier to change the behavior of rules that use the construct (e.g., by providing an alternate definition in a vendor file). .\" .Bh "Non-Rule Macros" .\" .LP .I Imake.rules defines some macros which are not rules. .LP .Cw NullArg .IP This macro evaluates to nothing. Use it in rule invocations to specify an empty argument. (Don't just leave an argument empty, because some .I cpp 's complain or fail when an argument is expected but none is specified.) .LP .Cw NullParameter .IP Like .Cw Null\%Arg ; provided to satisfy X11 habits. .LP .Cw DirFailPrefix .IP This macro is normally empty, but may be defined as .Cw - for those systems which have a shell that doesn't evaluate the following constructs properly: .Ps if [ -d ] ... if [ ! -d ] ... .Pe Normally .Cw Dir\%Fail\%Prefix is defined in vendor files as necessary, and is not of concern to the .I Imakefile writer. .\" .Bh "Rule Macros" .\" .LP Rules are listed by sections, paralleling the layout by which .I Imake.rules is organized. Within sections, rules are described in the order they appear within .I Imake.rules , rather than alphabetically. .\" .Bh "Directory-Making Rules" .\" .LP .Cw MakeDir(\f(CIdir\fP) .IP .Cw MakeDir() generates commands to check whether the given directory exists and to create it if not. This rule is used tab-indented as a command line; it's usually used within other rule definitions, rather than in Imakefiles. .LP .Cw MakeDirectories(\f(CItarget,dirs\fP) .IP This rule generates a target entry .Ci target that creates the named directories if they don't exist. Unlike .Cw Make\%Dir() , the rule may be used standalone, so it's suitable for use in Imakefiles. .\" .Bh "Rules for Building Executable Programs" .\" .LP .Cw BuildProgram(\f(CIprog,srcs,objs,linklibs,deplibs\fP) .IP .Cw BuildProgram() is the general interface for building programs. It generates entries to build, remove, and lint a single program, and it may be invoked multiple times in the same .I Imakefile . .sp .5v .Ci prog is the program name, .Ci srcs and .Ci objs list the program's source and object files, .Ci linklibs lists the libraries needed to link the program, and .Ci deplibs lists the libraries to check as dependencies. Dependency libraries must be given as pathnames. .sp .5v .Cw BuildProgram() produces several targets. A .Ci prog target builds the program. An .Cw all target builds the program and any others in the .I Imakefile . A .Cw clean target removes the program and cleans up, .Cw lint.\f(CIprog\fP .I lint 's the sources for .Ci prog , and .Cw lint .I lint 's the sources for all programs in the .I Imakefile . .LP .Cw BuildSimpleProgram(\f(CIname,linklibs,deplibs\fP) .IP .Cw BuildSimpleProgram() is a simplified version of .Cw BuildProgram() that makes a number of assumptions, namely that you want to build a single program consisting of a single source file .Ci name\fI.c\fP , that the manual page, if there is one, is named .Ci name\fI.man\fP , and that you want to install the program in .Cw LOCAL\%BIN\%DIR and the manual page in .Cw MAN\%DIR . .Cw link\%libs and .Cw dep\%libs are as for .Cw Build\%Program() . .sp .5v .Cw BuildSimpleProgram() sets the .I make variables .Cw SRCS and .Cw OBJS , invokes .Cw Build\%Program() , as well as installation and manpage installation rules, and invokes .Cw Depend\%Target() . .sp .5v .Cw BuildSimpleProgram() may be invoked only once per .I Imake\%file , and should not be used with any other program or library-building rules. .sp .5v If you want to install the program in a different directory, you can assign a different value to .Cw LOCAL\%BIN\%DIR in the .I Imake\%file : .Ps LOCALBINDIR = /some/other/directory .sp .3v BuildSimpleProgram(prog,NullArg,NullArg) .Pe 0 .LP .Cw SpecialObjectTarget(\f(CIdst,src,flags,depends\fP) .IP This rule allows you to specify special flags for compiling a particular object file. .Ci dst is the object file name, .Ci src is the source file name, .Cw flags is the special flags to use when compiling it, and .Ci depends is any special dependencies for .Ci obj (other than .Ci src ). .LP .Cw SpecialCObjectTarget(\f(CIbasename,flags,depends\fP) .IP This rule allows you to specify special flags for compiling a particular object file from a C source file. .Ci basename is the object file basename (no extension), .Cw flags is the special flags to use when compiling it, and .Ci depends is any special dependencies for the object files .Ci obj (other than then source file). .Cw Special\%CObject\%Target() determines the name of the source file as \f(CIbasename\f(CW.c\fR and the name of the object file using the suffix appropriate for your system (e.g., .Cw \&.o for UNIX and .Cw \&.obj for Windows NT. .\" .Bh "Library-Building Rules" .\" .LP The WRPRC2 rules support only ``normal'' (static) libraries; there is no support for shared, debugging, or profiled libraries. .LP .Cw NormalLibraryObjectRule() .IP This rule redefines the .I .c \(-> .I .o transformation .I make uses to compile C source files for building objects in libraries. It should be invoked exactly once in any .I Imakefile in which you invoke .Cw BuildNormalLibrary() . Since this rule may change the default transformation, it's best not to build programs and libraries in the same directory. .LP .Cw BuildNormalLibrary(\f(CIname,srcs,objs\fP) .IP .Cw BuildNormalLibrary() generates a target entry to build a library from the named object files. When you use it, invoke .Cw Normal\%Library\%Object\%Rule() as well. .sp .5v .Ci name is the library basename (e.g., for a library .I libxxx.a , the basename is .I xxx ). .Ci srcs and .Ci objs list the library's source and object files. .sp .5v A .Cw lib\f(CIname\fP.a target is produced that builds the library. An .Cw all target builds all libraries in the .I Imake\%file . A .Cw clean target cleans up. .Cw lint.lib\f(CIname\fP.a and .Cw lint targets lint the sources for the .Ci name library and all libraries in the .I Imakefile , respectively. .LP .Cw BuildLintLibrary(\f(CIname,srcs\fP) .IP Build a .I lint library for the given library based on the given source files. .Ci srcs should name the same file as the .Ci srcs argument to .Cw Build\%Normal\%Library() . .sp .5v Generates .Cw llib-l\f(CIname\fP.ln and .Cw lintlib targets that build the .Ci name .I lint library and .I lint library for all libraries in the .I Imakefile , respectively, and a .Cw clean target to clean up. .\" .Bh "Rules for Building Targets by Running Templates through Filters" .\" .LP The WRPRC2 rules allow you to generate files from templates by running them through some filter program to process the template. The filter may be arbitrary, but for convenience, rules are provided that assume either .I msub or .I cpp as the filter. .LP The output file may be either executable (i.e., scripts) or non-executable. Executable scripts may be produced that, when run, are executed by an arbitrary script processor (not just the shell). .LP For all the rules, .Ci dst is the target file to produce, .Ci src is the input template, and .Ci deps names any dependencies that must exist before processing the template. For those rules that take a .Ci filter argument, it's the filter program that should process the template. For those rules that take a .Ci prog argument, it's the processor that executes the output script when it's run. .Ci prog must be a full pathname. .LP Rules that build executable scripts act differently according to whether .Cw Has\%Execable\%Scripts is .Cw YES or .Cw NO . If it's .Cw YES , the rule writes a line like this at the beginning of the script, where .Ci prog is the script processor: .Ps #!\f(CIprog\fP .Pe If .Cw Has\%Execable\%Scripts is .Cw NO , the rule writes a shell script that writes your script to a temporary file, passes the file to the script processor as a separate command, and removes the file. This means the script template contains no .Cw #! line at the beginning. It's added if necessary by the rule that generates the script. (This contrasts, for instance, with the X11 rules to generate scripts from .I cpp templates. For those rules, the .Cw #! line must be present in the template and is removed if necessary.) .\" .LP .Cw FileFromTemplate(\f(CIdst,src,filter,deps\fP) .IP Produce a non-executable file from a template. .LP .Cw ScriptFromTemplate(\f(CIprog,dst,src,filter,deps\fP) .IP Produce an executable script from a template. .LP .Cw FileFromMsubTemplate(\f(CIdst,src,deps\fP) .IP Produce a non-executable file from a template, assuming .I msub as the filter program. .LP .Cw ScriptFromMsubTemplate(\f(CIprog,dst,src,deps\fP) .IP Produce an executable script from a template, assuming .I msub as the filter program. .LP .Cw ShScriptFromMsubTemplate(\f(CIdst,src,deps\fP) .IP Produce an executable script from a template, assuming .I msub as the filter program and the shell as the script processor. .LP .Cw ScriptFromMsubTemplateWithFlags(\f(CIprog,dst,src,flags,deps\fP) .br .Cw ShScriptFromMsubTemplateWithFlags(\f(CIdst,src,flags,deps\fP) .IP Like .Cw Script\%From\%Msub\%Template() and .Cw ShScript\%From\%Msub\%Template() , but these rules allow you to specify flags that are passed to .I msub . This is useful when you want to redefine the variable reference delimiters that .I msub recognizes. (See the .I msub manual page.) .LP .Cw FileFromCppTemplate(\f(CIdst,src,defs,deps\fP) .IP Produce a non-executable file from a template, assuming .I cpp as the filter program. .Ci defs contains any .I \-D 's or .I \-U 's you want to pass to .I cpp . .LP .Cw ScriptFromCppTemplate(\f(CIprog,dst,src,defs,deps\fP) .IP Produce an executable script from a template, assuming .I cpp as the filter program. .Ci defs is as for .Cw File\%From\%Cpp\%Template() . .LP .Cw ShScriptFromCppTemplate(\f(CIdst,src,defs,deps\fP) .IP Produce an executable script from a template, assuming .I cpp as the filter program and the shell as the script processor. .Ci defs is as for .Cw File\%From\%Cpp\%Template() . .\" .Bh "Miscellaneous Target-Building Rules" .\" .LP .Cw BuildFakeFile(\f(CItarget\fP) .IP Generates a target entry that simply announces that target isn't built. .LP .Cw LinkTarget(\f(CItarget,linkto\fP) .IP Generates a target entry .Ci target that creates a link .Ci target to the file .Ci linkto . .LP .Cw FileFromIntermediary(\f(CIdst,inter,src\fP) .IP Generates .Ci inter from .Ci src , then updates .Ci dst if .Ci dst differs from .Ci inter or doesn't exist. Otherwise does not update .Ci dst . (See also the .Cw Update\%If\%Changed() rule.) .LP .Cw SimpleWorldTarget(\f(CIproject,release\fP) .IP Generates a simple .Cw World target entry so that you can say .I make .I World to build your entire project from scratch. Used only in the .I Imakefile in the project's root. .sp .5v The .Cw World target is preceded by an empty .Cw all target so that .Cw all rather than .Cw World is the default target if no other rule precedes .Cw Simple\%World\%Target() in the .I Imakefile (which might be the case for a multiple-directory project). .sp .5v Caveat: This rule uses a simple configure-clean-depend-build model of project building. If your project has any special requirements, you'll probably need to write your own .Cw World entry. .\" .Bh "Installation Rules" .\" .LP Generally, the installation rules make use of the .Cw INST*FLAGS parameters, although there is no requirement for this. You can invoke .Cw Install\%File() and pass it any set of flags you want, e.g., for a .I root "" setuid- program, you can write this: .Ps InstallFile(install,myprog,myprog,$(LOCALETCDIR),-o root $(INSTUIDMODE) $(INSTSTRIP)) .Pe See the section that describes the .I Imake.params file for a discussion of the installation parameters that are available. .LP For all installation rules, the destination directory is created if it doesn't exist. That means if you're in any doubt about where targets will be installed, it's prudent to run .I make .I \-n .I install (or .I make .I \-n .I install.man ) before you run .I make .I install (or .I make .I install.man ). .LP .Cw InstallFile(\f(CItarget,dstfile,srcfile,dir,flags\fP) .IP This rule is the general interface for installing files other than manual pages. Most other installation rules are trivial and simply invoke .Cw Install\%File() with arguments appropriate for different types of files. .sp .5v .Ci target is the name of the target to produce, typically .Cw install . .Ci dstfile is the name of the installed file, .Ci srcfile is the name of the file to install, .Ci dir is the directory in which to install the file, and .Ci flags is the installation flags. .sp .5v Besides the .Ci target target, an .Ci \f(CWi.\fPdstfile target is generated so that you can install individual files. Typically .Ci target is .Cw install so that .I make .I install installs everything. .sp .5v Generally, .Ci dstfile and .Ci srcfile are identical. Two parameters are provided so you can install a file and rename it at the same time if you want. However, none of the rules in .I Imake.rules do so. You can provide such a rule in .I Imake.p-rules if your project requires it. .LP .Cw InstallProgram(\f(CIfile,dir\fP) .IP Install an executable (binary) program. .LP .Cw InstallUidProgram(\f(CIfile,dir\fP) .IP Install a setuid executable (binary) program. .LP .Cw InstallGidProgram(\f(CIfile,dir\fP) .IP Install a setgid executable (binary) program. .LP .Cw InstallUGidProgram(\f(CIfile,dir\fP) .IP Install a setuid/setgid executable (binary) program. .LP .Cw InstallScript(\f(CIfile,dir\fP) .IP Install an executable script. Differs from .Cw Install\%Program() in that the flag for stripping binaries isn't passed to .I install . Some versions of .I install complain if they're told to strip non-binary executables. .LP .Cw InstallDataFile(\f(CIfile,dir\fP) .IP Install a non-executable file. .LP .Cw InstallIncludeFile(\f(CIfile,dir\fP) .IP Install a C header file. .LP .Cw InstallLibrary(\f(CIname,dir\fP) .IP Install a library (as .Ci \fIlib\fPname\fP.a ), and run .I ranlib on the installed image if you have it on your system. .LP .Cw InstallLintLibrary(\f(CIname,dir\fP) .IP Install a .I lint library (as .Ci \fIllib-l\fPname\fP.a ). Generates targets .Cw install.lint and .Cw i.llib-l\f(CIname\fP.a . The former installs all .I lint libraries in the directory, the latter installs only .Ci \fIllib-l\fPname\fP.a . .LP .Cw InstallLink(\f(CItarget,linkto,dir\fP) .IP Make a link from .Ci dir/target to .Ci dir/linkto . .LP .Cw InstallMultipleDataFiles(\f(CItarget,files,dir\fP) .IP Install a set of non-executables named by .Ci files into .Ci dir . .Ci target is the name of the target entry, usually .Cw install . .\" .Ch "Rules for Installing Manual Pages" .\" .LP .Cw InstallManFile(\f(CItarget,name,dstsuffix,dir\fP) .IP This is the general interface for manual page installation. .Cw target is the name of the target entry, usually .Cw install.man . In addition, an .Cw i.\f(CIname\fP.man entry is generated so you can install individual manual pages. .Ci name is the name of the manual page. The manual page file must end with a .I .man suffix, but you specify the name in the rule without the suffix. .Ci dstsuffix is the suffix to be given to the installed manual page. .Ci dir is the directory in which to install the manual page. It's created if it doesn't exist. .LP .Cw InstallMan1Page(\f(CIfile\fP) .br .Cw InstallMan2Page(\f(CIfile\fP) .br .Cw InstallMan3Page(\f(CIfile\fP) .br .Cw InstallMan4Page(\f(CIfile\fP) .br .Cw InstallMan5Page(\f(CIfile\fP) .br .Cw InstallMan6Page(\f(CIfile\fP) .br .Cw InstallMan7Page(\f(CIfile\fP) .br .Cw InstallMan8Page(\f(CIfile\fP) .br .Cw InstallManLPage(\f(CIfile\fP) .br .Cw InstallManNPage(\f(CIfile\fP) .IP Install a manual page in the section 1, 2, 3, 4, 5, 6, 7, 8, .I l (el, for local), or .I n directory. .LP .Cw InstallManPage(\f(CIfile\fP) .IP Install a manual page in the ``usual'' manual page directory. By default, this is section .I l (el), but may be different at your site. It's changed by changing the value of .Cw MAN\%SUFFIX . .\" .Ch "Pseudo-Installation Rules" .\" .LP These rules generate .Cw install target entries that simply announce the target isn't installed anywhere. This has the function of making it explicit in the .I Imake\%file that the target is not intended to be installed, and that you didn't just forget to invoke an installation rule in the .I Imake\%file . .LP .Cw FakeInstallFile(\f(CIfile\fP) .IP Generate a fake .Cw install target for a file. Also generates an .Ci \f(CWi.\fPfile entry. .LP .Cw FakeInstallLibrary(\f(CIname\fP) .IP Generate a fake .Cw install target for a library. Also generates an .Cw i.lib\f(CIname\fP.a entry. .\" .Bh "Rules That Generate Recursive Target Entries" .\" .LP The rules in this section generate target entries that run a given .I make operation in a set of subdirectories. They're convenient for constructing directory-traversing operations. Executed in a project root, they will traverse the entire project tree. Executed in some subdirectory of the project, they will traverse the project subtree under that subdirectory. .LP Many of these rules are invoked automatically by the last section of .I Imake.tmpl and thus need not be invoked in individual Imakefiles. .LP .Cw NamedTargetSubdirs(\f(CIop,dirs,verb,flags\fP) .IP This rule is the general interface to recursive entry generation; it's invoked by most of the other recursive rules to do the work. .Ci op is the .I make operation to generate a recursive entry for, .Ci dirs names the directories to process, .Ci verb is the word that .I make uses to announce what it's doing as it processes the entry (e.g., ``cleaning'', ``installing''), and .Ci flags is any flags that should be passed to .I make in subdirectories. .sp .5v Note: The WRPRC version of .Cw Named\%Target\%Subdirs() is like the X11 rule of the same name, but has one fewer argument. .LP .Cw MakeSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw all target entry for building targets. .LP .Cw DependSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw depend target entry for generating header-file dependencies. .LP .Cw InstallSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw install target entry for installing programs and other non-manual-page files. .LP .Cw InstallManSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw install.man target entry for installing manual pages. .LP .Cw CleanSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw clean target entry for removing garbage files. .LP .Cw TagSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw tags target entry for generating .I TAGS files. .\" .Bh "Makefile-Generating Rules" .\" .LP .Cw MakefileTarget() .IP Generates a .Cw Makefile target entry to rebuild the .I Make\%file in the current directory. This rule invokes .I imboot , which is more portable than generating an .I imake command, since .I imboot takes care of knowing where the configuration file directories are on your machine. As such, .I make .I Make\%file usually works to bootstrap a .I Make\%file even when you move a project to a different machine, which would not be true were the entry to invoke .I imake directly. .LP .Cw MakefileSubdirs(\f(CIdirs\fP) .IP Generate a recursive .Cw Make\%files target entry for building Makefiles. The operation of this is described in a later section. .\" .Bh "Document-Formatting Rules" .\" .LP These rules generate target entries that process .I troff documents to produce PostScript files, which reflects my preferred output format. It would be easy enough to adapt the rules to produce plain text, RTF, etc., or to send the output directly to a printer. .LP .Cw TROFF\%OPTS may be set on the .I make command line to pass additional options to .I troff . For instance, if you want to format only pages 7 through 10 of a document, you can do this: .Ps % make doc.ps "TROFFOPTS=-o7-10" .Pe .Cw TroffToPostScript(\f(CIdst,src,formatter,filters,deps\fP) .IP This rule is the general interface to document processing. .Ci dst is the name of the output file, .Ci src is the name of the input file or files, .Ci formatter is the formatting program and its options (usually some .I troff program), .Ci filters names any preprocessors, and .Ci deps names any dependencies that must exist before processing the document. .sp .5v .Ci filters can either be .Cw Null\%Arg if there are no preprocessors, or else a piece of a command pipeline such as .Cw |$(TBL) or .Cw |$(TBL)|$(EQN) . Note the use of the .Cw | character; if non-empty, .Ci filters must begin with one. .sp .5v This rule generates a .Ci dst target to produce the formatted output file, and a .Cw clean target to remove it. .LP .Cw TroffManToPostScript(\f(CIdst,src,filters,deps\fP) .br .Cw TroffMeToPostScript(\f(CIdst,src,filters,deps\fP) .br .Cw TroffMmToPostScript(\f(CIdst,src,filters,deps\fP) .br .Cw TroffMsToPostScript(\f(CIdst,src,filters,deps\fP) .IP These rules simply invoke .Cw Troff\%To\%Post\%Script() , passing their arguments to it and adding the appropriate macro package argument .I \-man , ( .I \-me , .I \-mm , or .I \-ms ). .\" .Bh "Odds and Ends" .\" .LP .Cw RemoveTarget(\f(CItarget\fP) .IP This rule generates commands to remove the target (a file). This rule is used tab-indented as a command line; it's usually used within other rule definitions, rather than in Imakefiles. .LP .Cw RanLibrary(\f(CIargs\fP) .IP This rule generates commands to run .I ranlib if it exists on your system, or an empty command otherwise. .Ci args lists any flags to be passed to .I ranlib . This rule is used tab-indented as a command line; it's usually used within other rule definitions, rather than in Imakefiles. .LP .Cw UpdateIfDifferent(\f(CIdst,src\fP) .IP Updates .Ci dst from .Ci src if .Ci dst doesn't exist or is different than .Ci src . Otherwise does nothing. This rule is used tab-indented as a command line; it's usually used within other rule definitions, rather than in Imakefiles. .LP .Cw StuffToClean(\f(CIstuff\fP) .IP This rule generates a .Cw clean entry with .Ci stuff as the dependency (multiple files may be listed). It is used in rules that build targets that should be removed when .I make .I clean is executed. You can invoke it explicitly in your .I Imakefile to make sure a given file is removed when the .Cw clean operation is performed. .LP .Cw AllTarget(\f(CItarget\fP) .IP This rule generates an .Cw all entry with .Ci target as the dependency. It is used in rules that build targets which should be built when .I make .I all is executed. It may be used in an .I Imakefile to indicate additional targets you want to make sure get built when the .Cw all operation is performed. .LP .Cw LintSources(\f(CIprog,srcs\fP) .IP Generates a .Cw lint.\f(CIprog\fP target entry to run the sources for .Ci prog through .I lint . .Ci srcs should name the program's source files. Also generates a .Cw lint target entry; .I make .I lint runs .I lint for all programs in the .I Imake\%file . .LP .Cw DependTarget() .IP Generates a .Cw depend target entry to generate header-file dependencies. .I make .I depend should be run after building or rebuilding the .I Makefile . .sp .5v This rule assumes the .I make variable .Cw SRCS is set to the names of the source files to be processed. .LP .Cw CleanTarget() .IP Generates a .Cw clean target entry to remove garbage files. This is invoked by .I Imake.tmpl , so you don't need to. The files that are removed are defined by .Cw Files\%To\%Clean . .LP .Cw TagsTarget() .IP Generates a .Cw tags target entry to create a .I TAGS file. .LP .Cw FiFiiSuffixRule() .IP Generates a suffix rule describing the transformation used to run .I figen to produce a .I .fii file from a .I .fi file. You should invoke this one with no arguments in any .I Imakefile which builds targets that need .I .fii files. You should also do two other things. First, make sure that the .Cw depend target causes any .I .fii files you need to be generated. You can do that like this: .Ps depend:: file1.fii file2.fii ... .Pe Second, make sure the .I .fii files are removed by .I make .I clean : .Ps StuffToClean(*.fii) .Pe 0 .\" .LP .Cw HelpAuxTarget(\f(CItarget\fP,\fPdescription\fP) .IP The intent of the .Cw Help\%Aux\%Target() rule is to help generate Makefiles that are ``self-documenting'' in the sense that the user can run the command: .Ps % \f(CBmake help\fP .Pe and find out what .I make commands build what targets. .IP This rule generates a .Cw help_aux target entry that prints a message describing the .I make command that builds .Ci target . For example, the following invocation: .Ps HelpAuxTarget(myprog,build the myprog program) .Pe generates a target entry that, when .I make .I help is run, prints the message: .Ps \&'make myprog' to build the myprog program .Pe .Cw Help\%Aux\%Target() is invoked from within most of the WRPRC2 target-generating rules. You can use it within your own rules to help users discover how to build the targets produced by the rules. .\" .Ah "How the WRPRC2 MakefileSubdirs() Rule Works" .\" .LP The .Cw MakefileSubdirs() rule is the trickiest rule in .I Imake.rules . Briefly, it works like this: for every directory it operates on, it changes from the current directory (the parent) into the subdirectory (the child), generates a .I Makefile there, runs .I make .I Makefiles with the new .I Makefile in case the child has subdirectories of its own, then returns to the parent directory. .LP Changing directories is relatively easy. A .I cd changes into the child, and the return to the parent is achieved by enclosing within parentheses the .I cd and the commands that run in the child, so that the commands run in a subshell. This way the .I cd applies only in the subshell and the current directory again becomes the parent when the subshell terminates. .LP The .I Makefile in the child is generated by running .I imboot and passing to it the values of the project root directory and the current directory within the project that are correct for the child. These are derived from the values of .Cw TOP and .Cw CURRENT_DIR in the parent directory. If .Cw TOP is an absolute path, then the value in the child is the same as the value in the parent. However, if .Cw TOP is a relative path from the parent to the project root, its value must be adjusted by prepending the path from the child to the parent. .LP The adjustment value is .Cw ../ '', `` .Cw ../../ '', `` .Cw ../../../ '', `` or .Cw ../../../../ '', `` depending on how many levels below the parent the child is located. The adjustment is determined from how many .Cw / '' `` characters are in the subdirectory's name. One complication is that if the name begins with .Cw ./ '', `` then that .Cw / '' `` doesn't count. .LP The location of the child within the project is easy to derive. .Cw CURRENT_DIR is the location of the parent within the project, so the location of any child .I xyz is .Cw $(CURRENT_DIR)\fI/xyz\fP . .LP Note that child directory names passed to .Cw MakefileSubdirs() must be specified as relative paths from the parent or this rule will not work. (But it would be absurd to specify them as absolute paths, anyway.) .LP The WRPRC2 .Cw MakefileSubdirs() rule is simpler than its counterpart in X11 Releases 1\-5. Of course, by using .I imboot , the rule incurs the cost of invoking an additional shell script. However, some difficulties are avoided. For example, some alternative approaches are to invoke .I imake directly, or to run .I make recursively to execute a subsidiary target that itself generates an .I imake command. The success of either approach hinges on getting the values of the macros .Cw TOPDIR and .Cw CURDIR set properly in the child so that .Cw TOP and .Cw CURRENT_DIR are correct. Conceptually this is no different than figuring out the proper values of the project root and the current directory to pass to .I imboot in the child, but in practice is more difficult because it involves heavy interaction between use of .I make variables to set .I cpp macros and vice-versa. Using .I imboot involves none of this. An additional complication is that if the .I imake command specifies a configuration directory located within the project (i.e., specified in terms of .Cw TOP ), the .I \-I argument giving that location must usually be adjusted, too. This is ugly because the adjustment value must be inserted into the middle of the argument. .LP An additional simplification gained by using .I imboot involves the handling of existing Makefiles. Typically, .I Makefile -generating operations remove any existing .I Makefile.bak , then rename any existing .I Makefile to .I Makefile.bak before generating a new .I Makefile . If the .I Makefile target entry generates an .I imake command itself, it must also take care of this removing and renaming. This is unnecessary when .I imboot is used instead, since .I imboot handles .I Makefile and .I Makefile.bak itself. (The X11R5 rule .Cw Make\%Nsubdir\%Make\%files() illustrates clearly why you want the removing and renaming stuff in .I imboot and not in your .I Makefile .) .\" .Ah "The Program-Building Model" .\" .LP A program is built by compiling its source files, then linking the resulting object files together (along with any libraries that may be needed) to produce the final executable. This section explains the model used by the WRPRC2 files to implement this process, with particular emphasis on compilation and loader parameters. .\" .Bh "Compilation Parameters" .\" .LP The model for compiling C object files looks like this: .Ps $(CC) $(CFLAGS) -c file.c .Pe The .I make variable .Cw CFLAGS indicates several types of information, but you don't set .Cw CFLAGS directly. Instead, you set the parameters that .Cw CFLAGS is defined in terms of. Two types of parameters of general interest are .I \-I 's to specify where to look for include files, and .I \-D 's and .I \-U 's to define or undefine macros. The configuration parameters for these are shown in the table below. Mixed-case parameter names are .I cpp macros and uppercase names are .I make variables. .sp .5v .ps -1 .vs -1 .TS tab(:); cfB | cfB | cfB | cfB cfB | cfB | cfB | cfB l | lfCW | lfCW | lfCW . Type of:Global:Per-project:Per-Directory Information:Parameters:Parameters:Parameters _ Include files:StandardIncludes:ProjectIncludes \^:STD_INCLUDES:PROJECT_INCLUDES:INCLUDES _ Defines:StandardDefines:ProjectDefines \^:STD_DEFINES:PROJECT_DEFINES:DEFINES _ .TE .vs +1 .ps +1 .sp .5v For instance, to specify include file directories, values may be assigned to the .I make variables .Cw STD_INCLUDES , .Cw PROJECT_INCLUDES , and .Cw INCLUDES . The three parameters are related, but have different functions: .Ls B .Li .Cw STD_INCLUDES is intended as a global parameter. It's the most far-reaching and applies to all projects configured with the WRPRC2 files. .Cw STD_INCLUDES gets its value from .Cw Standard\%Includes , which should be given a default value that's appropriate for your system when you install the configuration files. You might, for instance, keep locally-installed header files under .Cw LOCAL\%INCLUDE\%ROOT rather than under the standard include hierarchy root. This is information that's likely to be needed by many or most projects compiled on your system. To make sure that .Cw \fI\-I\fP$(LOCALINCLUDEROOT) is passed to all .I cc commands that compile source files, .Cw StandardIncludes can be written like this: .Ps #ifndef StandardIncludes #define StandardIncludes -I$(LOCALINCLUDEROOT) #endif .Pe That is in fact the default value given in .I Imake.params in the WRPRC2 distribution. If you need to pass other directories in addition to .Cw LOCAL\%INCLUDE\%ROOT , e.g., .I /var/include , override the default value of .Cw Standard\%Includes in .I site.def : .Ps #ifndef StandardIncludes #define StandardIncludes -I$(LOCALINCLUDEROOT) -I/var/include #endif .Pe Or, if you install local include files in the usual system include hierarchy (not recommended), you can redefine .Cw Standard\%Includes to be empty: .Ps #ifndef StandardIncludes #define StandardIncludes /**/ #endif .Pe 0 .Li .Cw PROJECT_INCLUDES is intended to specify include directories particular to a given project. It applies in every directory of your project. Its value comes from .Cw Project\%Includes , which is empty by default. If necessary, override the default in .I Imake.p-params in your project's .I config directory. .sp .5v For instance, if your project has project-specific header files in .I include under the project root, you might write something like this to make sure the directory is passed to all compiler commands for the project: .Ps #ifndef ProjectIncludes #define ProjectIncludes -I$(TOP)/include #endif .Pe 0 .Li .Cw INCLUDES is intended to specify include directories that are particular to an individual directory. You assign it a value directly in the directory's .I Imakefile : .Ps INCLUDES = -I\f(CIsomedir\fP .Pe 0 .Le For specifying .I \-D 's and .I \-U 's, the three parameters .Cw STD_DEFINES , .Cw PROJECT_DEFINES , and .Cw DEFINES are used. They're given values in a manner very similar to the way you specify include directory parameters. The defaults for the project- and .I Imakefile -specific parameters are empty. The default value of .Cw Standard\%Defines is .Cw -DSYSV or .Cw -DSVR4 if your system is SVR2/SRV3 or SVR4, respectively, or empty if it's not based on System V. If .Cw Standard\%Defines needs to have a value that is different than the default, it's generally defined in your vendor file when you install the configuration files, rather than in .I site.def . That's because defines needed on a system-wide basis tend to reflect peculiarities of your vendor's compiler rather than characteristics of your site's file system layout. .LP Parameters for include directories and defines become part of the value of .Cw CFLAGS . Since the .I Imakefile is most specific, parameters specified in it should have the highest priority. Conversely, the global parameters are least specific, so parameters specified there should have the lowest priority. Project-specific parameters are in between. .LP For include directory parameters, earlier .I \-I 's on a .I cc command take precedence over later ones, so, within the value of .Cw CFLAGS , include file parameters are ordered like this: .Ps $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) .Pe On the other hand, later .I \-D 's and .I \-U 's take precedence over earlier ones, so defines are ordered like this: .Ps $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) .Pe 0 .\" .Bh "Loader Parameters" .\" .LP The model for linking executable programs looks like this: .Ps $(CC) -o prog objects loader-flags link-libraries extra-libraries .Pe .Cw prog , .Cw objects , and .Cw link-libraries generally come from the invocation of the rule that builds the program (e.g., see the .Cw Build\%Program() rule). .Cw loader-flags and .Cw extra-libraries come from the configuration files. .Ls B .Li .Cw loader-flags specifies any special flags the loader needs in order to produce a final executable. For example, the linker looks for libraries in certain system directories by default. If you keep local libraries somewhere other than those directories, you need to specify search directories for the linker using .I \-L arguments. .Li .Cw extra-libraries is used to compensate for compatibility problems or library deficiencies on your system. For example, a non-BSD version of UNIX may allow programs that use BSD functions to be built by providing a BSD compatibility library (accessed, e.g., as .I \-lbsd ). This means on some systems you must add .I \-lbsd to the link command. .sp .5v .Cw extra-libraries is not intended to be use for specifying libraries that you know you'll need on all platforms. For instance, if you're building a program .I myprog using .Cw Build\%Simple\%Program() and you know you'll need to link in the ETM library, specify that like this: .Ps BuildSimpleProgram(myprog,$(ETMLIB),$(DEPETMLIB)) .Pe 0 .Le Like includes and defines, loader flags and extra libraries may be specified at three levels, as summarized in the following table. .sp .5v .ps -1 .vs -1 .TS tab(:); cfB | cfB | cfB | cfB cfB | cfB | cfB | cfB l | lfCW | lfCW | lfCW . Type of:Global:Per-project:Per-Directory Information:Parameters:Parameters:Parameters _ Loader flags:StandardLoadFlags:ProjectLoadFlags \^:STD_LDFLAGS:PROJECT_LDFLAGS:LDFLAGS _ Extra libraries:StandardLoadLibs:ProjectLoadLibs \^:STD_LDLIBS:PROJECT_LDLIBS:LDLIBS _ .TE .vs +1 .ps +1 .sp .5v Loader flags are given in the same order as include directories (i.e., .I Imakefile -specific first, global last): .Ps $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) .Pe Extra libraries are specified after other libraries, .I Imakefile -specific libraries first: .Ps $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) .Pe .Cw Standard\%Load\%Flags and .Cw Standard\%Load\%Libs are normally specified in the shared configuration files. .Cw Project\%Load\%Flags and .Cw Project\%Load\%Libs are given empty default values in the shared files; they're intended to be overridden as necessary in the project-specific configuration files. .Cw LDFLAGS and .Cw LDLIBS may be specified in individual Imakefiles on a directory-specific basis. .\" .Ah "Tertiarities in the WRPRC2 Architecture" .\" .LP The WRPRC2 configuration file architecture (that is, the order in which configuration files are processed, and the locations in which to look for them) is designed explicitly to allow for a two-level specification of information: a standard baseline configuration specified by the shared files in the public directory, and project-specific configuration information specified in private files in the project's .I config directory. .LP However, the discussion in the previous section illustrates that in some instances there is allowance for a tertiary (three-level) configuration specification, e.g., in the way you specify include-file directories and preprocessor defines. The third level in these cases is .I Imakefile , per- that is, you can specify directories or defines that apply within a given .I Imakefile but nowhere else. but in practice is more difficult because it involves heavy interaction between use of .I make variables to set .I cpp macros and vice-versa. Using .I imboot involves none of this. An additional complication is that if the .I imake command specifies a configuration directory located within the project (i.e., specified in terms of .Cw TOP ), the .I \-I argument giving that location must usually be adjusted, too. This is ugly because the adjustment value must be inserted into the middle of the argWRPRC-2.11/tutorial.ms010066400017710000151000000545570634140471700163100ustar00junkyarddatamgmt00000400000027.\" .\" these macros are used in addition to the -ms macros. .so tmac.wrprc .\" .\" $(TBL) thisfile | $(TROFF) $(MSMACROS) > output .\" .\" revision date - change whenever this file is edited .ds RD 15 July 1996 .\" .EH 'WRPRC2 \fIImakefile\fP Writing'- % -'' .OH ''- % -'WRPRC2 \fIImakefile\fP Writing' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .TL Writing Imakefiles Using the .sp .3v WRPRC2 Configuration Files .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Revision date:\0\0\*(RD .LP This document is a tutorial showing how to write Imakefiles using Release 2 of the WRPRC imake configuration files. It explains the more commonly used rules and parameters and provides example Imakefiles illustrating how to use them. .LP The tutorial doesn't cover all of the rules and parameters that are available. A separate document serves as a reference describing the contents of the individual configuration files. .\" .Ah "Imakefile Writing" .\" .LP To use .I imake , you write an .I Imakefile containing descriptions of targets you want to build. Then you use .I imake to generate a .I Makefile from the .I Imakefile (typically by running the .I imboot bootstrapper, which runs .I imake for you.) The .I Imakefile is a machine-independent description of your targets. .I imake generates the properly configured machine-dependent .I Makefile that's appropriate for your system. Once you have the .I Makefile , you run .I make to build your targets. .LP To generate the initial .I Makefile from an .I Imakefile , use .I imboot : .Ps % \f(CBimboot -C WRPRC2\fP \f(CItopdir\fP .Pe .Ci topdir is the location of the project root directory, specified either relative to your current directory or as an absolute path. If you are in the project root, .Ci topdir may be omitted. .I imboot runs .I imake for you with the appropriate arguments for selecting the WRPRC2 configuration files. .LP If you edit an .I Imakefile thereafter, you must rebuild the .I Makefile so it reflects the changes. If you've already got a .I Makefile , you can use it to rebuild itself with the following command: .Ps % \f(CBmake Makefile\fP .Pe If your changes to the .I Imakefile are erroneous and result in an unusable .I Makefile , fix the .I Imakefile and use .I imboot again to regenerate a working .I Makefile . .LP If your directory has subdirectories, use this command to build the Makefiles in those directories: .Ps % \f(CBmake Makefiles\fP .Pe If you're writing C programs, you should regenerate header file dependencies each time you rebuild a .I Makefile : .Ps % \f(CBmake depend\fP .Pe Makefiles generated from the WRPRC2 configuration files automatically contain a .Cw help target entry. This means you can run the following command to find out how to build the other targets listed in the .I Make\%file : .Ps % \f(CBmake help\fP .Pe 0 .\" .Ah "Building and Installing Programs" .\" .LP This section describes the rules provided by the WRPRC2 configuration files for building programs and libraries. .\" .Bh "Building a Single Program" .\" .LP To build a single program that consists of one source file, use .Cw BuildSimpleProgram() . This rule takes three arguments: .Ps BuildSimpleProgram(\f(CIprog\fP,\f(CIlinklibs\fP,\f(CIdeplibs\fP) .Pe The first argument is the name of the program; .Cw BuildSimpleProgram() assumes there is a single source file named .Ci prog\fI.c\fP and a single object file .Ci prog\fI.o\fP . The second argument names the libraries needed to link the program, and the third names the libraries the program depends on. .LP If a program uses no libraries, the .I Imakefile looks like this: .Ps BuildSimpleProgram(myprog,NullArg,NullArg) .Pe This specifies you want to build a program .I myprog . The second and third arguments are empty, which is specified explicitly using .Cw NullArg . The symbol .Cw NullArg evaluates to nothing; it's preferable to leaving the arguments empty because that causes problems building the .I Makefile on some systems. .LP If a program uses libraries, you need to specify what they are. The libraries the program depends on are the same as the link libraries, but the value of .Ci deplibs is often different than .Ci linklibs because .Ci deplibs can consist only of libraries that can be named as pathnames .I make "" ( understands pathnames only as dependencies, not libraries specified using .I \-l syntax). A system library is usually specified using .I \-l and thus has no dependency specifier. .LP Suppose a program uses the math library, you can write the .I Imakefile like this: .Ps BuildSimpleProgram(myprog,-lm,NullArg) .Pe The math library is specified as .I \-lm for linking, but since it's a system library, there's no dependency specifier for it and .Ci deplibs is empty. .LP Suppose a program needs a library .I mylib that's located in the .I lib directory under the project root. You can refer to it as .Cw $(TOP)\fI/lib/libmylib.a\fP , because .Cw TOP always refers to the top of the project tree. Since that reference is a pathname, you can use it not only for linking, but for dependency purposes as well: .Ps BuildSimpleProgram(myprog,$(TOP)/lib/libmylib.a,$(TOP)/lib/libmylib.a) .Pe .Cw BuildSimpleProgram() can be invoked only once per .I Imakefile . It generates target entries for the following operations: .Ps % \f(CBmake\fP \f(CIprog\fP \fRBuild program\fP % \f(CBmake\fP \fRSame as \f(CWmake\fP \f(CIprog\f(CW % \f(CBmake all\fP \fRSame as \f(CWmake % \f(CBmake clean\fP \fRRemove object and executable files\fP % \f(CBmake lint\fP \fRRun sources through \fIlint\f(CW % \f(CBmake install\fP \fRInstall program\fP % \f(CBmake install.man\fP \fRInstall program's manual page\fP .Pe The .Cw install target installs the program in the directory named by .Cw LOCALBINDIR , which by default is your site's normal installation directory for user programs. The .Cw install.man target installs the manual page in the directory named by .Cw MANDIR , (your site's normal directory for user program manual pages) with the suffix named by .Cw MAN\%SUFFIX . Of course, the .Cw install.man target entry only works if you write a manual page; if you do, name it .Ci prog\fI.man\fP . .LP Note that for all installation operations, the installation directory is created if it doesn't exist. That means it's prudent to run .I make .I \-n .I install (or .I make .I \-n .I install.man ) before you run .I make .I install (or .I make .I \-n .I install.man ), to see where your files will be installed. If the installation directories are somewhere other than what you expect or intend, you need to redefine .Cw Local\%Bin\%Dir and/or the manual page installation location macros in the configuration files. Alternatively, you can redefine the .Cw LOCAL\%BIN\%DIR or the .Cw MAN\%DIR and .CW MAN\%SUFFIX .I make variables on the command line: .Ps % \f(CBmake install LOCALBINDIR=/var/local/bin\fP % \f(CBmake install.man MANDIR=/var/local/man/man1 MANSUFFIX=1\fP .Pe .\" .Bh "Building and Installing Multiple Programs" .\" .LP The general-purpose interface for building programs is .Cw BuildProgram() . You can invoke this rule any number of times in an .I Imakefile , so it's suitable for building an arbitrary number of programs in a single directory. .LP Suppose you're building three programs .I proga , .I progb , and .I progc . Your .I Imakefile might look like this: .Ps BuildProgram(proga,proga.c,proga.o,NullArg,NullArg) BuildProgram(progb,bmain.c bfuncs.c,bmain.o bfuncs.o,-lm,NullArg) BuildProgram(progc,progc.c,progc.o,NullArg,NullArg) .Pe The arguments to .Cw BuildProgram() are the program name, the program's source and object files, and the program's link and dependency libraries. .LP There are certain improvements we can make to the .I Imakefile . For one thing, we can make the the rule invocations more readable by using .I make variables to hold the source and object file lists, and the link and dependency libraries. Then we refer to the variables in the invocations: .Ps ASRCS = proga.c AOBJS = proga.o ALIBS = DEPALIBS = .sp .3v BSRCS = bmain.c bfuncs.c BOBJS = bmain.o bfuncs.o BLIBS = -lm DEPBLIBS = .sp .3v CSRCS = progc.c COBJS = progc.o CLIBS = DEPCLIBS = .sp .3v BuildProgram(proga,$(ASRCS),$(AOBJS),$(ALIBS),$(DEPALIBS)) BuildProgram(progb,$(BSRCS),$(BOBJS),$(BLIBS),$(DEPBLIBS)) BuildProgram(progc,$(CSRCS),$(COBJS),$(CLIBS),$(DEPCLIBS)) .Pe These changes also make the .I Imakefile easier to edit. .LP .Cw BuildProgram() generates target entries for the following operations: .Ps % \f(CBmake\fP \f(CIprog\fP \fRBuild a single program\fP % \f(CBmake all\fP \fRBuild all programs\fP % \f(CBmake\fP \fRSame as \fPmake\fP \fPall % \f(CBmake clean\fP \fRRemove object and executable files\fP % \f(CBmake lint\fP \fRRun sources through \fRlint\f(CW % \f(CBmake lint.\f(CIprog\f(CW \fRRun \f(CIprog\fP sources through \fIlint\f(CW .Pe The commands .I make or .I make .I all build all programs in the .I Makefile , whereas .I make .Ci prog builds only .Ci prog . This is useful when you don't want to build everything. Similarly, .I make .I lint runs the source files for all programs through .I lint , whereas .I make .Ci \fIlint.\fPprog lints only the sources for .Ci prog . This is useful when you make a change to the sources for only one program and don't want to .I lint everything. .LP .Cw BuildProgram() doesn't generate any .Cw depend target, so we should invoke .Cw DependTarget() to do that. .Cw DependTarget() implicitly assumes the .I make variable .Cw SRCS is set to the names of all the source files for which dependencies should be generated. It's convenient to set .Cw SRCS to the concatenation of the variables used to name the sources for individual programs: .Ps ASRCS = proga.c AOBJS = proga.o ALIBS = DEPALIBS = .sp .3v BSRCS = bmain.c bfuncs.c BOBJS = bmain.o bfuncs.o BLIBS = -lm DEPBLIBS = .sp .3v CSRCS = progc.c COBJS = progc.o CLIBS = DEPCLIBS = .sp .3v SRCS = $(ASRCS) $(BSRCS) $(CSRCS) .sp .3v BuildProgram(proga,$(ASRCS),$(AOBJS),$(ALIBS),$(DEPALIBS)) BuildProgram(progb,$(BSRCS),$(BOBJS),$(BLIBS),$(DEPBLIBS)) BuildProgram(progc,$(CSRCS),$(COBJS),$(CLIBS),$(DEPCLIBS)) .sp .3v DependTarget() .Pe Note that .Cw DependTarget() shouldn't be invoked before the program-building rules or .Cw depend will become the default target. .LP No installation target entries are generated by .Cw BuildProgram() . To install a program, invoke .Cw InstallProgram() : .Ps InstallProgram(\f(CIprog\fP,\f(CIdir\fP) .Pe .Ci prog is the name of the program and .Ci dir is the directory in which to install it. .Cw LOCALBINDIR can be used to install the program in your site's ``usual'' user program installation directory. For example: .Ps InstallProgram(proga,$(LOCALBINDIR)) .Pe .Cw InstallProgram() generates target entries for the following operations: .Ps % \f(CBmake install\fP \fRInstall all programs built by the \fIMakefile\f(CW % \f(CBmake i.\f(CIprog\f(CW \fRInstall only \f(CIprog\f(CW .Pe If you write a manual page for .Ci prog , name it .Ci prog\fI.man\fP and invoke .Cw InstallManPage() : .Ps InstallManPage(\f(CIprog\fP) .Pe Note that you specify only the program name (without the .I .man suffix). .Cw InstallManPage() generates target entries for the following operations: .Ps % \f(CBmake install.man\fP \fRInstall manual pages for all programs built by the \fIMakefile\f(CW % \f(CBmake i.\f(CIprog\fP.man\f(CW \fRInstall manual page only for \f(CIprog\f(CW .Pe Manual pages are installed in your site's ``usual'' directory for user program manual pages. .LP After modifying the .I Imakefile to add installation rules for our programs and manual pages, it looks like this: .Ps ASRCS = proga.c AOBJS = proga.o ALIBS = DEPALIBS = .sp .3v BSRCS = bmain.c bfuncs.c BOBJS = bmain.o bfuncs.o BLIBS = -lm DEPBLIBS = .sp .3v CSRCS = progc.c COBJS = progc.o CLIBS = DEPCLIBS = .sp .3v SRCS = $(ASRCS) $(BSRCS) $(CSRCS) .sp .3v BuildProgram(proga,$(ASRCS),$(AOBJS),$(ALIBS),$(DEPALIBS)) InstallProgram(proga,$(LOCALBINDIR)) InstallManPage(proga) .sp .3v BuildProgram(progb,$(BSRCS),$(BOBJS),$(BLIBS),$(DEPBLIBS)) InstallProgram(progb,$(LOCALBINDIR)) InstallManPage(progb) .sp .3v BuildProgram(progc,$(CSRCS),$(COBJS),$(CLIBS),$(DEPCLIBS)) InstallProgram(progc,$(LOCALBINDIR)) InstallManPage(progc) .sp .3v DependTarget() .Pe 0 .\" .Bh "Building and Installing a Library" .\" .LP The WRPRC2 configuration files provide support only for building static libraries. There is no support for shared libraries. .LP To build a library, invoke .Cw BuildNormalLibrary() , passing it the library basename and the source file and object file lists. (If a library's name is .I libxyz.a , the basename is .I xyz ). You should invoke .Cw NormalLibraryObjectRule() in conjunction with .Cw BuildNormalLibrary() so that .I .o files are built in a way suitable for libraries. You should also set the .I make variable .Cw SRCS and invoke .Cw DependTarget() so that .I make .I depend works. Thus, a typical library-building .I Imakefile looks like this: .Ps OBJS = ... SRCS = ... .sp .3v NormalLibraryObjectRule() BuildNormalLibrary(name,$(SRCS),$(OBJS)) DependTarget() .Pe .Cw NormalLibraryObjectRule() may redefine the default .I .c \(-> .I .o transformation that .I make uses to produce object files, so it's best not to build programs in a directory that's used to build a library or libraries. .LP .Cw BuildNormalLibrary() generates target entries for the following operations: .Ps % \f(CBmake lib\f(CIname\fP.a\f(CW \fRBuild library \fP\f(CIname\f(CW % \f(CBmake all\fP \fRBuild all libraries\fP % \f(CBmake\fP \fRSame as \f(CWmake\fP \fPall % \f(CBmake clean\fP \fRRemove object and library files\fP % \f(CBmake lint\fP \fRRun all sources through \fIlint\f(CW % \f(CBmake lint.lib\f(CIname\fP.a\f(CW \fRRun sources for library \f(CIname\fP through \fIlint\f(CW .Pe .Cw BuildNormalLibrary() does not generate any installation target entries; use .Cw Install\%Library() to install a library: .Ps InstallLibrary(\f(CIname\fP,\f(CIdir\fP) .Pe The .Ci dir parameter is often .Cw LOCALUSRLIBDIR , which by default is .I /usr/local/lib . .Cw InstallLibrary() generates entries for the following operations: .Ps % \f(CBmake install\fP \fRInstall all libraries\fP % \f(CBmake i.lib\f(CIname\fP.a\f(CW \fRInstall only library \f(CIname\f(CW .Pe You can invoke .Cw BuildNormalLibrary() any number of times to build an arbitrary number of libraries. Example: .Ps OBJS1 = ... SRCS1 = ... .sp .3v OBJS2 = ... SRCS2 = ... .sp .3v SRCS = $(SRCS1) $(SRCS2) .sp .3v NormalLibraryObjectRule() .sp .3v BuildNormalLibrary(lib1,$(SRCS1),$(OBJS1)) InstallLibrary(lib1,$(LOCALUSRLIBDIR)) .sp .3v BuildNormalLibrary(lib2,$(SRCS2),$(OBJS2)) InstallLibrary(lib2,$(LOCALUSRLIBDIR)) .sp .3v DependTarget() .Pe Note that you invoke .Cw NormalLibraryObjectRule() just once. .\" .Ah "Other Installation Rules" .\" .LP The WRPRC2 files provide a number of installation rules besides .Cw Install\%Program() , .Cw Install\%Library() , and .Cw Install\%Man\%Page() . Some of the more common ones are: .Ps InstallScript(file,dir) \fRInstall an executable script\fP InstallDataFile(file,dir) \fRInstall a non-executable file\fP InstallIncludeFile(file,dir) \fRInstall a header file\fP .Pe You can install manual pages in directories other than the ``usual'' directory. To install a page explicitly in the directory for a given manual section, invoke .Cw InstallMan\f(CIS\fPPage() , where .Ci S is 1, 2, 3, 4, 5, 6, 7, 8, L, or N. As with .Cw InstallManPage() , the name of the file to be installed should end in a .I .man suffix, but the argument to the rule does not include the suffix. The installed manual page will be renamed appropriately for the directory into which it's installed. .\" .Ah "Naming WRPRC Libraries" .\" .LP At WRPRC, several locally-developed libraries are commonly used to build programs. The WRPRC2 configuration files provide link and dependency specifiers for them. The following table lists the specifiers provided by the WRPRC2 configuration files. For every library .Ci XXX , there is a .Ci XXX\f(CWLIB\fP variable for link purposes and a .Ci \f(CWDEP\fPXXX\f(CWLIB\fP variable for dependency purposes. .ps -2 .vs -2 .TS tab(:); lfB | lfB | lfB lfB | lfB | lfB l | lfCW | lfCW . Library:Link:Dependency Name:Specifier:Specifier _ \fIrefer\fP record manipulation library:BIBSTUFFLIB:DEPBIBSTUFFLIB Exception and termination manager library:ETMLIB:DEPETMLIB Form processing library:FPLLIB:DEPFPLLIB Form query library:FQLLIB:DEPFQLLIB GECOS library:GECOSLIB:DEPGECOSLIB Simple log manager library:LOGMGRLIB:DEPLOGMGRLIB Simple memory manager library:MEMMGRLIB:DEPMEMMGRLIB Network database service library:NDSLIB:DEPNDSLIB Network I/O library:NIOLIB:DEPNIOLIB Order processing library:ORDERLIB:DEPORDERLIB Sequence number library:SEQNUMLIB:DEPSEQNUMLIB Simple screen-management library:SIMSCRLIB:DEPSIMSCRLIB Temporary file manager library:TFMlIB:DEPTFMLIB Token scanning library:TSLIB:DEPTSLIB _ .TE .vs +2 .ps +2 .LP Example: Suppose a program .I myprog is built from .I prog.c and the ETM, memory manager, and token scanning libraries. The .I Imakefile might look like this: .Ps LIBS = $(MEMMGRLIB) $(TSLIB) $(ETMLIB) DEPLIBS = $(DEPMEMMGRLIB) $(DEPTSLIB) $(DEPETMLIB) .sp .3v BuildSimpleProgram(myprog,$(LIBS),$(DEPLIBS)) .Pe .\" .Ah "Multiple-Directory Support" .\" .LP If a directory has subdirectories, normally you want .I make to traverse those subdirectories when you run it. Write the .I Imakefile like this: .Ps #define IHaveSubdirs #define PassCDebugFlags .sp .3v SUBDIRS = \f(CIlist\fP .Pe where .Ci list is a space-separated list of the subdirectories that should be processed by .I make , in the order you want them processed. For example: .Ps #define IHaveSubdirs #define PassCDebugFlags .sp .3v SUBDIRS = include lib apps doc man .Pe After you build the .I Makefile , it will contain recursive entries for .Cw all , .Cw depend , .Cw install , .Cw install.man , .Cw clean , .Cw tags , and .Cw Makefiles targets. .LP If you anticipate that you'll want to build debuggable targets, define .Cw PassCDebugFlags like this instead: .Ps #define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' .Pe Then you can specify debugging flags from the .I make command line, e.g.: .Ps % \f(CBmake CDEBUGFLAGS=-g\fP .Pe 0 .\" .Ah "Generating a World Target" .\" .LP You can invoke .Cw SimpleWorldTarget() in the .I Imakefile in a project's root (top-level) directory to generate a .Cw World target entry. Then you can say .I make .I World to build the entire project from scratch (including configuring its Makefiles). Note that if your project is at all complex, it may require a configure/build sequence that varies from the simple .Cw World entry provided by .Cw SimpleWorldTarget() . In this case you'll need to write your own .Cw World entry by hand. .LP .Cw SimpleWorldTarget() takes the project name and release level as arguments: .Ps SimpleWorldTarget(\f(CIproject\fP,\f(CIrelease\fP) .Pe If your project has a .I config directory for private configuration information, it's useful to create a file .I Imake.p-params there to override the macros that define the project name and release numbers. For example: .Ps #ifndef ProjectName #define ProjectName My Project Name #endif #ifndef ProjectMajorRelease #define ProjectMajorRelease 1 #endif #ifndef ProjectMinorRelease #define ProjectMinorRelease 03 #endif .Pe Then you can invoke .Cw SimpleWorldTarget() using the associated .I make variables: .Ps SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) .Pe In this case, whenever you change the release numbers in .I Imake.p-params , you don't have the change the project root .I Imakefile . However, you do need to rebuild the .I Makefile so it gets the updated release numbers. .LP If your project builds targets in multiple directories, the root .I Imakefile might look like this: .Ps #define IHaveSubdirs #define PassCDebugFlags .sp .3v SUBDIRS = \f(CIlist\fP .sp .3v SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) .Pe .\" .Ah "Formatting Documents" .\" .LP The WRPRC2 files contain rules for producing PostScript files from .I troff documents. In most cases, a .I troff document is formatted using the .I \-man , .I \-me , .I \-mm , or .I \-ms macros, possibly after having been run through one or more preprocessors such as .I tbl or .I pic . .LP For instance, to produce a PostScript file .I doc.ps from a document .I doc.ms that requires the .I \-ms macros but no preprocessors, write this: .Ps TroffMsToPostScript(doc.ps,doc.ms,NullArg,NullArg) .Pe The arguments to .Cw TroffMsToPostScript() are the destination output file, the input source file (or files), the preprocessor list, and any dependencies that must exist before the source can be processed. The preprocessor list must be given in the form of a piece of a command pipeline, beginning with ``|''. For example, to run the input through .I pic , use this: .Ps TroffMsToPostScript(doc.ps,doc.ms,|$(PIC),NullArg) .Pe To run the input through .I tbl and .I eqn , use this: .Ps TroffMsToPostScript(doc.ps,doc.ms,|$(TBL)|$(EQN),NullArg) .Pe .LP To format a document with one of the other macro packages, change the ``Ms'' in the rule name to ``Man'', ``Me'', or ``Mm''. .\" .Ah "Default Target Entries" .\" .LP The WRPRC2 configuration files provide several target entries in the .I Makefile for you. Some of them actually do something, others are simply placeholders to prevent errors when certain .I make operations are performed. .IP \(bu A .Cw help entry is provided allowing .I make .I help , which indicates some typical .I make commands and what they do. .IP \(bu A .Cw Makefile entry is produced so you can run .I make .I Makefile to rebuild the .I Makefile after you make changes to the .I Imakefile . .IP \(bu A default .Cw clean entry is produced that removes typical garbage files such as .I *.o , .I *.a , and .I *.bak files, and .I core . .B Note: Unlike the default .Cw clean entry produced by the X11 rules, the WRPRC2 default .Cw clean entry does not remove .I *~ files; this is because my own convention for creating backup files is to use .Cw ~ rather than .I \&.bak . .IP \(bu A .Cw tags entry is provided so you can say .I make .I tags . .IP \(bu If the .I Imakefile is for a directory with subdirectories, recursive .Cw all , .Cw depend , .Cw install , .Cw install.man , .Cw clean , .Cw tags , and .Cw Makefiles entries are produced. If the directory doesn't have subdirectories, dummy targets for these operations are produced as necessary so that .I make doesn't generate errors (this is necessary or recursive .I make operations would fail as soon as they reached a directory with no subdirectories). support for shared libraries. .LP To build a library, invoke .Cw BuildNormalLibrary() , passing it the library basename and the source file and oWRPRC-2.11/tmac.wrprc010066400017710000151000000123140634140471700160700ustar00junkyarddatamgmt00000400000027.\" .\" Font Notes: .\" CW, CB, CI are used for non-proportional, non-proportional bold, and .\" non-proportional italic (courier, courier-bold, courier-italic). If .\" the font names are different at your site, change definitions of .\" of .Cw, .Cb, and .Ci below. There may be other inline references to .\" CW, CB, and CI that need to be changed as well. .\" .\" The inline font reference is given using \f[xx], which requires a .\" version of troff that understands the [xx] notation, e.g., groff. .\" .\" .\" Ft - font reference .\" $1 = font to use for .ft switches .\" $2 = font to use for inline \f switches .\" $3 = thing to put in the given font .\" $4 = goes immediately after $3 .\" $5 = goes immediately before $4 .\" if $3-$5 are empty, simply switch font w/o switching back .de Ft .nr PQ \\n(.f .ie \(ts\\$3\\$4\\$5\(ts\(ts .ft \\$1 .el \&\\$5\\f[\\$2]\\$3\\f\\n(PQ\&\\$4 .. .\" .\" Cw - constant width font .de Cw .Ft CW CW "\\$1" "\\$2" "\\$3" .. .\" .\" Cb - bold constant width font .de Cb .Ft CB CB "\\$1" "\\$2" "\\$3" .. .\" .\" Ci - italic constant width font .de Ci .Ft CI CI "\\$1" "\\$2" "\\$3" .. .\" .\" I - italic font .de I .Ft I I "\\$1" "\\$2" "\\$3" .. .\" .\" B - bold font .de B .Ft B B "\\$1" "\\$2" "\\$3" .. .\" .\" Bi - bold italic font .de Bi .Ft BI BI "\\$1" "\\$2" "\\$3" .. .\" .\" Most of following are modified from ORA macros .\" .de Ps \" Printout start; $1 = indent (default is 5 spaces) .br .nr pS \\n(.s \" Save current point size .nr vS \\n(.v \" Save current vertical spacing .nr pF \\n(.f \" Save current font .nr pI \\n(.iu \" Save current indent .sp \\n(PDu .ns .\".ps 9 .\".vs 11 .ps 8 .vs 10 .ft CW .ie !"\\$1"" .in \\n(.iu+\\$1n .el .in \\n(.iu+5n \" default indent = +5n .nf .\" 4n doesn't work. How come? .\".ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n .nr Cw 4*\\w`n` .ta \\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu .rr Cw .. .de Pe \" Printout end; if $1 non-null, no concluding blank line .br .if "\\$1"" .sp \\n(PDu .ps \\n(pS .vs \\n(vSu .ft \\n(pF .in \\n(pIu .rr pS .rr vS .rr pF .rr pI .fi .. .\" .\" Vertical ellipsis with squished vertical spacing. Optional argument .\" sets indent (restored afterward). .\" .de Ve .if !`\\$1`` .in \\$1 .vs 4 \&. \&. \&. .vs .if !`\\$1`` .in .. .\" .nr l0 0 1 \" initialize list nesting level counter .\" .\" list start; $1 = A(LPHA), a(alpha), B(ullet), N(umeric), .\" R(oman), r(oman); $2 = indent; $3 = bullet char .de Ls .br .if !"\\$1"A" .if !"\\$1"B" .if !"\\$1"N" .if !"\\$1"R" \ . if !"\\$1"r" .if !"\\$1"a" .if !"\\$1"" \ .ab Ls: Need A B N R a r or null as list type--abort .nr l\\n+(l0 0 1 \" increment list level, create new l register for level n .nr In\\n(l0 \\n(.iu \" save initial indent .\".tm Ls indent In\\n(l0 is \\n[In\\n(l0] .ie "\\$1"" \{\ . if "\\n(l0"1" .af l\\n(l0 1 \" default to numeric at 1st level . if "\\n(l0"2" .af l\\n(l0 a \" default to lc alphabetic at 2nd level . if "\\n(l0"3" .af l\\n(l0 i \" default to lc roman at 3rd level . if "\\n(l0"4" .ds l\\n(l0 \(bu \" default to bullet at 4th level . if "\\n(l0"5" .ds l\\n(l0 \f3\-\f1 \" default to dash at 5th level . if \\n(l0-5 .ds l\\n(l0\(bu \" default to bullet above 5rd level . if \\n(l0-3 .nr l\\n(l0 0-1 . \} .el \{\ . if "\\$1"A" .af l\\n(l0 A . if "\\$1"a" .af l\\n(l0 a . if "\\$1"B"\{\ . if "\\$3"" .ds l\\n(l0 \(bu \" no 3rd arg = default bullet . if !"\\$3"" .ds l\\n(l0 \\$3 \" 3rd arg = bullet . nr l\\n(l0 0-1 . \} . if "\\$1"R" .af l\\n(l0 I . if "\\$1"r" .af l\\n(l0 i \} .ie !"\\$2"" .nr i\\n(l0 \\$2 \" 2nd arg = list indent, if given .el .nr i\\n(l0 \\n(.iu+3n \" default indent (used to be 5) .\".el .nr i\\n(l0 3 \" default indent (used to be 5) .\".nr I0 0 .if \\n(l0>1 .RS \" shift right if this is a nested list .. .de Li \" list item; $1 = 0 means no blank line before item .br .if "\\$1"0" .ns .ie "\\n(l\\n(l0"-1" .IP "\\*(l\\n(l0" "\\n(i\\n(l0u" .el \{\ . nr l\\n(l0 +1 . IP "\\n(l\\n(l0." "\\n(i\\n(l0u" .\} .. .de Le \" list end; $1 = 0 means no extra blank line following last item .br .rr l\\n(l0 .rr i\\n(l0 .rm l\\n(l0 .\".tm Le \\n(l0 indent1=\\n(.i .if \\n(l0>1 .RE \" shift left if this is a nested list .\".tm Le \\n(l0 indent2=\\n(.i .in \\n[In\\n(l0]u .rr In\\n(l0 .\".tm Le \\n(l0 indent3=\\n(.i .nr l0 -1 \" decrement list level .ie !\\n(l0 \{\ .\" if the current indent is now > 0 assume the list was inside an IP .\" and don't reset indent all the way back out . ie \\n(.i>0 \{\ . if !"\\$1"0" .sp \\n(PDu . \} . el \{\ . ie "\\$1"0" .LP 0 . el .LP . \} .\} .el .if !"\\$1"0" .sp \\n(PDu .\".if \\n(IP=0 'in 0 .. .\" .\" Ah, Bh, Ch - headings for various levels. $1 = heading .\" .de Ah .sp .RT .ne 5 .ps 14 .vs 16 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .de Bh .sp .RT .ne 5 .ps 11 .vs 13 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .de Ch .sp .RT .ne 5 .ps 10 .vs 12 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .\" .\" Reset margins and paragraph distance. .nr PO 1.2in \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance t indent = +5n .nf .\" 4n doesn't work. How come? .\".ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n .nr Cw 4*\\w`n` .ta \\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu .rr Cw .. .dWRPRC-2.11/config/004077500017710000151000000000000634140472000153265ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/Makefile010066400017710000151000000402200634140471700167670ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./config # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = no-project-name PROJECTMAJORRELEASE = 0 PROJECTMINORRELEASE = 00 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile CFFILES = README Imake.tmpl \ Imake.params Imake.p-params \ Imake.rules Imake.p-rules \ site.def site.p-def \ *.cf *.p-cf INSTALLDIR = $(CONFIGROOTDIR)/$(CONFIGNAME) all:: install:: @if [ -d $(INSTALLDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(INSTALLDIR)); fi @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(CFFILES) ;\ do \ (set -x; $(INSTALL) $(INSTDATFLAGS) $$i $(INSTALLDIR)/$$i); \ done help_aux:: @echo "'make "install"' to "install $(CFFILES) test:: @echo "AdmDir: "/usr/adm @echo "ArCmd: "ar cq @echo "AsCmd: "as @echo "AwkCmd: "awk @echo "BibStuffLib: "-lbibstuff @echo "BinDir: "/usr/bin @echo "BourneShell: "/bin/sh @echo "CURDIR: "./config @echo "CatCmd: "cat @echo "CcCmd: "cc @echo "ChdirCmd: "cd @echo "ChmodCmd: "chmod @echo "CmpCmd: "cmp @echo "CommCmd: "comm @echo "ConfigMajorRelease: "2 @echo "ConfigMinorRelease: "11 @echo "ConfigName: "WRPRC2 @echo "ConfigRelease: "$(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) @echo "ConfigRootDir: "/usr/local/lib/config @echo "ConstructMFLAGS: "0 @echo "CpCmd: "cp @echo "CppCmd: "/lib/cpp @echo "DefaultCCOptions: "-Xc @echo "DefaultCDebugFlags: "-O @echo "DepBibStuffLib: " @echo "DepEtmLib: " @echo "DepFplLib: " @echo "DepFqlLib: " @echo "DepGecosLib: " @echo "DepLogMgrLib: " @echo "DepMemMgrLib: " @echo "DepNdsLib: " @echo "DepNioLib: " @echo "DepOrderLib: " @echo "DepSeqNumLib: " @echo "DepSimScrLib: " @echo "DepTsLib: " @echo "DependCmd: "makedepend @echo "DistarCmd: "distar @echo "EqnCmd: "geqn @echo "EtcDir: "/usr/etc @echo "EtmLib: "-letm @echo "FigenCmd: "figen @echo "FilesToClean: "*.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut @echo "FplLib: "-lfpl @echo "FqlLib: "-lfql @echo "GecosLib: "-lgecos @echo "HasExecableScripts: "1 @echo "HasGcc2: "0 @echo "HasGcc: "0 @echo "HasRanlibCmd: "0 @echo "HasSoelim: "1 @echo "HasStdarg: "1 @echo "HasSymLinks: "1 @echo "HasUnistdH: "1 @echo "HasVFork: "0 @echo "HasVarargs: "1 @echo "HasVoidSignalReturn: "1 @echo "ImbootCmd: "imboot @echo "IncludeRoot: "/usr/include @echo "InstCopy: "-c @echo "InstDatFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) @echo "InstDatMode: "-m 0444 @echo "InstGidProgFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) @echo "InstGidProgMode: "-m 02755 @echo "InstGroup: " @echo "InstIncFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) @echo "InstIncMode: "-m 0444 @echo "InstLibFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) @echo "InstLibMode: "-m 0644 @echo "InstManFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) @echo "InstManMode: "-m 0444 @echo "InstOwner: " @echo "InstProgFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) @echo "InstProgMode: "-m 0755 @echo "InstScriptFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) @echo "InstScriptMode: "-m 0755 @echo "InstStrip: "-s @echo "InstUGidProgFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) @echo "InstUGidProgMode: "-m 06755 @echo "InstUidProgFlags: "$(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) @echo "InstUidProgMode: "-m 04755 @echo "InstallCmd: "/usr/ucb/install @echo "LdCmd: "ld @echo "LintCmd: "lint @echo "LintLibDir: "$(USRLIBDIR)/lint @echo "LintLibFlag: "-o @echo "LintLibs: " @echo "LintOpts: "-bh @echo "LnCmd: "ln -s @echo "LoaderLibPrefix: " @echo "LocalAdmDir: "$(LOCALROOTDIR)/adm @echo "LocalBinDir: "$(LOCALROOTDIR)/bin @echo "LocalEtcDir: "$(LOCALROOTDIR)/etc @echo "LocalIncludeRoot: "$(LOCALROOTDIR)/include @echo "LocalLintLibDir: "$(LOCALUSRLIBDIR)/lint @echo "LocalRootDir: "/usr/local @echo "LocalUsrLibDir: "$(LOCALROOTDIR)/lib @echo "LogMgrLib: "-llogmgr @echo "MakeCmd: "make @echo "Man1Dir: "$(MANSOURCEPATH)$(MAN1SUFFIX) @echo "Man1Suffix: "1 @echo "Man2Dir: "$(MANSOURCEPATH)$(MAN2SUFFIX) @echo "Man2Suffix: "2 @echo "Man3Dir: "$(MANSOURCEPATH)$(MAN3SUFFIX) @echo "Man3Suffix: "3 @echo "Man4Dir: "$(MANSOURCEPATH)$(MAN4SUFFIX) @echo "Man4Suffix: "4 @echo "Man5Dir: "$(MANSOURCEPATH)$(MAN5SUFFIX) @echo "Man5Suffix: "5 @echo "Man6Dir: "$(MANSOURCEPATH)$(MAN6SUFFIX) @echo "Man6Suffix: "6 @echo "Man7Dir: "$(MANSOURCEPATH)$(MAN7SUFFIX) @echo "Man7Suffix: "7 @echo "Man8Dir: "$(MANSOURCEPATH)$(MAN8SUFFIX) @echo "Man8Suffix: "8 @echo "ManDir: "$(MANSOURCEPATH)$(MANSUFFIX) @echo "ManLDir: "$(MANSOURCEPATH)$(MANLSUFFIX) @echo "ManLSuffix: "l @echo "ManMacros: "-man @echo "ManNDir: "$(MANSOURCEPATH)$(MANNSUFFIX) @echo "ManNSuffix: "n @echo "ManRoot: "/usr/local/man @echo "ManSourcePath: "$(MANROOT)/man @echo "ManSuffix: "$(MAN1SUFFIX) @echo "MdocMacros: "-mdoc @echo "MeMacros: "-me @echo "MemMgrLib: "-lmemmgr @echo "MkdirHierCmd: "mkdirhier @echo "MmMacros: "-mm @echo "MsMacros: "-ms @echo "MsubCmd: "msub @echo "MvCmd: "mv @echo "NdsLib: "-lnds @echo "NeqnCmd: "neqn @echo "NioLib: "-lnio @echo "NroffCmd: "nroff @echo "OSMajorVersion: "5 @echo "OSMinorVersion: "5 @echo "OSTeenyVersion: "0 @echo "OrderLib: "-lorder @echo "Perl5Cmd: "perl5 @echo "Perl5Path: "$(LOCALBINDIR)/perl5 @echo "PerlCmd: "perl @echo "PerlPath: "$(LOCALBINDIR)/perl @echo "PicCmd: "pic @echo "ProjectDefines: " @echo "ProjectIncludes: " @echo "ProjectLoadFlags: " @echo "ProjectLoadLibs: " @echo "ProjectMajorRelease: "0 @echo "ProjectMinorRelease: "00 @echo "ProjectName: "no-project-name @echo "ProjectRelease: "$(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) @echo "RanlibCmd: "ranlib @echo "RanlibInstFlags: " @echo "RmCmd: "rm -f @echo "SedCmd: "sed @echo "SeqNumLib: "-lseqnum @echo "SimScrLib: "-lsimscr @echo "SoelimCmd: "soelim @echo "SortCmd: "sort @echo "StandardCppDefines: " @echo "StandardDefines: "-Dsun -DSVR4 @echo "StandardIncludes: "-I$(LOCALINCLUDEROOT) @echo "StandardLoadFlags: "-L$(LOCALUSRLIBDIR) @echo "StandardLoadLibs: "-lsocket -lnsl -lw @echo "SystemV4: "1 @echo "SystemV: "0 @echo "TOPDIR: "../. @echo "TagsCmd: "ctags @echo "TblCmd: "gtbl @echo "TblcvtCmd: "tblcvt @echo "TcManMacros: "-man @echo "TcMdocMacros: "-mdoc @echo "TcMeMacros: "-me @echo "TcMmMacros: "-mm @echo "TcMsMacros: "-ms @echo "TmpDir: "/tmp @echo "Troff2HtmlCmd: "troff2html @echo "Troff2RtfCmd: "troff2rtf @echo "TroffCmd: "groff @echo "TroffcvtCmd: "troffcvt @echo "TsLib: "-ltokenscan @echo "UniqCmd: "uniq @echo "UnroffCmd: "unroff @echo "UsrLibDir: "/usr/lib # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend WRPRC-2.11/config/site.p-def010066400017710000151000000000000634140471700172000ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/Imake.tmpl010066400017710000151000000141350634140471700172610ustar00junkyarddatamgmt00000400000027/* * Imake.tmpl - imake template for Wisconsin Regional Primate * Research Center configuration files, Release 2.08. * * Bootstrap using these files with: * * % imboot -C WRPRC2 [ topdir ] * * topdir is the path to the project root. It may be omitted if you * are in the project root. * * WRPRC 2.xx configuration file architecture and content was derived * from and influenced by configuration files from X11 (R4, R5, R6.x), * WRPRC (release 1), and InterViews (3.1). */ /* * These files assume you're using an imake from X11R6 or higher, which * takes care of XCOMM processing itself. If you have an X11R5 imake, you'll * get a lot of XCOMM lines in your Makefiles. In that case, try uncommenting * the line below. (But you really should update your imake instead.) If * you uncomment and your cpp complains about the # being a stringizing * operator, try using #define XCOMM \# instead. */ /* #define XCOMM # */ XCOMM ------------------------------------------------------------------------- XCOMM Makefile generated from IMAKE_TEMPLATE and INCLUDE_IMAKEFILE. XCOMM XCOMM Platform-specific parameters may be set in the appropriate .cf and XCOMM .p-cf configuration files. Site-wide parameters may be set in the XCOMM files site.def and site.p-def. Full rebuilds are recommended if XCOMM any parameters are changed. #define YES 1 #define NO 0 /* Vendor block selection */ #include #include XCOMM ------------------------------------------------------------------------- XCOMM site-specific configuration parameters that need to come before the XCOMM platform-specific parameters - edit site.def or site.p-def to change #define BeforeVendorCF #include #include #undef BeforeVendorCF XCOMM ------------------------------------------------------------------------- XCOMM Set the OS name and version macros if imake has defined them #if !defined(OSName) && defined(DefaultOSName) #define OSName DefaultOSName #endif #if !defined(OSMajorVersion) && defined(DefaultOSMajorVersion) #define OSMajorVersion DefaultOSMajorVersion #endif #if !defined(OSMinorVersion) && defined(DefaultOSMinorVersion) #define OSMinorVersion DefaultOSMinorVersion #endif #if !defined(OSTeenyVersion) && defined(DefaultOSTeenyVersion) #define OSTeenyVersion DefaultOSTeenyVersion #endif XCOMM ------------------------------------------------------------------------- XCOMM platform-specific configuration parameters specific to this project XCOMM edit ProjectVendorFile to change #include ProjectVendorIncludeFile XCOMM ------------------------------------------------------------------------- XCOMM platform-specific configuration parameters XCOMM edit VendorFile to change #include VendorIncludeFile /* * Concat - concatenates two strings. */ #ifndef Concat #if (__STDC__ && !defined(UnixCpp)) || defined(AnsiCpp) #define Concat(a,b)a##b #else #define Concat(a,b)a/**/b #endif #endif /* * Concat3 - concatenates three strings. */ #ifndef Concat3 #if (__STDC__ && !defined(UnixCpp)) || defined(AnsiCpp) #define Concat3(a,b,c)a##b##c #else #define Concat3(a,b,c)a/**/b/**/c #endif #endif /* * Concat4 - concatenates four strings. */ #ifndef Concat4 #if (__STDC__ && !defined(UnixCpp)) || defined(AnsiCpp) #define Concat4(a,b,c,d)a##b##c##d #else #define Concat4(a,b,c,d)a/**/b/**/c/**/d #endif #endif XCOMM ------------------------------------------------------------------------- XCOMM site-specific configuration parameters that go after the XCOMM platform-specific parameters - edit site.def or site.p-def to change #define AfterVendorCF #include #include #undef AfterVendorCF XCOMM ------------------------------------------------------------------------- XCOMM project-specific system and project description parameters XCOMM Edit Imake.p-params to change #include XCOMM ------------------------------------------------------------------------- XCOMM Standard system and project description parameters XCOMM Edit Imake.params to change #include XCOMM ------------------------------------------------------------------------- XCOMM Project-specific imake rules XCOMM Edit Imake.p-rules to change #include XCOMM ------------------------------------------------------------------------- XCOMM Standard imake rules XCOMM Edit Imake.rules to change #include XCOMM ------------------------------------------------------------------------- XCOMM start of Imakefile #include INCLUDE_IMAKEFILE XCOMM ------------------------------------------------------------------------- XCOMM common rules for all Makefiles /* * These need to be here so that rules in Imakefile occur first; the blank * emptyrule is to make sure that an empty Imakefile doesn't default to make * clean. */ emptyrule:: CleanTarget() TagsTarget() MakefileTarget() help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: #ifdef IHaveSubdirs XCOMM ------------------------------------------------------------------------- XCOMM rules for building in SUBDIRS MakeSubdirs($(SUBDIRS)) DependSubdirs($(SUBDIRS)) InstallSubdirs($(SUBDIRS)) InstallManSubdirs($(SUBDIRS)) CleanSubdirs($(SUBDIRS)) TagSubdirs($(SUBDIRS)) MakefileSubdirs($(SUBDIRS)) #else XCOMM ------------------------------------------------------------------------- XCOMM empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: #endif /* if subdirectory rules are needed */ XCOMM ------------------------------------------------------------------------- XCOMM dependencies generated by makedepend WRPRC-2.11/config/cray.cf010066400017710000151000000024410634140471700166020ustar00junkyarddatamgmt00000400000027/* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES * * Note: I have never tested this file (it's derived from the X11R5 cray.cf). * It's here mainly to show that * there is a system that really uses * LoaderLibPrefix. * -- pd */ #ifndef OSName #define OSName UNICOS 6.1 #endif #ifndef OSMajorVersion #define OSMajorVersion 6 #endif #ifndef OSMinorVersion #define OSMinorVersion 1 #endif XCOMM platform: cray.cf 93/08/26 XCOMM operating system: OSName #define SystemV YES /*#define InstallCmd sh $(SCRIPTSRC)/install.sh*/ #define InstallCmd install.sh #define ArCmd bld cr #define StandardDefines -DSYSV -DUSG #define HasExecableScripts NO #define CcCmd scc #ifdef CRAY2 #define DefaultCCOptions -hpagelm -hlimitlm #endif /* * LoaderLibPrefix should be used to specify only libraries that are named * by pathname (e.g., LoaderLibPrefix $(TOP)/lib/libmylib.a). You don't * use it to specify libraries named with -lname notation (e.g., you write * -lmylib, not LoaderLibPrefix -lmylib). */ #define LoaderLibPrefix -l #if CRAY2 && OSMajorVersion < 6 # undef LoaderLibPrefix # define LoaderLibPrefix -L #endif #if OSMajorVersion >= 6 #define CppCmd /lib/pcpp #else # if OSMajorVersion == 5 # define CppCmd /lib/cpp # define StandardLoadLibs -lnet # endif #endif WRPRC-2.11/config/Imake.p-rules010066400017710000151000000000000634140471700176560ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/cray.p-cf010066400017710000151000000000000634140471700170240ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/generic.cf010066400017710000151000000011030634140471700172520ustar00junkyarddatamgmt00000400000027/* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES */ #ifndef OSName #define OSName None #endif #ifndef OSMajorVersion #define OSMajorVersion 0 #endif #ifndef OSMinorVersion #define OSMinorVersion 0 #endif XCOMM platform: generic.cf XCOMM operating system: OSName /***************************************************************************** * Platform-specfic parameters * *****************************************************************************/ #ifdef SYSV #define SystemV YES #endif #ifdef SVR4 #define SystemV4 YES #endif WRPRC-2.11/config/hp.p-cf010066400017710000151000000000000634140471700164750ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/hp.cf010066400017710000151000000025640634140471700162610ustar00junkyarddatamgmt00000400000027/* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES */ #ifndef OSName #define OSName HP-UX 9.05 #endif #ifndef OSMajorVersion #define OSMajorVersion 9 #endif #ifndef OSMinorVersion #define OSMinorVersion 05 #endif XCOMM platform: hp.cf 95/07/15 XCOMM operating system: OSName #ifndef SystemV #define SystemV YES #endif #ifndef HasExecableScripts #define HasExecableScripts YES #endif /* * If you set HasStdarg to YES, you should pass -Aa to the C compiler * if you use cc, or else use c89. (Or possibly use gcc.) */ #ifndef HasStdarg #define HasStdarg NO #endif #ifndef HasVarargs #define HasVarargs YES #endif #ifndef HasVFork #define HasVFork YES #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES #endif #if HasStdarg #ifndef CcCmd #define CcCmd c89 #endif #endif #ifndef StandardDefines #ifdef hp9000s800 #define StandardDefines -DSYSV #else #define StandardDefines -Wc,-Nd4000,-Ns3300,-Ne700,-Np200,-Nw300 -DSYSV #endif #endif #ifndef LintOpts #ifdef hp9000s800 #define LintOpts -ax -DSYSV #else #define LintOpts -ax -Nd4000 -Ns3300 -Ne700 -Np200 -Na25000 -DSYSV #endif #endif #ifndef MvCmd #define MvCmd mv -f #endif /* * install.sh is from the X11R[56] distribution. You may prefer bsdinst * instead. */ #ifndef InstallCmd #define InstallCmd install.sh #endif WRPRC-2.11/config/CHANGES010066400017710000151000000023240634140471700163250ustar00junkyarddatamgmt00000400000027This is an incomplete list of changes in the WRPRC 2.xx files relative to the WRPRC 1.xx files). INCLUDEPATH is no more. Use INCLUDEROOT. MANPATH is no more. Use MANROOT. Imake.tmpl has been split into Imake.tmpl, Imake.cf, and Imake.params. The latter also includes what used to be Project.tmpl. Imake.params defines some commonly used directories: BINDIR, ETCDIR, USRLIBDIR, ADMDIR, TMPDIR Imake.params contains symbols for libraries commonly used to build WRPRC project. For each library there is a XXXLIB symbol for linking and a DEPXXXLIB symbol for dependencies. UseSoelim (defined or not defined) has now become HasSoelim (YES/NO). EXTRA_INCLUDES is replaced by PROJECT_INCLUDES. PROJECT_DEFINES is a new symbol for project-specific -D's. No programs are built. This distribution now only contains configuration files. Thus there is no use for UseInstalled in any of the symbol definitions or rules, and all of the *Dependency() rules have been removed. The program building rules are completely different. BuildProgram() is the main interface to this. Use BuildLibrary(), not NormalLibraryTarget(). The installation rules are completely different, especially those for manpages. Document rules are different. WRPRC-2.11/config/Mips.cf010066400017710000151000000217470634140471700165660ustar00junkyarddatamgmt00000400000027/* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES * * Also set the definition of MipsHasNroff according to whether you have * nroff on your machine. */ /* * * Problems configuring for Mips RISC/os: * * 1) The include hierarchy root is /usr/include for the System V environment * and /bsd43/usr/include for the BSD environment. Similarly, the library * directories are /usr/lib and /bsd43/usr/lib. The latter can be taken * care of by making sure the compiler knows which environment it's to * conform to, by passing -systype sysv or -systype bsd43 on the command * line. * * The compiler will also look in the correct header file directory when * processing #include directives. However, for generating header file * dependencies, the include hierarchy root must be passed explicitly to * makedepend, since makedepend knows nothing about any -systype * conventions (and makedepend gets confused about the argument following * -systype, anyway). The include hierarchy root is passed by setting * StandardIncludes to the proper directory. Eventually StandardIncludes * becomes part of the value of ALLINCLUDES, which is passed to makedepend * by DependTarget(). * * 2) Other configuration parameters vary when you use the System V environment. * Signal semantics differ, for instance. * * 3) Pre-4.50 versions of RISC/os don't have the v?printf() functions in the * C library. This file corrects for that by adding -ltermcap to * StandardLoadLibs (the v?printf functions are in -ltermcap). * * 4) mipsinstall needs -f, or sometimes it will create a destination file * as a directory instead, and the install will fail. (If you want unstripped * binaries, define InstStrip as nothing, like this: * #define InstStrip * * 5) Man page installation is difficult because of the arcane arrangement of * manual pages under RISC/os. Also, they should be installed as nroff-ed * files. However, nroff is not included with RISC/os by default. If you * have nroff, define MipsHasNroff as YES below. If this symbol is NO, * manual page rules are disabled so that "make install.man" is a nop. * * As near as I can tell, manual pages should be arranged as follows. * Under /usr/man, there are three directories: * a_man - for administrative sections (7, 8) * p_man - programmer sections (2-6) * u_man - user sections (1, 6) * Under these three directories, the manX and bsd_manX directories hold * the SystemV and BSD versions of commands. This means the location in which * a manual page is installed depends both on the section it should go in, * and the compilation environment. Fun. * * Anyway, the way it's set up below works on my machine. Your mileage may * vary. * * * To use imake with the BSD environment, it should have been built in an * imake source distribution using this command in the distribution root: * * % make World BOOTSTRAPCFLAGS="-DMips -DBSD43" >& make.world * * To build for the System V environment, do this instead: * * % make World BOOTSTRAPCFLAGS="-DMips -DSYSV" >& make.world * * Unfortunately, although you can do this for either environment, you can't * easily build the distribution for one environment and then use it later * to configure projects for the other environment. */ #ifndef OSName #define OSName RISC/os 4.01 #endif #ifndef OSMajorVersion #define OSMajorVersion 4 #endif #ifndef OSMinorVersion #define OSMinorVersion 01 #endif XCOMM platform: Mips.cf 93/06/30 XCOMM operating system: OSName #ifndef CCompilerMajorVersion #define CCompilerMajorVersion 2 #endif #ifndef CCompilerMinorVersion #define CCompilerMinorVersion 0 #endif /* set this early because stuff below depends on it */ #ifndef SystemV #ifdef SYSV #define SystemV YES /* need System V style */ #else #define SystemV NO /* need BSD style */ #endif #endif /* * default for ExecableScripts is NO when SystemV is YES; but on RISC/os, * scripts are execable regardless of environment. */ #ifndef HasExecableScripts #define HasExecableScripts YES #endif #ifndef HasVarargs #define HasVarargs YES #endif /* Use signal semantics consistent with compilation environment */ #ifndef HasVoidSignalReturn #if SystemV #define HasVoidSignalReturn YES #else #define HasVoidSignalReturn NO #endif #endif /* * Default value of ConfigDir is defined in terms of USRLIBDIR, which differs * depending on environment, so use /usr/local/lib literally. */ #ifndef ConfigRootDir #define ConfigRootDir /usr/local/lib/config #endif #ifndef UsrLibDir #if SystemV #define UsrLibDir /usr/lib #else #define UsrLibDir /bsd43/usr/lib #endif #endif #ifndef IncludeRoot #if SystemV #define IncludeRoot /usr/include #else #define IncludeRoot /bsd43/usr/include #endif #endif #ifndef LocalRootDir #if SystemV #define LocalRootDir /usr/local #else #define LocalRootDir /bsd43/usr/local #endif #endif /* these don't need to be environment-specific */ #ifndef LocalAdmDir #define LocalAdmDir /usr/local/adm #endif #ifndef LocalBinDir #define LocalBinDir /usr/local/bin #endif #ifndef LocalEtcDir #define LocalEtcDir /usr/local/etc #endif #ifndef StandardCppDefines #if SystemV #define StandardCppDefines -DSYSV #else #define StandardCppDefines -DBSD43 #endif #endif #ifndef StandardDefines #define StandardDefines StandardCppDefines #endif /* * The include roots vary depending on SystemV/not-SystemV, so make sure * they're explicitly part of the include parameters so "make depend" works. */ #ifndef StandardIncludes #define StandardIncludes -I$(LOCALINCLUDEROOT) -I$(INCLUDEROOT) #endif #ifndef HasGcc2 #ifndef CcCmd #if SystemV #define CcCmd cc -systype sysv #else #define CcCmd cc -systype bsd43 #endif #endif #endif #ifndef StandardLoadLibs #if SystemV #define StandardLoadLibs /* as nothing */ #else /* * For BSD environment, need -ltermcap for v?printf. It's not in * the BSD C library in releases of RISC/os prior to 4.50. */ #if OSMajorVersion > 4 || (OSMajorVersion == 4 && OSMinorVersion >= 50) #define StandardLoadLibs /* as nothing */ #else #define StandardLoadLibs -ltermcap #endif #endif #endif /* * I'm not sure about the utility of setting these correctly; there aren't * any lint libraries on my machine even for system libraries... */ #ifndef LintLibFlag #define LintLibFlag -o /* even if not SystemV */ #endif #ifndef LintOpts #define LintOpts -bh /* even if not SystemV */ #endif #ifndef InstallCmd #define InstallCmd /etc/mipsinstall -f #endif /* * Manual page installation support. * * If nroff is present, use it to install nroff-ed manual pages. Otherwise * disable the install rule. (If you don't have nroff, but do have groff, * try setting MipsHasNroff to YES and defining nroff as groff -Tascii.) */ #ifndef MipsHasNroff #define MipsHasNroff YES #endif #ifndef InstallManFile #if MipsHasNroff #define InstallManFile(target,name,dstsuffix,dir) @@\ target:: i.name.man @@\ i.name.man:: name.man @@\ MakeDir(dir) @@\ x=$(TMPDIR)/man$$$$ ; \ @@\ $(NEQN) name.man | $(NROFF) $(MANMACROS) > $$x ; \ @@\ $(INSTALL) $(INSTMANFLAGS) $$x dir/name.dstsuffix ; \ @@\ $(RM) $$x #else #define InstallManFile(target,name,dstsuffix,dir) @@\ target:: i.name.man @@\ i.name.man:: name.man @@\ @echo "$(NROFF) unavailable, cannot install "name.man #endif /* MipsHasNroff */ #endif /* InstallManFile */ #undef MipsHasNroff #ifndef ManRoot #define ManRoot /usr/man #endif /* * Sections 2-5 go under p_man * Sections 7,8 go under a_man * Sections 1,6,l,n go under u_man */ #ifndef Man2Dir #if SystemV #define Man2Dir $(MANROOT)/p_man/man$(MAN2SUFFIX) #else #define Man2Dir $(MANROOT)/p_man/bsd_man$(MAN2SUFFIX) #endif #endif #ifndef Man3Dir #if SystemV #define Man3Dir $(MANROOT)/p_man/man$(MAN3SUFFIX) #else #define Man3Dir $(MANROOT)/p_man/bsd_man$(MAN3SUFFIX) #endif #endif #ifndef Man4Dir #if SystemV #define Man4Dir $(MANROOT)/p_man/man$(MAN4SUFFIX) #else #define Man4Dir $(MANROOT)/p_man/bsd_man$(MAN4SUFFIX) #endif #endif #ifndef Man5Dir #if SystemV #define Man5Dir $(MANROOT)/p_man/man$(MAN5SUFFIX) #else #define Man5Dir $(MANROOT)/p_man/bsd_man$(MAN5SUFFIX) #endif #endif #ifndef Man7Dir #if SystemV #define Man7Dir $(MANROOT)/a_man/man$(MAN7SUFFIX) #else #define Man7Dir $(MANROOT)/a_man/bsd_man$(MAN7SUFFIX) #endif #endif #ifndef Man8Dir #if SystemV #define Man8Dir $(MANROOT)/a_man/man$(MAN8SUFFIX) #else #define Man8Dir $(MANROOT)/a_man/bsd_man$(MAN8SUFFIX) #endif #endif #ifndef Man1Dir #if SystemV #define Man1Dir $(MANROOT)/u_man/man$(MAN1SUFFIX) #else #define Man1Dir $(MANROOT)/u_man/bsd_man$(MAN1SUFFIX) #endif #endif #ifndef Man6Dir #if SystemV #define Man6Dir $(MANROOT)/u_man/man$(MAN6SUFFIX) #else #define Man6Dir $(MANROOT)/u_man/bsd_man$(MAN6SUFFIX) #endif #endif #ifndef ManLDir #if SystemV #define ManLDir $(MANROOT)/u_man/man$(MANLSUFFIX) #else #define ManLDir $(MANROOT)/u_man/bsd_man$(MANLSUFFIX) #endif #endif #ifndef ManNDir #if SystemV #define ManNDir $(MANROOT)/u_man/man$(MANNSUFFIX) #else #define ManNDir $(MANROOT)/u_man/bsd_man$(MANNSUFFIX) #endif #endif #ifndef ManDir #define ManDir $(MANLDIR) #endif #ifndef ManSuffix #define ManSuffix $(MANLSUFFIX) #endif WRPRC-2.11/config/sun.p-cf010066400017710000151000000000000634140471700166730ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/site.def010066400017710000151000000054550634140471700167660ustar00junkyarddatamgmt00000400000027XCOMM site: Primate Center 89/12/22 /***************************************************************************** * * * SITE-SPECIFIC DEFINITIONS * * * * This file contains two halves, one included before the vendor-specific * * configuration file (.cf file), and one included after the .cf file. * * The before-half should be protected by #ifdef BeforeVendorCF, and the * * after-half should be protected by #ifdef AfterVendorCF. * * * * The before-half should only set things that the .cf file depends on. * * For the .cf files shipped in this release, the main variables in this * * category are HasGcc and HasGcc2. * * * * The after-half should contain all other definitions. * * * * OS Major and Minor version numbers should be changed directly in the .cf * * file, not overridden in site.def. * * * *****************************************************************************/ #ifdef BeforeVendorCF /* * Uncomment one of the following definitions if you have gcc and want to * use it. (Either can still be overridden in site.p-def as desired on a * project-specific basis.) */ /* #ifndef HasGcc2 #define HasGcc2 YES #endif */ /* #ifndef HasGcc #define HasGcc YES #endif */ #endif /* BeforeVendorCF */ #ifdef AfterVendorCF /* * Some parameters you might want to change here to suit local convention are: * * - ConfigRootDir (should match value imboot uses for configuration root) * - document preparation preferences * - directories such as BinDir, UsrLibDir, TmpDir, etc. */ #ifndef ConfigRootDir #define ConfigRootDir /usr/local/lib/config #endif /* #ifndef BinDir #define BinDir /usr/local/bin #endif */ #ifndef ManRoot #define ManRoot /usr/local/man #endif #ifndef ManSuffix /* set this to where man pages are "usually" installed */ #define ManSuffix $(MAN1SUFFIX) /* use just one tab or cpp will die */ #endif #ifndef PerlPath /* for use in #! lines */ #define PerlPath $(LOCALBINDIR)/perl #endif #ifndef Perl5Path /* for use in #! lines */ #define Perl5Path $(LOCALBINDIR)/perl5 #endif /* document preparation preferences */ #ifndef TroffCmd #define TroffCmd groff #endif #ifndef TblCmd #define TblCmd gtbl #endif #ifndef EqnCmd #define EqnCmd geqn #endif #endif /* AfterVendorCF */ WRPRC-2.11/config/Mips.p-cf010066400017710000151000000000000634140471700167760ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/ultrix.cf010066400017710000151000000014720634140471700171760ustar00junkyarddatamgmt00000400000027/* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES */ #ifndef OSName #define OSName Ultrix 3.1 #endif #ifndef OSMajorVersion #define OSMajorVersion 3 #endif #ifndef OSMinorVersion #define OSMinorVersion 1 #endif XCOMM platform: ultrix.cf 93/06/30 XCOMM operating system: OSName #ifndef DirFailPrefix #define DirFailPrefix - #endif #ifndef HasVarargs #define HasVarargs YES #endif /* I believe signal return type changed from int to void between 3.0 and 3.1... */ #ifndef HasVoidSignalReturn #if OSMajorVersion > 3 || (OSMajorVersion == 3 && OSMinorVersion >= 1) #define HasVoidSignalReturn YES #else #define HasVoidSignalReturn NO #endif #endif #ifndef ManMacros /* these work better than -man under Ultrix */ #define ManMacros -man.new #endif #ifndef SpoolRootDir #define SpoolRootDir /var/spool #endif WRPRC-2.11/config/Imake.params010066400017710000151000000610770634140471700175770ustar00junkyarddatamgmt00000400000027/***************************************************************************** * * * Imake.params - general system and project parameters * * This file section contains defaults for things that can be overridden in * * Imake.p-params or the vendor and site files. * * * ****************************************************************************/ /* General system characteristics, specific feature symbols */ #ifndef SystemV #define SystemV NO /* SYSV (R3) */ #endif #ifndef SystemV4 #define SystemV4 NO /* SVR4 */ #endif #ifndef OSMajorVersion #define OSMajorVersion 0 #endif #ifndef OSMinorVersion #define OSMinorVersion 0 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 0 #endif #ifndef ConstructMFLAGS #if SystemV #define ConstructMFLAGS YES /* build MFLAGS from MAKEFLAGS */ #else #define ConstructMFLAGS NO /* don't */ #endif #endif #ifndef BourneShell /* to force shell in Makefile */ #define BourneShell /bin/sh #endif #ifndef HasExecableScripts #if SystemV #define HasExecableScripts NO /* can't execute scripts with #! */ #else #define HasExecableScripts YES #endif #endif #ifndef HasGcc2 #define HasGcc2 NO #endif #ifndef HasGcc #if defined(HasGcc2) #define HasGcc HasGcc2 #else #define HasGcc NO #endif #endif #ifndef HasRanlibCmd #if SystemV || SystemV4 #define HasRanlibCmd NO #else #define HasRanlibCmd YES #endif #endif #ifndef HasSoelim #define HasSoelim YES #endif #ifndef HasSymLinks #define HasSymLinks YES #endif #ifndef HasStdarg #define HasStdarg NO /* no stdarg.h */ #endif #ifndef HasVarargs #define HasVarargs NO /* no varargs.h */ #endif #ifndef HasUnistdH #if __STDC__ #define HasUnistdH YES #else #define HasUnistdH NO #endif #endif #ifndef HasStringH #define HasStringH YES #endif #ifndef HasVFork #if SystemV #define HasVFork NO #else #define HasVFork YES #endif #endif #ifndef HasVoidSignalReturn #if SystemV #define HasVoidSignalReturn YES #else #define HasVoidSignalReturn NO /* may or may not be true */ #endif #endif /* * TOPDIR, CURDIR are usually defined on the imake * command line and override these defaults */ #ifndef TOPDIR #define TOPDIR . #endif #ifndef CURDIR #define CURDIR . #endif /* * Configuration file identification - * name and release level of this set of configuration files */ #ifndef ConfigName #define ConfigName WRPRC2 #endif #ifndef ConfigMajorRelease #define ConfigMajorRelease 2 #endif #ifndef ConfigMinorRelease #define ConfigMinorRelease 11 #endif #ifndef ConfigRelease #define ConfigRelease $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) #endif #ifndef ConfigRootDir #define ConfigRootDir $(LOCALUSRLIBDIR)/config #endif /* Project name and release level -- override in project's Imake.p-params */ #ifndef ProjectWRPRC #define ProjectWRPRC $(CONFIGRELEASE) #endif #ifndef ProjectName #define ProjectName no-project-name #endif #ifndef ProjectMajorRelease #define ProjectMajorRelease 0 #endif #ifndef ProjectMinorRelease #define ProjectMinorRelease 00 #endif #ifndef ProjectRelease #define ProjectRelease $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) #endif /* * System layout - commonly-used directories */ /* * Standard system directories */ #ifndef BinDir #define BinDir /usr/bin #endif #ifndef UsrLibDir #define UsrLibDir /usr/lib #endif #ifndef LintLibDir #define LintLibDir $(USRLIBDIR)/lint #endif #ifndef AdmDir #define AdmDir /usr/adm #endif #ifndef EtcDir #define EtcDir /usr/etc #endif #ifndef IncludeRoot /* root of system include hierarchy */ #define IncludeRoot /usr/include #endif #ifndef TmpDir #define TmpDir /tmp #endif #ifndef SpoolRootDir #define SpoolRootDir /usr/spool #endif /* * Local system directories */ #ifndef LocalRootDir #define LocalRootDir /usr/local #endif #ifndef LocalBinDir #define LocalBinDir $(LOCALROOTDIR)/bin #endif #ifndef LocalUsrLibDir #define LocalUsrLibDir $(LOCALROOTDIR)/lib #endif #ifndef LocalLintLibDir #define LocalLintLibDir $(LOCALUSRLIBDIR)/lint #endif #ifndef LocalAdmDir #define LocalAdmDir $(LOCALROOTDIR)/adm #endif #ifndef LocalEtcDir #define LocalEtcDir $(LOCALROOTDIR)/etc #endif #ifndef LocalIncludeRoot #define LocalIncludeRoot $(LOCALROOTDIR)/include #endif /* * Manual page layout stuff - a mess, due to the differences in the way * various systems arrange pages. * * Typical man sections are 1-8, l (ell), and n. There are parameters for * each of these, and "generic" parameters that usually point to section * 1, l (ell), or n, and indicate the "typical" directory in which to * install program man pages. * * To point to /usr/local/man instead, set ManRoot in site.def or vendor.cf. * * If manual pages need to be preformatted when installed, override the * InstallManFile() rule in the vendor file and perhaps redefine ManSourcePath * with "cat" on the end rather than "man". */ #ifndef ManRoot /* root of system manpage hierarchy */ #if SystemV4 #define ManRoot /usr/share/man #else #define ManRoot /usr/man #endif #endif #ifndef ManSourcePath #define ManSourcePath $(MANROOT)/man #endif #ifndef Man1Suffix #define Man1Suffix 1 /* use just one tab or cpp will die */ #endif #ifndef Man2Suffix #define Man2Suffix 2 /* use just one tab or cpp will die */ #endif #ifndef Man3Suffix #define Man3Suffix 3 /* use just one tab or cpp will die */ #endif #ifndef Man4Suffix #define Man4Suffix 4 /* use just one tab or cpp will die */ #endif #ifndef Man5Suffix #define Man5Suffix 5 /* use just one tab or cpp will die */ #endif #ifndef Man6Suffix #define Man6Suffix 6 /* use just one tab or cpp will die */ #endif #ifndef Man7Suffix #define Man7Suffix 7 /* use just one tab or cpp will die */ #endif #ifndef Man8Suffix #define Man8Suffix 8 /* use just one tab or cpp will die */ #endif #ifndef ManLSuffix #define ManLSuffix l /* use just one tab or cpp will die */ #endif #ifndef ManNSuffix #define ManNSuffix n /* use just one tab or cpp will die */ #endif #ifndef ManSuffix /* set this to where man pages are "usually" installed */ #define ManSuffix $(MANLSUFFIX) /* use just one tab or cpp will die */ #endif #ifndef Man1Dir #define Man1Dir $(MANSOURCEPATH)$(MAN1SUFFIX) #endif #ifndef Man2Dir #define Man2Dir $(MANSOURCEPATH)$(MAN2SUFFIX) #endif #ifndef Man3Dir #define Man3Dir $(MANSOURCEPATH)$(MAN3SUFFIX) #endif #ifndef Man4Dir #define Man4Dir $(MANSOURCEPATH)$(MAN4SUFFIX) #endif #ifndef Man5Dir #define Man5Dir $(MANSOURCEPATH)$(MAN5SUFFIX) #endif #ifndef Man6Dir #define Man6Dir $(MANSOURCEPATH)$(MAN6SUFFIX) #endif #ifndef Man7Dir #define Man7Dir $(MANSOURCEPATH)$(MAN7SUFFIX) #endif #ifndef Man8Dir #define Man8Dir $(MANSOURCEPATH)$(MAN8SUFFIX) #endif #ifndef ManLDir #define ManLDir $(MANSOURCEPATH)$(MANLSUFFIX) #endif #ifndef ManNDir #define ManNDir $(MANSOURCEPATH)$(MANNSUFFIX) #endif #ifndef ManDir #define ManDir $(MANSOURCEPATH)$(MANSUFFIX) #endif /* configuration programs */ #ifndef ImbootCmd #define ImbootCmd imboot #endif #ifndef DependCmd #define DependCmd makedepend #endif #ifndef MkdirHierCmd #define MkdirHierCmd mkdirhier #endif #ifndef MsubCmd #define MsubCmd msub #endif /* Project development commands */ #ifndef ArCmd #if SystemV4 #define ArCmd ar cq #else #define ArCmd ar clq #endif #endif #ifndef CcCmd #if HasGcc2 #define CcCmd gcc -fpcc-struct-return #else #if HasGcc #define CcCmd gcc -fstrength-reduce -fpcc-struct-return #else #define CcCmd cc #endif #endif #endif #ifndef AsCmd #define AsCmd as #endif #ifndef CppCmd #define CppCmd /lib/cpp #endif #ifndef LdCmd #define LdCmd ld #endif #ifndef LintCmd #define LintCmd lint #endif #ifndef LintLibFlag #if SystemV || SystemV4 #define LintLibFlag -o #else #define LintLibFlag -C #endif #endif #ifndef LintOpts #if SystemV || SystemV4 #define LintOpts -bh #else #define LintOpts -axz #endif #endif #ifndef LintLibs #define LintLibs /**/ #endif #ifndef CpCmd #define CpCmd cp #endif #ifndef LnCmd #if HasSymLinks #define LnCmd ln -s #else #define LnCmd ln /* or even cp */ #endif #endif #ifndef MakeCmd #define MakeCmd make #endif #ifndef MvCmd #define MvCmd mv #endif #ifndef CmpCmd #define CmpCmd cmp #endif #ifndef RanlibCmd #define RanlibCmd ranlib #endif #ifndef RanlibInstFlags #define RanlibInstFlags /**/ #endif #ifndef RmCmd #define RmCmd rm -f #endif #ifndef TagsCmd #define TagsCmd ctags #endif /* full pathnames to perl and perl5, for use on #! lines in scripts */ #ifndef PerlPath #define PerlPath /usr/bin/perl #endif #ifndef Perl5Path #define Perl5Path /usr/bin/perl5 #endif /* names of perl and perl5, for command lines when pathname is unnecessary */ #ifndef PerlCmd #define PerlCmd perl #endif #ifndef Perl5Cmd #define Perl5Cmd perl5 #endif #ifndef AwkCmd #define AwkCmd awk #endif #ifndef SedCmd #define SedCmd sed #endif #ifndef CommCmd #define CommCmd comm #endif #ifndef CatCmd #define CatCmd cat #endif #ifndef ColCmd #define ColCmd col #endif #ifndef SortCmd #define SortCmd sort #endif #ifndef UniqCmd #define UniqCmd uniq #endif #ifndef ChmodCmd #define ChmodCmd chmod #endif #ifndef ChdirCmd #define ChdirCmd cd /* or maybe chdir */ #endif #ifndef SendmailPath #define SendmailPath /usr/lib/sendmail #endif /* Important local programs */ #ifndef FigenCmd #define FigenCmd figen #endif #ifndef DistarCmd #define DistarCmd distar #endif /* * Various flags */ #ifndef Osuf #define Osuf o #endif #ifndef StandardCppDefines #define StandardCppDefines /**/ #endif #ifndef StandardIncludes #define StandardIncludes -I$(LOCALINCLUDEROOT) #endif #ifndef StandardDefines #if SystemV4 #define StandardDefines -DSVR4 #else #if SystemV #define StandardDefines -DSYSV #else #define StandardDefines /**/ #endif #endif #endif #ifndef StandardLoadLibs #if SystemV4 #define StandardLoadLibs -lsocket -lnsl -lw #else #define StandardLoadLibs /**/ #endif #endif #ifndef StandardLoadFlags #define StandardLoadFlags -L$(LOCALUSRLIBDIR) #endif #ifndef ProjectIncludes #define ProjectIncludes /**/ #endif #ifndef ProjectDefines #define ProjectDefines /**/ #endif #ifndef ProjectLoadLibs #define ProjectLoadLibs /**/ #endif #ifndef ProjectLoadFlags #define ProjectLoadFlags /**/ #endif #ifndef DefaultCDebugFlags #define DefaultCDebugFlags -O #endif #ifndef DefaultCCOptions #define DefaultCCOptions /* as nothing: this is for floating point, etc. */ #endif #ifndef LoaderLibPrefix #define LoaderLibPrefix /**/ #endif #ifndef FilesToClean #define FilesToClean *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut #endif /* Installation support */ #ifndef InstallCmd #if SystemV || SystemV4 #define InstallCmd bsdinst #else #define InstallCmd install #endif #endif #ifndef InstCopy #define InstCopy -c /* redefine as nothing to disable */ #endif #ifndef InstStrip #define InstStrip -s /* redefine as nothing to disable */ #endif #ifndef InstOwner #define InstOwner /* as nothing */ #endif #ifndef InstGroup #define InstGroup /* as nothing */ #endif #ifndef InstProgMode #define InstProgMode -m 0755 #endif #ifndef InstUidProgMode #define InstUidProgMode -m 04755 #endif #ifndef InstGidProgMode #define InstGidProgMode -m 02755 #endif #ifndef InstUGidProgMode #define InstUGidProgMode -m 06755 #endif #ifndef InstScriptMode #define InstScriptMode -m 0755 #endif #ifndef InstLibMode #define InstLibMode -m 0644 #endif #ifndef InstDatMode #define InstDatMode -m 0444 #endif #ifndef InstManMode #define InstManMode -m 0444 #endif #ifndef InstIncMode #define InstIncMode -m 0444 #endif /* * Useful flag combinations. * Strip flag is used only to install binaries (avoids message from install * about stripping non-binaries). */ #ifndef InstProgFlags #define InstProgFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) #endif #ifndef InstUidProgFlags #define InstUidProgFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) #endif #ifndef InstGidProgFlags #define InstGidProgFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) #endif #ifndef InstUGidProgFlags #define InstUGidProgFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) #endif #ifndef InstScriptFlags #define InstScriptFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) #endif #ifndef InstLibFlags #define InstLibFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) #endif #ifndef InstDatFlags #define InstDatFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) #endif #ifndef InstManFlags #define InstManFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) #endif #ifndef InstIncFlags #define InstIncFlags $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) #endif /* Document preparation stuff */ #ifndef SoelimCmd #if HasSoelim #define SoelimCmd soelim #else #define SoelimCmd cat /* fake it */ #endif #endif #ifndef TroffCmd #define TroffCmd troff #endif #ifndef NroffCmd #define NroffCmd nroff #endif #ifndef TblCmd #define TblCmd tbl #endif #ifndef EqnCmd #define EqnCmd eqn #endif #ifndef NeqnCmd #define NeqnCmd neqn #endif #ifndef PicCmd #define PicCmd pic #endif #ifndef ManMacros #define ManMacros -man #endif #ifndef MeMacros #define MeMacros -me #endif #ifndef MmMacros #define MmMacros -mm #endif #ifndef MsMacros #define MsMacros -ms #endif #ifndef MdocMacros #define MdocMacros -mdoc #endif #ifndef TroffcvtCmd #define TroffcvtCmd troffcvt #endif #ifndef TblcvtCmd #define TblcvtCmd tblcvt #endif #ifndef Troff2HtmlCmd #define Troff2HtmlCmd troff2html #endif #ifndef Troff2RtfCmd #define Troff2RtfCmd troff2rtf #endif #ifndef UnroffCmd #define UnroffCmd unroff #endif #ifndef TcManMacros #define TcManMacros -man #endif #ifndef TcMeMacros #define TcMeMacros -me #endif #ifndef TcMmMacros #define TcMmMacros -mm #endif #ifndef TcMsMacros #define TcMsMacros -ms #endif #ifndef TcMdocMacros #define TcMdocMacros -mdoc #endif /* * Libraries often used to build WRPRC projects. * * For every library, there is a XXXLIB variable for link purposes and a * DEPXXXLIB variable for dependency purposes. * * The default values below assume the libraries are already installed * as system libraries. If the current project is one that builds one * of these libraries, its Imake.p-params should override the XxxLib and * DepXxxLib macros to point to the library's location within the project. */ #ifndef BibStuffLib /* refer record manipulation library */ #define BibStuffLib -lbibstuff #endif #ifndef DepBibStuffLib #define DepBibStuffLib /**/ #endif #ifndef EtmLib /* Exception and Termination Manager library */ #define EtmLib -letm #endif #ifndef DepEtmLib #define DepEtmLib /**/ #endif #ifndef FplLib /* Form Processing library */ #define FplLib -lfpl #endif #ifndef DepFplLib #define DepFplLib /**/ #endif #ifndef FqlLib /* Form Query library */ #define FqlLib -lfql #endif #ifndef DepFqlLib #define DepFqlLib /**/ #endif #ifndef GecosLib /* GECOS library */ #define GecosLib -lgecos #endif #ifndef DepGecosLib #define DepGecosLib /**/ #endif #ifndef LogMgrLib /* simple Log Manager library */ #define LogMgrLib -llogmgr #endif #ifndef DepLogMgrLib #define DepLogMgrLib /**/ #endif #ifndef MemMgrLib /* simple Memory Manager library */ #define MemMgrLib -lmemmgr #endif #ifndef DepMemMgrLib #define DepMemMgrLib /**/ #endif #ifndef NdsLib /* Network Database Service library */ #define NdsLib -lnds #endif #ifndef DepNdsLib #define DepNdsLib /**/ #endif #ifndef NioLib /* Network I/O library */ #define NioLib -lnio #endif #ifndef DepNioLib #define DepNioLib /**/ #endif #ifndef OrderLib /* Order processing library */ #define OrderLib -lorder #endif #ifndef DepOrderLib #define DepOrderLib /**/ #endif #ifndef SeqNumLib /* Sequence number library */ #define SeqNumLib -lseqnum #endif #ifndef DepSeqNumLib #define DepSeqNumLib /**/ #endif #ifndef SimScrLib /* Simple Screen-management library */ #define SimScrLib -lsimscr #endif #ifndef DepSimScrLib #define DepSimScrLib /**/ #endif #ifndef TfmLib /* Temporary File Manager library */ #define TfmLib -ltfm #endif #ifndef DepTfmLib #define DepTfmLib /**/ #endif #ifndef TsLib /* Token Scanning library */ #define TsLib -ltokenscan #endif #ifndef DepTsLib #define DepTsLib /**/ #endif #ifndef PortLib /* Portability library */ #define PortLib -lport #endif #ifndef DepPortLib #define DepPortLib /**/ #endif XCOMM ------------------------------------------------------------------------- XCOMM definitions common to all Makefiles PATHSEP = / /* for building filenames */ #if ConstructMFLAGS MFLAGS = -$(MAKEFLAGS) #endif SHELL = BourneShell #if HasStdarg #define xx_stdarg_defines_xx -DSTDARG #else #define xx_stdarg_defines_xx #endif #if HasVarargs #define xx_varargs_defines_xx -DVARARGS #else #define xx_varargs_defines_xx #endif VARARGS_DEFINES = xx_stdarg_defines_xx xx_varargs_defines_xx #undef xx_stdarg_defines_xx #undef xx_varargs_defines_xx #if !HasVoidSignalReturn SIGNAL_DEFINES = -DSIGNALRETURNSINT #endif TOP = TOPDIR CURRENT_DIR = CURDIR XCOMM Configuration file identification - name and release level CONFIGNAME = ConfigName CONFIGMAJORRELEASE = ConfigMajorRelease CONFIGMINORRELEASE = ConfigMinorRelease CONFIGRELEASE = ConfigRelease CONFIGROOTDIR = ConfigRootDir XCOMM Project identfication - name and release level PROJECTNAME = ProjectName PROJECTMAJORRELEASE = ProjectMajorRelease PROJECTMINORRELEASE = ProjectMinorRelease PROJECTRELEASE = ProjectRelease BINDIR = BinDir /* user program directory */ USRLIBDIR = UsrLibDir /* system library directory */ LINTLIBDIR = LintLibDir /* lint library directory ADMDIR = AdmDir /* administrative file directory */ ETCDIR = EtcDir /* server directory */ INCLUDEROOT = IncludeRoot /* top of system include tree */ TMPDIR = TmpDir /* temporary file directory */ SPOOLROOTDIR = SpoolRootDir /* root of spool hierarchy */ LOCALROOTDIR = LocalRootDir LOCALBINDIR = LocalBinDir LOCALUSRLIBDIR = LocalUsrLibDir LOCALLINTLIBDIR = LocalLintLibDir LOCALADMDIR = LocalAdmDir LOCALETCDIR = LocalEtcDir LOCALINCLUDEROOT = LocalIncludeRoot MANROOT = ManRoot /* top of manual page tree */ MANSOURCEPATH = ManSourcePath /* prefix for man page sources */ MAN1SUFFIX = Man1Suffix MAN2SUFFIX = Man2Suffix MAN3SUFFIX = Man3Suffix MAN4SUFFIX = Man4Suffix MAN5SUFFIX = Man5Suffix MAN6SUFFIX = Man6Suffix MAN7SUFFIX = Man7Suffix MAN8SUFFIX = Man8Suffix MANLSUFFIX = ManLSuffix MANNSUFFIX = ManNSuffix MANSUFFIX = ManSuffix MAN1DIR = Man1Dir /* man pages for section 1 */ MAN2DIR = Man2Dir /* man pages for section 2 */ MAN3DIR = Man3Dir /* man pages for section 3 */ MAN4DIR = Man4Dir /* man pages for section 4 */ MAN5DIR = Man5Dir /* man pages for section 5 */ MAN6DIR = Man6Dir /* man pages for section 6 */ MAN7DIR = Man7Dir /* man pages for section 7 */ MAN8DIR = Man8Dir /* man pages for section 8 */ MANLDIR = ManLDir /* man pages for section l */ MANNDIR = ManNDir /* man pages for section n */ MANDIR = ManDir /* man pages for commands */ IMBOOT = ImbootCmd DEPEND = DependCmd MSUB = MsubCmd MKDIRHIER = MkdirHierCmd AR = ArCmd CC = CcCmd CPP = CppCmd $(STD_CPP_DEFINES) /* simple filters */ LD = LdCmd LINT = LintCmd LINTLIBFLAG = LintLibFlag LINTOPTS = LintOpts LINTLIBS = LintLibs LN = LnCmd MAKE = MakeCmd MV = MvCmd CP = CpCmd CMP = CmpCmd #if HasRanlibCmd RANLIB = RanlibCmd RANLIBINSTFLAGS = RanlibInstFlags #endif RM = RmCmd TAGS = TagsCmd PERL = PerlCmd PERLPATH = PerlPath PERL5 = Perl5Cmd PERL5PATH = Perl5Path AWK = AwkCmd SED = SedCmd COMM = CommCmd CAT = CatCmd COL = ColCmd SORT = SortCmd UNIQ = UniqCmd CHMOD = ChmodCmd CHDIR = ChdirCmd SENDMAILPATH = SendmailPath XCOMM Important local programs FIGEN = FigenCmd DISTAR = DistarCmd /* * STD_INCLUDES contains system-specific includes that apply to all * builds for all projects. Override by setting StandardIncludes in * Imake.p-params, site.def or site.p-def. * PROJECT_INCLUDES contains project-specific includes that apply to * all builds for a particular project. Override by setting * ProjectIncludes in Imake.p-params. * INCLUDES contains Imakefile-specific includes. Has no default value; * use by setting INCLUDES in Imakefile. * * STD_DEFINES, PROJECT_DEFINES, and DEFINES are similar, except they * are for -D's and -U's, rather than -I's. Override by setting * StandardDefines in Imake.p-params, site.def or site.p-def, ProjectDefines in * Imake.p-params, or DEFINES in Imakefile. * * STD_LDLIBS, PROJECT_LDLIBS, and LDLIBS are similar, except they are * for link libraries. * * STD_LDFLAGS, PROJECT_LDFLAGS, and LDFLAGS are similar, except they are * for loader flags. */ XCOMM Standard system include file directories, defines, etc. STD_CPP_DEFINES = StandardCppDefines STD_INCLUDES = StandardIncludes STD_DEFINES = StandardDefines STD_LDLIBS = StandardLoadLibs STD_LDFLAGS = StandardLoadFlags XCOMM Project-specific include file directories, defines, etc. PROJECT_INCLUDES = ProjectIncludes PROJECT_DEFINES = ProjectDefines PROJECT_LDLIBS = ProjectLoadLibs PROJECT_LDFLAGS = ProjectLoadFlags LOADERLIBPREFIX = LoaderLibPrefix CDEBUGFLAGS = DefaultCDebugFlags CCOPTIONS = DefaultCCOptions /* to distinguish from param flags */ ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) FilesToClean INSTALL = InstallCmd INSTCOPY = InstCopy INSTSTRIP = InstStrip INSTOWNER = InstOwner INSTGROUP = InstGroup INSTPROGMODE = InstProgMode INSTUIDPROGMODE = InstUidProgMode INSTGIDPROGMODE = InstGidProgMode INSTUGIDPROGMODE = InstUGidProgMode INSTSCRIPTMODE = InstScriptMode INSTLIBMODE = InstLibMode INSTDATMODE = InstDatMode INSTMANMODE = InstManMode INSTINCMODE = InstIncMode INSTPROGFLAGS = InstProgFlags INSTUIDPROGFLAGS = InstUidProgFlags INSTGIDPROGFLAGS = InstGidProgFlags INSTUGIDPROGFLAGS = InstUGidProgFlags INSTSCRIPTFLAGS = InstScriptFlags INSTLIBFLAGS = InstLibFlags INSTDATFLAGS = InstDatFlags INSTMANFLAGS = InstManFlags INSTINCFLAGS = InstIncFlags SOELIM = SoelimCmd TROFF = TroffCmd NROFF = NroffCmd TBL = TblCmd EQN = EqnCmd NEQN = NeqnCmd PIC = PicCmd MANMACROS = ManMacros MEMACROS = MeMacros MMMACROS = MmMacros MSMACROS = MsMacros MDOCMACROS = MdocMacros TROFFCVT = TroffcvtCmd TBLCVT = TblcvtCmd TROFF2HTML = Troff2HtmlCmd TROFF2RTF = Troff2RtfCmd UNROFF = UnroffCmd TCMANMACROS = TcManMacros TCMEMACROS = TcMeMacros TCMMMACROS = TcMmMacros TCMSMACROS = TcMsMacros TCMDOCMACROS = TcMdocMacros XCOMM Library link and dependency specifiers BIBSTUFFLIB = BibStuffLib DEPBIBSTUFFLIB = DepBibStuffLib ETMLIB = EtmLib DEPETMLIB = DepEtmLib FPLLIB = FplLib DEPFPLLIB = DepFplLib FQLLIB = FqlLib DEPFQLLIB = DepFqlLib GECOSLIB = GecosLib DEPGECOSLIB = DepGecosLib LOGMGRLIB = LogMgrLib DEPLOGMGRLIB = DepLogMgrLib MEMMGRLIB = MemMgrLib DEPMEMMGRLIB = DepMemMgrLib NDSLIB = NdsLib DEPNDSLIB = DepNdsLib NIOLIB = NioLib DEPNIOLIB = DepNioLib ORDERLIB = OrderLib DEPORDERLIB = DepOrderLib SEQNUMLIB = SeqNumLib DEPSEQNUMLIB = DepSeqNumLib SIMSCRLIB = SimScrLib DEPSIMSCRLIB = DepSimScrLib TFMLIB = TfmLib DEPTFMLIB = DepTfmLib TSLIB = TsLib DEPTSLIB = DepTsLib PORTLIB = PortLib DEPPORTLIB = DepPortLib XCOMM Makefile-generating commands and parameters IMBOOT_DEFINES = /* leave blank, for command line use only */ IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) #ifndef DepFqlLib #define DepFqlLib /**/ #endif #ifndef GecosLib /* GECOS library */ #define GecosLib -lgecos #endif #ifndef DepGecosLib #define DepGecosLib /**/ #endif #ifndef LogMgrLib /* simple Log Manager library */ #define LogMgrLib -llogmgr #endif #ifndef DepLogMgrLib #define DepLogMgrLib /**/ #endif #ifndef MemMgrLib /* simple Memory Manager library */ #define MemMgrLib -lmemmgr #endif #ifndef DepMemMgrLib #define DepMemMgrLib /**/ #endifWRPRC-2.11/config/osf1.p-cf010066400017710000151000000000000634140471700167360ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/Imake.p-params010066400017710000151000000000000634140471700200070ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/Imakefile010066400017710000151000000141670634140471700171530ustar00junkyarddatamgmt00000400000027CFFILES = README Imake.tmpl \ Imake.params Imake.p-params \ Imake.rules Imake.p-rules \ site.def site.p-def \ *.cf *.p-cf INSTALLDIR = $(CONFIGROOTDIR)/$(CONFIGNAME) all:: InstallMultipleDataFiles(install,$(CFFILES),$(INSTALLDIR)) test:: @echo "AdmDir: "AdmDir @echo "ArCmd: "ArCmd @echo "AsCmd: "AsCmd @echo "AwkCmd: "AwkCmd @echo "BibStuffLib: "BibStuffLib @echo "BinDir: "BinDir @echo "BourneShell: "BourneShell @echo "CURDIR: "CURDIR @echo "CatCmd: "CatCmd @echo "CcCmd: "CcCmd @echo "ChdirCmd: "ChdirCmd @echo "ChmodCmd: "ChmodCmd @echo "CmpCmd: "CmpCmd @echo "CommCmd: "CommCmd @echo "ConfigMajorRelease: "ConfigMajorRelease @echo "ConfigMinorRelease: "ConfigMinorRelease @echo "ConfigName: "ConfigName @echo "ConfigRelease: "ConfigRelease @echo "ConfigRootDir: "ConfigRootDir @echo "ConstructMFLAGS: "ConstructMFLAGS @echo "CpCmd: "CpCmd @echo "CppCmd: "CppCmd @echo "DefaultCCOptions: "DefaultCCOptions @echo "DefaultCDebugFlags: "DefaultCDebugFlags @echo "DepBibStuffLib: "DepBibStuffLib @echo "DepEtmLib: "DepEtmLib @echo "DepFplLib: "DepFplLib @echo "DepFqlLib: "DepFqlLib @echo "DepGecosLib: "DepGecosLib @echo "DepLogMgrLib: "DepLogMgrLib @echo "DepMemMgrLib: "DepMemMgrLib @echo "DepNdsLib: "DepNdsLib @echo "DepNioLib: "DepNioLib @echo "DepOrderLib: "DepOrderLib @echo "DepSeqNumLib: "DepSeqNumLib @echo "DepSimScrLib: "DepSimScrLib @echo "DepTsLib: "DepTsLib @echo "DependCmd: "DependCmd @echo "DistarCmd: "DistarCmd @echo "EqnCmd: "EqnCmd @echo "EtcDir: "EtcDir @echo "EtmLib: "EtmLib @echo "FigenCmd: "FigenCmd @echo "FilesToClean: "FilesToClean @echo "FplLib: "FplLib @echo "FqlLib: "FqlLib @echo "GecosLib: "GecosLib @echo "HasExecableScripts: "HasExecableScripts @echo "HasGcc2: "HasGcc2 @echo "HasGcc: "HasGcc @echo "HasRanlibCmd: "HasRanlibCmd @echo "HasSoelim: "HasSoelim @echo "HasStdarg: "HasStdarg @echo "HasSymLinks: "HasSymLinks @echo "HasUnistdH: "HasUnistdH @echo "HasVFork: "HasVFork @echo "HasVarargs: "HasVarargs @echo "HasVoidSignalReturn: "HasVoidSignalReturn @echo "ImbootCmd: "ImbootCmd @echo "IncludeRoot: "IncludeRoot @echo "InstCopy: "InstCopy @echo "InstDatFlags: "InstDatFlags @echo "InstDatMode: "InstDatMode @echo "InstGidProgFlags: "InstGidProgFlags @echo "InstGidProgMode: "InstGidProgMode @echo "InstGroup: "InstGroup @echo "InstIncFlags: "InstIncFlags @echo "InstIncMode: "InstIncMode @echo "InstLibFlags: "InstLibFlags @echo "InstLibMode: "InstLibMode @echo "InstManFlags: "InstManFlags @echo "InstManMode: "InstManMode @echo "InstOwner: "InstOwner @echo "InstProgFlags: "InstProgFlags @echo "InstProgMode: "InstProgMode @echo "InstScriptFlags: "InstScriptFlags @echo "InstScriptMode: "InstScriptMode @echo "InstStrip: "InstStrip @echo "InstUGidProgFlags: "InstUGidProgFlags @echo "InstUGidProgMode: "InstUGidProgMode @echo "InstUidProgFlags: "InstUidProgFlags @echo "InstUidProgMode: "InstUidProgMode @echo "InstallCmd: "InstallCmd @echo "LdCmd: "LdCmd @echo "LintCmd: "LintCmd @echo "LintLibDir: "LintLibDir @echo "LintLibFlag: "LintLibFlag @echo "LintLibs: "LintLibs @echo "LintOpts: "LintOpts @echo "LnCmd: "LnCmd @echo "LoaderLibPrefix: "LoaderLibPrefix @echo "LocalAdmDir: "LocalAdmDir @echo "LocalBinDir: "LocalBinDir @echo "LocalEtcDir: "LocalEtcDir @echo "LocalIncludeRoot: "LocalIncludeRoot @echo "LocalLintLibDir: "LocalLintLibDir @echo "LocalRootDir: "LocalRootDir @echo "LocalUsrLibDir: "LocalUsrLibDir @echo "LogMgrLib: "LogMgrLib @echo "MakeCmd: "MakeCmd @echo "Man1Dir: "Man1Dir @echo "Man1Suffix: "Man1Suffix @echo "Man2Dir: "Man2Dir @echo "Man2Suffix: "Man2Suffix @echo "Man3Dir: "Man3Dir @echo "Man3Suffix: "Man3Suffix @echo "Man4Dir: "Man4Dir @echo "Man4Suffix: "Man4Suffix @echo "Man5Dir: "Man5Dir @echo "Man5Suffix: "Man5Suffix @echo "Man6Dir: "Man6Dir @echo "Man6Suffix: "Man6Suffix @echo "Man7Dir: "Man7Dir @echo "Man7Suffix: "Man7Suffix @echo "Man8Dir: "Man8Dir @echo "Man8Suffix: "Man8Suffix @echo "ManDir: "ManDir @echo "ManLDir: "ManLDir @echo "ManLSuffix: "ManLSuffix @echo "ManMacros: "ManMacros @echo "ManNDir: "ManNDir @echo "ManNSuffix: "ManNSuffix @echo "ManRoot: "ManRoot @echo "ManSourcePath: "ManSourcePath @echo "ManSuffix: "ManSuffix @echo "MdocMacros: "MdocMacros @echo "MeMacros: "MeMacros @echo "MemMgrLib: "MemMgrLib @echo "MkdirHierCmd: "MkdirHierCmd @echo "MmMacros: "MmMacros @echo "MsMacros: "MsMacros @echo "MsubCmd: "MsubCmd @echo "MvCmd: "MvCmd @echo "NdsLib: "NdsLib @echo "NeqnCmd: "NeqnCmd @echo "NioLib: "NioLib @echo "NroffCmd: "NroffCmd @echo "OSMajorVersion: "OSMajorVersion @echo "OSMinorVersion: "OSMinorVersion @echo "OSTeenyVersion: "OSTeenyVersion @echo "OrderLib: "OrderLib @echo "Perl5Cmd: "Perl5Cmd @echo "Perl5Path: "Perl5Path @echo "PerlCmd: "PerlCmd @echo "PerlPath: "PerlPath @echo "PicCmd: "PicCmd @echo "ProjectDefines: "ProjectDefines @echo "ProjectIncludes: "ProjectIncludes @echo "ProjectLoadFlags: "ProjectLoadFlags @echo "ProjectLoadLibs: "ProjectLoadLibs @echo "ProjectMajorRelease: "ProjectMajorRelease @echo "ProjectMinorRelease: "ProjectMinorRelease @echo "ProjectName: "ProjectName @echo "ProjectRelease: "ProjectRelease @echo "RanlibCmd: "RanlibCmd @echo "RanlibInstFlags: "RanlibInstFlags @echo "RmCmd: "RmCmd @echo "SedCmd: "SedCmd @echo "SeqNumLib: "SeqNumLib @echo "SimScrLib: "SimScrLib @echo "SoelimCmd: "SoelimCmd @echo "SortCmd: "SortCmd @echo "StandardCppDefines: "StandardCppDefines @echo "StandardDefines: "StandardDefines @echo "StandardIncludes: "StandardIncludes @echo "StandardLoadFlags: "StandardLoadFlags @echo "StandardLoadLibs: "StandardLoadLibs @echo "SystemV4: "SystemV4 @echo "SystemV: "SystemV @echo "TOPDIR: "TOPDIR @echo "TagsCmd: "TagsCmd @echo "TblCmd: "TblCmd @echo "TblcvtCmd: "TblcvtCmd @echo "TcManMacros: "TcManMacros @echo "TcMdocMacros: "TcMdocMacros @echo "TcMeMacros: "TcMeMacros @echo "TcMmMacros: "TcMmMacros @echo "TcMsMacros: "TcMsMacros @echo "TmpDir: "TmpDir @echo "Troff2HtmlCmd: "Troff2HtmlCmd @echo "Troff2RtfCmd: "Troff2RtfCmd @echo "TroffCmd: "TroffCmd @echo "TroffcvtCmd: "TroffcvtCmd @echo "TsLib: "TsLib @echo "UniqCmd: "UniqCmd @echo "UnroffCmd: "UnroffCmd @echo "UsrLibDir: "UsrLibDir WRPRC-2.11/config/osf1.cf010066400017710000151000000011340634140471700165120ustar00junkyarddatamgmt00000400000027/* this file is not very well tested... */ /* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES */ #ifndef OSName #define OSName OSF/1 1.2 #endif #ifndef OSMajorVersion #define OSMajorVersion 1 #endif #ifndef OSMinorVersion #define OSMinorVersion 2 #endif XCOMM platform: osf1.cf 93/08/05 XCOMM operating system: OSName #ifndef HasVarargs #define HasVarargs YES #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES #endif #ifndef InstallCmd #define InstallCmd installbsd #endif #ifndef LintLibFlag #define LintLibFlag -o #endif #ifndef LintOpts #define LintOpts -bh #endif WRPRC-2.11/config/Imake.p-cf010066400017710000151000000000000634140471700171140ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/Imake.rules010066400017710000151000001215520634140471700174410ustar00junkyarddatamgmt00000400000027/***************************************************************************** * * * Imake rules * * * *****************************************************************************/ /* * Derived in part from X Window System X11R3-R6 imake rules, and from * WRPRC release 1 rules. * * Some conventions to use in Imakefiles: * * INCLUDES and DEFINES can be used in individual Imakefiles to specify * special include directories or defines that should apply only within a * given Makefile. * * PROJECT_INCLUDES and PROJECT_DEFINES may be used for includes and * definitions that should apply project-wide. The corresponding macros * ProjectIncludes and ProjectDefines are given default values in the * public Imake.params. A project may override the defaults by assigning * these macros values in the project-specific Imake.p-params file. */ #ifndef NullArg /* for specifying null (empty) arguments */ #define NullArg #endif #ifndef NullParameter /* same, but for compatibility with X11 */ #define NullParameter #endif /***************************************************************************** * Directory-making stuff * *****************************************************************************/ /* * If [ -d ] or [ ! -d ] causes make to fail, define this as - in your * system's vendor file */ #ifndef DirFailPrefix #define DirFailPrefix #endif /* * MakeDir() - make a directory if it does't already exist. Used by most * installation rules to ensure that the destination directory exists. * * This rule is used tab-indented as a command line in other rules. */ #ifndef MakeDir #define MakeDir(dir) DirFailPrefix@if [ -d dir ]; then set +x; \ @@\ else (set -x; $(MKDIRHIER) dir); fi #endif /* MakeDir */ /* * MakeDirectories() - make one or more directories as part of the named * operation. */ #ifndef MakeDirectories #define MakeDirectories(op,dirs) @@\ op:: @@\ $(MKDIRHIER) dirs #endif /* MakeDirectories */ /***************************************************************************** * * * Target-building rules * * * *****************************************************************************/ /***************************************************************************** * Rules for generating target names * *****************************************************************************/ #ifndef ProgramTargetName #define ProgramTargetName(target)target #endif #ifndef LibraryTargetName #define LibraryTargetName(libname)Concat(lib,libname.a) #endif #ifndef LintLibraryTargetName #define LintLibraryTargetName(libname)Concat(llib-l,libname.ln) #endif /***************************************************************************** * Rules for building executable programs * *****************************************************************************/ /* * BuildProgram() generates entries to build, remove, and * lint a single program. May be invoked multiple times * in the same Imakefile. * * This rule is the general interface for building programs. * * Arguments: * prog program name * srcs program's source files * objs program's object files * linklibs libraries needed to link program * deplibs libraries to check as dependencies * (must be given as pathnames) * * Targets produced: * all build prog (and all others in Imakefile) * prog build prog only * clean remove all programs in Imakefile * lint lint all programs in Imakefile * lint.prog lint prog only */ #ifndef BuildProgram #define BuildProgram(prog,srcs,objs,linklibs,deplibs) @@\ AllTarget(ProgramTargetName(prog)) @@\ HelpAuxTarget(ProgramTargetName(prog),build ProgramTargetName(prog)) @@\ ProgramTargetName(prog): objs deplibs @@\ RemoveTarget($@) @@\ $(CC) -o $@ objs $(LDOPTS) linklibs $(EXTRA_LDLIBS) @@\ StuffToClean(ProgramTargetName(prog)) @@\ LintSources(ProgramTargetName(prog),srcs) #endif /* BuildProgram */ /* * BuildSimpleProgram() is a simplified version of BuildProgram() that * assumes a single source file name.c, sets SRCS and OBJS, invokes * BuildProgram(), as well as installation and manpage installation rules, * and invokes DependTarget(). May be called only once per Imakefile, and * should not be used with any other program or library-building rules. * * The manual page is assumed to be named name.man. * * The program is installed in LOCALBINDIR and the manual page in MANDIR. */ #ifndef BuildSimpleProgram #define BuildSimpleProgram(name,linklibs,deplibs) @@\ SRCS = name.c @@\ OBJS = name.o @@\ @@\ BuildProgram(name,$(SRCS),$(OBJS),linklibs,deplibs) @@\ InstallProgram(name,$(LOCALBINDIR)) @@\ InstallManPage(name) @@\ @@\ DependTarget() #endif /* BuildSimpleProgram */ /* * SpecialObjectTarget() - compile an object file with special flags * * Arguments: * dst object file name * src source file name * flags special compile flags * depends any special dependencies (in addition to src) * * Targets produced: * dst compile this file */ #ifndef SpecialObjectTarget #define SpecialObjectTarget(dst,src,flags,depends) @@\ dst: src depends @@\ RemoveTarget($@) @@\ $(CC) -c $(CFLAGS) flags src #endif /* SpecialObjectTarget */ /* * SpecialCObjectTarget() - compile a C object file with special flags * * Arguments: * basename file basename (no suffix) * flags special compile flags * depends any special dependencies (in addition to src) * * Targets produced: * dst compile this file */ #ifndef SpecialCObjectTarget #define SpecialCObjectTarget(basename,flags,depends) @@\ SpecialObjectTarget(basename.Osuf,basename.c,flags,depends) #endif /* SpecialCObjectTarget */ /***************************************************************************** * Library-building rules * *****************************************************************************/ /* * NormalLibraryObjectRule() - For building objects in libraries. * Invoke when using BuildNormalLibrary(). Needs to be invoked only * once, even if you're building multiple libraries in a directory. * Since this rule overrides the normal *.c -> *.o transformation, * it's best not to build programs and libraries in the same directory. */ #ifndef NormalLibraryObjectRule #define NormalLibraryObjectRule() @@\ .c.o: @@\ RemoveTarget ($@) @@\ $(CC) -c $(CFLAGS) $*.c #endif /* NormalLibraryObjectRule */ /* * BuildNormalLibrary() - generate target entry to build a library from * the named object files. When you use this, invoke NormalLibraryObjectRule() * as well. * * Arguments: * name library name; this is the basename, the target name * is "libname.a" * srcs library's source files * objs library's object files * * Targets produced: * all build this library (and all others in Imakefile) * libname.a build this library only * clean remove all libraries in Imakefile * lint lint all sources in Imakefile * lint.libname.a lint sources for libname.a only */ #ifndef BuildNormalLibrary #define BuildNormalLibrary(name,srcs,objs) @@\ AllTarget(LibraryTargetName(name)) @@\ LibraryTargetName(name): objs @@\ RemoveTarget($@) @@\ $(AR) $@ objs @@\ RanLibrary($@) @@\ StuffToClean(LibraryTargetName(name)) @@\ LintSources(LibraryTargetName(name),srcs) @@\ HelpAuxTarget(LibraryTargetName(name),build the LibraryTargetName(name) library) #endif /* BuildNormalLibrary */ /* Build a lint library */ #ifndef BuildLintLibrary #define BuildLintLibrary(name,srcs) @@\ lintlib:: LintLibraryTargetName(name) @@\ @@\ LintLibraryTargetName(name):: srcs @@\ RemoveTarget($@) @@\ $(LINT) Concat($(LINTLIBFLAG),name) $(LINTFLAGS) srcs @@\ StuffToClean(LintLibraryTargetName(name)) @@\ HelpAuxTarget(LintLibraryTargetName(name),build the LintLibraryTargetName(name) lint library) #endif /* BuildLintLibrary */ /***************************************************************************** * Rules for building targets by running templates through filters * *****************************************************************************/ /* * FileFromTemplate() - Create a non-executable target file by running a * template through a filter. */ #ifndef FileFromTemplate #define FileFromTemplate(dst,src,filter,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ filter src > $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build dst) #endif /* FileFromTemplate */ /* * ScriptFromTemplate() - Create an executable target file (i.e., a script) * for some arbitrary program by running a template through some filter. * prog must be a full pathname. * * If the HasExecableScripts configuration parameter is not YES, make sure * the first line begins with a colon and write the script into a temp * file, have the program execute that, and remove the temp file when * done. Ugly ugly ugly. On the other hand, the template need not begin * with a #! line. */ #ifndef ScriptFromTemplate #if HasExecableScripts /* can use #! */ #define ScriptFromTemplate(prog,dst,src,filter,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo "#!"prog > $@ @@\ filter src >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #else #define ScriptFromTemplate(prog,dst,src,filter,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo \: > $@ @@\ echo 'x=$(TMPDIR)/xx$$$$' >> $@ @@\ echo "$(CAT) > "'$$x'" << 'EOF'" >> $@ @@\ filter src >> $@ @@\ echo EOF >> $@ @@\ echo prog '$$x' '$$@' >> $@ @@\ echo $(RM) '$$x' >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #endif /* HasExecableScripts */ #endif /* ScriptFromTemplate */ /* * Rules for building targets by running templates through msub * * FileFromMsubTemplate() - create non-executable target * FileFromMsubTemplateWithFlags() - create non-executable target, allowing * flags to be passed to Msub * ScriptFromMsubTemplate() - create executable script for arbitrary program * ShScriptFromMsubTemplate() - create executable shell script * ScriptFromMsubTemplateWithFlags() - create executable script for arbitrary * program, allowing flags to be passed to Msub * ShScriptFromMsubTemplateWithFlags() - create executable shell script, * allowing flags to be passed to Msub * * Arguments: * prog - program that should process script; must be full pathname * dst - name of file to produce * src - name of template from which file is produced * flags - flags to pass to msub * deps - dependencies that must exist before building dst */ #ifndef FileFromMsubTemplate #define FileFromMsubTemplate(dst,src,deps) @@\ FileFromTemplate(dst,src,$(MSUB),deps) #endif /* FileFromMsubTemplate */ #ifndef ScriptFromMsubTemplate #define ScriptFromMsubTemplate(prog,dst,src,deps) @@\ ScriptFromTemplate(prog,dst,src,$(MSUB),deps) #endif /* ScriptFromMsubTemplate */ #ifndef ShScriptFromMsubTemplate #define ShScriptFromMsubTemplate(dst,src,deps) @@\ ScriptFromTemplate($(SHELL),dst,src,$(MSUB),deps) #endif /* ShScriptFromMsubTemplate */ #ifndef FileFromMsubTemplateWithFlags #define FileFromMsubTemplateWithFlags(dst,src,flags,deps) @@\ FileFromTemplate(dst,src,$(MSUB) flags,deps) #endif /* FileFromMsubTemplateWithFlags */ #ifndef ScriptFromMsubTemplateWithFlags #define ScriptFromMsubTemplateWithFlags(prog,dst,src,flags,deps) @@\ ScriptFromTemplate(prog,dst,src,$(MSUB) flags,deps) #endif /* ScriptFromMsubTemplateWithFlags */ #ifndef ShScriptFromMsubTemplateWithFlags #define ShScriptFromMsubTemplateWithFlags(dst,src,flags,deps) @@\ ScriptFromTemplate($(SHELL),dst,src,$(MSUB) flags,deps) #endif /* ShScriptFromMsubTemplateWithFlags */ /* * Rules for building targets by running templates through cpp * * FileFromCppTemplate() - create non-executable target * ScriptFromCppTemplate() - create executable script for arbitrary program * ShScriptFromCppTemplate() - create executable shell script * * For all of these, translate XCOMM into pound sign with sed, rather than * passing -DXCOMM=XCOMM to cpp, because that trick does not work on all * ANSI C preprocessors. (Translation occurs at beginning of lines only.) * Also delete line numbers from the cpp output (-P is not portable, I guess). * * Arguments: * prog - program that should process script; must be full pathname * dst - name of file to produce * src - name of template from which file is produced * defs - defines to pass to cpp * deps - dependencies that must exist before building dst */ #ifndef CppSedMagic #define CppSedMagic sed -e '/^# *[0-9][0-9]* *.*$$/d' \ -e '/^XCOMM$$/s//#/' \ -e '/^XCOMM[^a-zA-Z0-9_]/s/^XCOMM/#/' #endif /* CppSedMagic */ #ifndef FileFromCppTemplate #define FileFromCppTemplate(dst,src,defs,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ $(CPP) defs < src | CppSedMagic >> $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build dst) #endif /* FileFromCppTemplate */ /* * ScriptFromCppTemplate() - generate target entry to create a script for * an arbitrary program by running the input through cpp. If the * HasExecableScripts configuration parameter is not YES, then make sure * that the first line begins with a colon and write the script into a * temp file, have the program execute that, and remove the temp file when * done. Ugly ugly ugly. On the other hand, the template need not begin * with a #! line. * * prog must be a full pathname. */ #ifndef ScriptFromCppTemplate #if HasExecableScripts /* can use #! */ #define ScriptFromCppTemplate(prog,dst,src,defs,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo "#!"prog > $@ @@\ $(CPP) defs < src | CppSedMagic >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #else #define ScriptFromCppTemplate(prog,dst,src,defs,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo \: > $@ @@\ echo 'x=/tmp/xx$$$$' >> $@ @@\ echo "$(CAT) > "'$$x'" << 'EOF'" >> $@ @@\ $(CPP) defs < src | CppSedMagic >> $@ @@\ echo EOF >> $@ @@\ echo prog '$$x' '$$@' >> $@ @@\ echo $(RM) '$$x' >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #endif /* HasExecableScripts */ #endif /* ScriptFromCppTemplate */ #ifndef ShScriptFromCppTemplate #define ShScriptFromCppTemplate(dst,src,defs,deps) @@\ ScriptFromCppTemplate($(SHELL),dst,src,defs,deps) #endif /* ShScriptFromCppTemplate */ /***************************************************************************** * Miscellaneous target-building rules * *****************************************************************************/ /* Generate a fake target entry that just announces a file is not built */ #ifndef FakeBuildFile #define FakeBuildFile(target) @@\ target:: @@\ @echo target" is not built here" #endif /* FakeBuildFile */ /* * LinkTarget() - Make a link to a target. Used when multiple targets use * the same file under different names. */ #ifndef LinkTarget #define LinkTarget(target,linkto) @@\ AllTarget(target) @@\ target:: linkto @@\ RemoveTarget(target) @@\ $(LN) linkto target @@\ StuffToClean(target) @@\ HelpAuxTarget(target,link target to linkto) #endif /* LinkTarget */ /* * FileFromIntermediary() - This is used when a file is created by processing * another file, but when that processing often will generate a file that's * identical to the current version (e.g., you create a header file from some * sort of template). By creating an intermediary file from the source and * comparing it to the destination, you can avoid touching the destination * if the intermediary isn't different. * * Useful to avoid triggering unnecessary builds of targets that depend on * dst. */ #ifndef FileFromIntermediary #define FileFromIntermediary(dst,inter,src) @@\ AllTarget(dst) @@\ dst:: src @@\ $(MAKE) $(MFLAGS) inter @@\ UpdateIfDifferent(dst,inter) @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build dst) #endif /* * SimpleWorldTarget() - Generate a World target that can be used to build * the entire project from scratch with "make World". The initial "all" * target is simply to prevent "World" from being the default target if * there are no earlier rule invocations in the Imakefile. * * Useful for relatively simple or straightforward projects built along * "configure-depend-build" lines. Probably insufficient for projects with * special build requirements. */ #ifndef SimpleWorldTarget #define SimpleWorldTarget(project,release) @@\ all:: @@\ World:: @@\ @echo "Building "project", Release "release @@\ @echo "" @@\ @date @@\ @echo "" @@\ $(MAKE) $(MFLAGS) Makefile @@\ $(MAKE) $(MFLAGS) Makefiles @@\ $(MAKE) $(MFLAGS) clean @@\ $(MAKE) $(MFLAGS) depend @@\ $(MAKE) $(MFLAGS) all @@\ @echo "" @@\ @date @@\ @echo "" @@\ @echo "Done building "project @@\ HelpAuxTarget(World,build the entire project distribution) #endif /* SimpleWorldTarget */ /***************************************************************************** * * * Installation rules * * * *****************************************************************************/ /* * In general, install rules generate an "install" target entry so that * "make install" installs everything (but manual pages), and also an * "i.target" entry so that "make i.target" installs only the named target. * This allows single-target installation granularity. * * Manual page install rules generate an "install.man" target entry and an * "i.target.man" entry so "make install.man" installs all manual pages and * "make i.target.man" installs the man page for the named target only. * Note that the individual page installation target alway ends in ".man" * even if name of the installed man page ends in something else like ".1" * or ".3". */ /* * InstallFile() is the general interface for file installation. * Most of the other rules call it with various flags. (Manual pages * are handled differently; see below.) * * HelpAuxTarget() is not placed at the end of the rule, because if * it were, InstallLibrary() would get messed up. (InstallLibrary() * adds lines to the i.dstfile target entry; that's an ugly thing, * but it works.) */ #ifndef InstallFile #define InstallFile(target,dstfile,srcfile,dir,flags) @@\ target:: i.dstfile @@\ HelpAuxTarget(i.dstfile,install dstfile) @@\ i.dstfile:: srcfile @@\ MakeDir(dir) @@\ $(INSTALL) flags srcfile dir/dstfile #endif /* InstallFile */ /* Install a normal program */ #ifndef InstallProgram #define InstallProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTPROGFLAGS)) #endif /* InstallProgram */ /* Install a setuid program */ #ifndef InstallUidProgram #define InstallUidProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTUIDPROGFLAGS)) #endif /* InstallUidProgram */ /* Install a setgid program */ #ifndef InstallGidProgram #define InstallGidProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTGIDPROGFLAGS)) #endif /* InstallGidProgram */ /* Install a setuid/setgid program */ #ifndef InstallUGidProgram #define InstallUGidProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTUGIDPROGFLAGS)) #endif /* InstallUGidProgram */ /* Install an executable script */ #ifndef InstallScript #define InstallScript(file,dir) @@\ InstallFile(install,file,file,dir,$(INSTSCRIPTFLAGS)) #endif /* InstallScript */ /* Install a data file (non-executable file) */ #ifndef InstallDataFile #define InstallDataFile(file,dir) @@\ InstallFile(install,file,file,dir,$(INSTDATFLAGS)) #endif /* InstallDataFile */ /* Install an include file */ #ifndef InstallIncludeFile #define InstallIncludeFile(file,dir) @@\ InstallFile(install,file,file,dir,$(INSTINCFLAGS)) #endif /* InstallIncludeFile */ /* * Install a library. This must install the library *and* rerun ranlib. * The RanLibrary() line depends on InstallFile() not adding blank lines at * end! */ #ifndef InstallLibrary #define InstallLibrary(name,dir) @@\ InstallFile(install,LibraryTargetName(name),LibraryTargetName(name),dir,$(INSTLIBFLAGS)) @@\ RanLibrary(dir/LibraryTargetName(name)) #endif /* InstallLibrary */ /* Install a lint library */ #ifndef InstallLintLibrary #define InstallLintLibrary(name,dir) @@\ InstallFile(install.lint,LintLibraryTargetName(name),LintLibraryTargetName(name),dir,$(INSTLIBFLAGS)) #endif /* InstallLintLibrary */ /* Install a link to another file installed in the given directory */ #ifndef InstallLink #define InstallLink(target,linkto,dir) @@\ install:: i.target @@\ i.target:: i.linkto @@\ MakeDir(dir) @@\ RemoveTarget(dir/target) @@\ $(LN) dir/linkto dir/target @@\ HelpAuxTarget(i.target,install dir/target as a link to dir/linkto) #endif /* InstallLink */ /* Install a set of data files */ #ifndef InstallMultipleDataFiles #define InstallMultipleDataFiles(target,files,dir) @@\ target:: @@\ MakeDir(dir) @@\ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\ for i in files ;\ @@\ do \ @@\ (set -x; $(INSTALL) $(INSTDATFLAGS) $$i dir/$$i); \ @@\ done @@\ HelpAuxTarget(target,install files) #endif /* InstallMultipleDataFiles */ /* * Manual page installation rules * * It's assumed that the manual page source file always has a .man * suffix. * * InstallManFile() is the general interface to manual page install * rules. The other installers call it with the proper arguments, and * require only the basename of the manual page. * * InstallMan1Page() - install a section 1 manual page * InstallMan2Page() - install a section 2 manual page * InstallMan3Page() - install a section 3 manual page * InstallMan4Page() - install a section 4 manual page * InstallMan5Page() - install a section 5 manual page * InstallMan6Page() - install a section 6 manual page * InstallMan7Page() - install a section 7 manual page * InstallMan8Page() - install a section 8 manual page * InstallManLPage() - install a section l manual page * InstallManNPage() - install a section n manual page * InstallManPage() - install a "default" section manual page */ #ifndef InstallManFile #define InstallManFile(target,name,dstsuffix,dir) @@\ target:: i.name.man @@\ i.name.man:: name.man @@\ MakeDir(dir) @@\ $(INSTALL) $(INSTMANFLAGS) name.man dir/name.dstsuffix @@\ HelpAuxTarget(i.name.man,install name.man manual page) #endif /* InstallManFile */ #ifndef InstallMan1Page #define InstallMan1Page(file) @@\ InstallManFile(install.man,file,$(MAN1SUFFIX),$(MAN1DIR)) #endif /* InstallMan1Page */ #ifndef InstallMan2Page #define InstallMan2Page(file) @@\ InstallManFile(install.man,file,$(MAN2SUFFIX),$(MAN2DIR)) #endif /* InstallMan2Page */ #ifndef InstallMan3Page #define InstallMan3Page(file) @@\ InstallManFile(install.man,file,$(MAN3SUFFIX),$(MAN3DIR)) #endif /* InstallMan3Page */ #ifndef InstallMan4Page #define InstallMan4Page(file) @@\ InstallManFile(install.man,file,$(MAN4SUFFIX),$(MAN4DIR)) #endif /* InstallMan4Page */ #ifndef InstallMan5Page #define InstallMan5Page(file) @@\ InstallManFile(install.man,file,$(MAN5SUFFIX),$(MAN5DIR)) #endif /* InstallMan5Page */ #ifndef InstallMan6Page #define InstallMan6Page(file) @@\ InstallManFile(install.man,file,$(MAN6SUFFIX),$(MAN6DIR)) #endif /* InstallMan6Page */ #ifndef InstallMan7Page #define InstallMan7Page(file) @@\ InstallManFile(install.man,file,$(MAN7SUFFIX),$(MAN7DIR)) #endif /* InstallMan7Page */ #ifndef InstallMan8Page #define InstallMan8Page(file) @@\ InstallManFile(install.man,file,$(MAN8SUFFIX),$(MAN8DIR)) #endif /* InstallMan8Page */ #ifndef InstallManLPage #define InstallManLPage(file) @@\ InstallManFile(install.man,file,$(MANLSUFFIX),$(MANLDIR)) #endif /* InstallManLPage */ #ifndef InstallManNPage #define InstallManNPage(file) @@\ InstallManFile(install.man,file,$(MANNSUFFIX),$(MANNDIR)) #endif /* InstallManNPage */ #ifndef InstallManPage #define InstallManPage(file) @@\ InstallManFile(install.man,file,$(MANSUFFIX),$(MANDIR)) #endif /* InstallManPage */ /* * "Fake" install rules for targets that are built but not installed anywhere. * These may be used to indicate a file is explicitly not installed (as * opposed to your appearing to have forgotten to invoke an installation rule * in the Imakefile). */ #ifndef FakeInstallFile #define FakeInstallFile(file) @@\ install:: i.file @@\ i.file:: @@\ @echo file is not installed anywhere. #endif /* FakeInstallFile */ #ifndef FakeInstallLibrary #define FakeInstallLibrary(name) @@\ install:: i.LibraryTargetName(name) @@\ i.LibraryTargetName(name):: @@\ @echo LibraryTargetName(name) is not installed anywhere. #endif /* FakeInstallLibrary */ /***************************************************************************** * * * Rules that generate recursive target entries * * * *****************************************************************************/ /* * NamedTargetSubdirs() - recursively run the named operation in a set of * directories. */ #ifndef NamedTargetSubdirs #define NamedTargetSubdirs(op,dirs,verb,flags) @@\ op:: @@\ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\ for i in dirs ;\ @@\ do \ @@\ ($(CHDIR) $$i ; echo verb "in $(CURRENT_DIR)/$$i..."; \ @@\ $(MAKE) $(MFLAGS) flags op); \ @@\ done #endif /* NamedTargetSubdirs */ /* * MakeSubdirs() - generate recursive "all" target entry. If you want * CDEBUGFLAGS passed along to subdirectories, provide a line like the * following in the appropriate Imakefile: * * #define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' */ #ifndef MakeSubdirs #define MakeSubdirs(dirs) \ NamedTargetSubdirs(all,dirs,"making" all,PassCDebugFlags) #endif /* MakeSubdirs */ /* * DependSubdirs() - generate recursive "depend" target entry. */ #ifndef DependSubdirs #define DependSubdirs(dirs) \ NamedTargetSubdirs(depend,dirs,"depending",NullArg) #endif /* DependSubdirs */ /* * InstallSubdirs() - generate recursive "install" target entry to install * programs and files. */ #ifndef InstallSubdirs #define InstallSubdirs(dirs) \ NamedTargetSubdirs(install,dirs,"installing",NullArg) #endif /* InstallSubdirs */ /* * InstallManSubdirs() - generate recursive "install.man" target entry * to install manual pages. */ #ifndef InstallManSubdirs #define InstallManSubdirs(dirs) \ NamedTargetSubdirs(install.man,dirs,"installing man pages",NullArg) #endif /* InstallManSubdirs */ /* * CleanSubdirs() - generate recursive "clean" target entry. */ #ifndef CleanSubdirs #define CleanSubdirs(dirs) \ NamedTargetSubdirs(clean,dirs,"cleaning",RM_CMD='$(RM_CMD)') #endif /* CleanSubdirs */ /* * TagSubdirs() - generate recursive "tags" target entry. */ #ifndef TagSubdirs #define TagSubdirs(dirs) \ NamedTargetSubdirs(tags,dirs,"tagging",TAGS='$(TAGS)') #endif /* TagSubdirs */ /***************************************************************************** * * * Makefile-generating rules * * * *****************************************************************************/ /* * MakefileTarget() - generate target entry to build Makefile from * Imakefile by invoking imboot. */ #ifndef MakefileTarget #define MakefileTarget() @@\ Makefile:: @@\ $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) #endif /* MakefileTarget */ /* * MakefileSubdirs() - generate target entry to recursively recreate * Makefiles. * * Logic: * * - Turn on error ignoring if -i or -k found in make argument list * - Loop through each child directory named in argument * - Figure out value of TOP in child. If TOP is an absolute path, it's * the same in the child. If TOP is relative, prepend path from child * to parent onto it. * - Change into child, build the Makefile there using imboot, then * run "make Makefiles" in case child has its own subdirectories */ #ifndef MakefileSubdirs #define MakefileSubdirs(dirs) @@\ Makefiles:: @@\ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\ for i in dirs ;\ @@\ do \ @@\ echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \ @@\ case "$$i" in \ @@\ ./?*/?*/?*/?*) parent=../../../../;; \ @@\ ./?*/?*/?*) parent=../../../;; \ @@\ ./?*/?*) parent=../../;; \ @@\ ./?*) parent=../;; \ @@\ */?*/?*/?*) parent=../../../../;; \ @@\ */?*/?*) parent=../../../;; \ @@\ */?*) parent=../../;; \ @@\ *) parent=../;; \ @@\ esac; \ @@\ case "$(TOP)" in \ @@\ /?*) topadj= ;; \ @@\ *) topadj=$$parent ;; \ @@\ esac; \ @@\ ($(CHDIR) $$i ; \ @@\ $(IMBOOT_CMD) $$topadj$(TOP) $(CURRENT_DIR)/$$i ; \ @@\ $(MAKE) $(MFLAGS) Makefiles ) ; \ @@\ done #endif /* MakefileSubdirs */ /***************************************************************************** * * * Document-formatting rules (troff-based) * * * *****************************************************************************/ /* * Rules for generating PostScript from troff documents. * * TroffToPostScript() is the base rule; the others call it with * appropriate arguments for the various macro packages. * * Arguments: * dst output file (this is also the main target) * src source file(s) * flags flags for troff * filters preprocessors * deps dependencies * * There is always some processs in front of troff (either soelim or cat) * so that filters can be inserted in between as appropriate. filters can * be empty, or something like "|$(TBL)|$(EQN)" (without quotes). (If * non-empty, filters MUST begin with a "|".) * * TroffMsToPostScript() - Format a document that uses the -ms macros * TroffMeToPostScript() - Format a document that uses the -me macros * TroffMmToPostScript() - Format a document that uses the -mm macros * TroffManToPostScript() - Format a document that uses the -man macros * TroffMdocToPostScript() - Format a document that uses the -mdoc macros * * TROFFOPTS is for command line use. You can set it, e.g., to format * only certain pages. */ #ifndef TroffToPostScript #define TroffToPostScript(dst,src,flags,filters,deps) @@\ dst:: src deps @@\ $(SOELIM) src filters | $(TROFF) flags $(TROFFOPTS) > dst @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,format dst in PostScript) #endif /* TroffToPostScript */ #ifndef TroffMsToPostScript #define TroffMsToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(MSMACROS),filters,deps) #endif /* TroffMsToPostScript */ #ifndef TroffMeToPostScript #define TroffMeToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(MEMACROS),filters,deps) #endif /* TroffMeToPostScript */ #ifndef TroffMmToPostScript #define TroffMmToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(MMMACROS),filters,deps) #endif /* TroffMmToPostScript */ #ifndef TroffManToPostScript #define TroffManToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(MANMACROS),filters,deps) #endif /* TroffManToPostScript */ #ifndef TroffMdocToPostScript #define TroffMdocToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(MDOCMACROS),filters,deps) #endif /* TroffMdocToPostScript */ /* * Rules for generating RTF from troff documents. These are similar * to the PostScript rules, except that the macro-specific rules have * a flags argument. This is needed because there may be flags that * are needed in addition to the input files. */ #ifndef TroffToRTF #define TroffToRTF(dst,src,flags,filters,deps) @@\ dst:: src deps @@\ $(SOELIM) src filters | $(TROFF2RTF) flags $(TROFFOPTS)> dst @@\ StuffToClean(dst) #endif /* TroffToRTF */ #ifndef TroffMsToRTF #define TroffMsToRTF(dst,src,flags,filters,deps) @@\ TroffToRTF(dst,src,$(TCMSMACROS) flags,filters,deps) #endif /* TroffMsToRTF */ #ifndef TroffMeToRTF #define TroffMeToRTF(dst,src,flags,filters,deps) @@\ TroffToRTF(dst,src,$(TCMEMACROS) flags,filters,deps) #endif /* TroffMeToRTF */ #ifndef TroffMmToRTF #define TroffMmToRTF(dst,src,flags,filters,deps) @@\ TroffToRTF(dst,src,$(TCMMMACROS) flags,filters,deps) #endif /* TroffMmToRTF */ #ifndef TroffManToRTF #define TroffManToRTF(dst,src,flags,filters,deps) @@\ TroffToRTF(dst,src,$(TCMANMACROS) flags,filters,deps) #endif /* TroffManToRTF */ #ifndef TroffMdocToRTF #define TroffMdocToRTF(dst,src,flags,filters,deps) @@\ TroffToRTF(dst,src,$(TCMDOCMACROS) flags,filters,deps) #endif /* TroffMdocToRTF */ /* * Rules for generating HTML from troff documents. These are similar * to the PostScript rules, except that the macro-specific rules have * a flags argument. This is needed because there may be flags that * are needed in addition to the input files. */ #ifndef TroffToHTML #define TroffToHTML(dst,src,flags,filters,deps) @@\ dst:: deps @@\ $(SOELIM) src filters | $(TROFF2HTML) flags $(TROFFOPTS) - >dst @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,format dst in HTML) #endif /* TroffToHTML */ #ifndef TroffManToHTML #define TroffManToHTML(dst,src,flags,filters,deps) @@\ TroffToHTML(dst,src,$(TCMANMACROS) flags,filters,deps) #endif /* TroffManToHTML */ #ifndef TroffMsToHTML #define TroffMsToHTML(dst,src,flags,filters,deps) @@\ TroffToHTML(dst,src,-ms flags,filters,deps) #endif /* TroffMsToHTML */ #ifndef TroffMeToHTML #define TroffMeToHTML(dst,src,flags,filters,deps) @@\ TroffToHTML(dst,src,$(TCMEMACROS) flags,filters,deps) #endif /* TroffMeToHTML */ #ifndef TroffMmToHTML #define TroffMmToHTML(dst,src,flags,filters,deps) @@\ TroffToHTML(dst,src,$(TCMMMACROS) flags,filters,deps) #endif /* TroffMmToHTML */ #ifndef TroffMdocToHTML #define TroffMdocToHTML(dst,src,flags,filters,deps) @@\ TroffToHTML(dst,src,$(TCMDOCMACROS) flags,filters,deps) #endif /* TroffMdocToHTML */ /* * Rules for generating plain text from troff documents. These are similar * to the PostScript rules, except that the macro-specific rules have * a flags argument. This is needed because there may be flags that * are needed in addition to the input files. */ #ifndef TroffToText #define TroffToText(dst,src,flags,filters,deps) @@\ dst:: deps @@\ $(SOELIM) src filters | $(UNROFF) flags $(TROFFOPTS) - > dst @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,format dst in plain text) #endif /* TroffToText */ #ifndef TroffManToText #define TroffManToText(dst,src,flags,filters,deps) @@\ TroffToText(dst,src,$(TCMANMACROS) flags,filters,deps) #endif /* TroffManToText */ #ifndef TroffMsToText #define TroffMsToText(dst,src,flags,filters,deps) @@\ TroffToText(dst,src,-ms flags,filters,deps) #endif /* TroffMsToText */ #ifndef TroffMeToText #define TroffMeToText(dst,src,flags,filters,deps) @@\ TroffToText(dst,src,$(TCMEMACROS) flags,filters,deps) #endif /* TroffMeToText */ #ifndef TroffMmToText #define TroffMmToText(dst,src,flags,filters,deps) @@\ TroffToText(dst,src,$(TCMMMACROS) flags,filters,deps) #endif /* TroffMmToText */ #ifndef TroffMdocToText #define TroffMdocToText(dst,src,flags,filters,deps) @@\ TroffToText(dst,src,$(TCMDOCMACROS) flags,filters,deps) #endif /* TroffMdocToText */ /***************************************************************************** * * * Odds and ends * * * *****************************************************************************/ /* * RemoveTarget() - generate a command to remove the target. * * This rule is used tab-indented as a command line in other rules. */ #ifndef RemoveTarget #define RemoveTarget(target) $(RM) target #endif /* RemoveTarget */ /* * RanLibrary() - run ranlib if it's present on the given machine, otherwise * do nothing. * * This rule is used tab-indented as a command line in other rules. */ #ifndef RanLibrary #if HasRanlibCmd #define RanLibrary(args) $(RANLIB) args #else #define RanLibrary(args) /**/ #endif #endif /* RanLibrary */ /* * StuffToClean() - generate a clean target entry to remove the files named * in the argument. Invoked by other rules to make sure that targets built * get removed by "make clean", but can also be used in Imakefiles to * explicitly name targets that should be cleaned. */ #ifndef StuffToClean #define StuffToClean(stuff) @@\ clean:: @@\ RemoveTarget (stuff) #endif /* StuffToClean */ /* * UpdateIfDifferent() - update dst with src if they're different. Otherwise * leave alone. */ #ifndef UpdateIfDifferent #define UpdateIfDifferent(dst,src) -@$(CMP) -s dst src; \ @@\ if [ $$? -ne 0 ]; then \ @@\ echo "$(MV) "src dst; \ @@\ $(MV) src dst; \ @@\ echo dst" updated"; \ @@\ else \ @@\ echo dst" not updated." ; \ @@\ fi #endif /* UpdateIfDifferent */ /* * AllTarget() - generate an all target entry to built the file named * in the argument. Invoked by other rules to make sure that targets get * built by "make all", but can also be used in Imakefiles to explicitly * name targets that should be built. */ #ifndef AllTarget #define AllTarget(target) @@\ all:: target #endif /* AllTarget */ /* * LintSources() - run the source files for a given program through lint. * Usually invoked by program-building rules to generate lint targets. * * Arguments: * target target (program or library) the source files belong to * srcs target's source files * * Targets produced: * lint lint these source files (and all others in Makefile) * lint.target lint target's source files only */ #ifndef LintSources #define LintSources(target,srcs) @@\ lint:: lint.target @@\ lint.target: @@\ $(LINT) $(LINTFLAGS) srcs $(LINTLIBS) @@\ HelpAuxTarget(lint.target,lint sources for target) #endif /* LintSources */ /* * DependTarget() - generate depend entry to compute dependencies for all * files listed in $(SRCS). This means that in the Imakefile, SRCS should * be assigned a value naming all the *.c files to be processed. */ #ifndef DependTarget #define DependTarget() @@\ depend:: @@\ $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) #endif /* DependTarget */ /* * CleanTarget() - generate target entry to remove any garbage files; the #* * is here instead of in the definition of RM_CMD because System V will treat * the pound sign in the RM_CMD variable as a comment. */ #ifndef CleanTarget #define CleanTarget() @@\ clean:: @@\ $(RM_CMD) "#"* #endif /* CleanTarget */ /* * TagsTarget() - generate target entry to compute tags files for C source * code. */ #ifndef TagsTarget #define TagsTarget() @@\ tags:: @@\ $(TAGS) -w *.[ch] @@\ $(TAGS) -xw *.[ch] > TAGS #endif /* TagsTarget */ /* * FiFiiSuffixRule() - provide suffix rule necessary to run figen to * produce a .fii file from a .fi file. */ #ifndef FiFiiSuffixRule #define FiFiiSuffixRule() @@\ .SUFFIXES: .fi .fii @@\ .fi.fii: @@\ $(FIGEN) $*.fi #endif /* FiFiiSuffixRule */ /* * Generate a help_aux target for the default help target. This is for * "make help" and can be placed inside target-building rules to print * for the user the command that builds a particular target. target is * the target name and description is a description of what "make target" * builds. */ #ifndef HelpAuxTarget #define HelpAuxTarget(target,description) @@\ help_aux:: @@\ @echo "'make "target"' to "description #endif /* HelpAuxTarget */ e processs in front of troff (either soelim or cat) * so that filters can be inserted in between as appropriate. filters can * be empty, or somethiWRPRC-2.11/config/README010066400017710000151000000410010634140471700162050ustar00junkyarddatamgmt00000400000027WRPRC2 Configuration Files Release 2.09 13 December 1996 This document accompanies the WRPRC2 imake configuration files, and describes the various parameters provided by them. It should be read by anyone who is porting the files to a new platform or attempting to change the defaults. Parts of this document are derived from the mit/config/README file in the X11R4 distribution. The WRPRC2 configuration files are used with imake, and assume that imake, makedepend, imboot, mkdirhier, and msub are installed. If you need those programs, see the README file in the top-level directory of the WRPRC2 distribution. 1. Introduction Because Makefiles are inherently unportable, a tool called imake generates platform-specific Makefiles from machine-independent descriptions called Imakefiles. It makes very heavy use of the C preprocessor both for constants and macro functions. imake can be somewhat tricky to master; however, it is invaluable for making projects easy to configure on different systems. Imakefiles usually contain definitions of make variables plus one or more invocations of macro functions to build the desired parts of the Makefile. imake reads a template file containing definitions that are common to all Makefiles, which includes machine, project, and site-specific files containing definitions for the various commonly used commands and flags for enabling certain build options. It then includes a rules file in which all of the various macro functions are defined, followed by the Imakefile being processed. Finally, it appends a set of common rules to the bottom. 2. The configuration files In the config directory, there is a set of configuration files, which may be divided into two categories: - Baseline configuration files which define the most probable defaults for parameter values. - Override files, which specify project-specific configuration information. The baseline configuration files are: Imake.tmpl Template defining the order in which other files are processed Imake.cf Vendor block selection Imake.params General system and project parameters Imake.rules Rules for generating Makefile target entries vendor.cf Vendor-specific parameters site.def Site-specific parameters The override files have names and functions similar to those of the baseline files. They are intended to be used by individual projects for which it's necessary to override or extend the configuration information provided by the baseline files: Imake.p-cf Imake.p-params Imake.p-rules vendor.p-cf site.p-def The baseline files and a set of dummy (i.e., empty) override files are installed into the directory under ConfigRootDir named by ConfigName (by default, WRPRC2). Should a project wish to override configuration parameters or define new ones, it may do so by providing project-specific override files in a config directory under the project top-level directory. imake searches for configuration files in such a way that project-specific override files are found before and take precedence over the dummy override files in the public configuration file directory. Before you install the configuration files, look over your vendor file and make sure it's correct for your system. You may also want to modify site.def to provide site-specific values of parameters to override the defaults. To see what values the parameters will have, build the Makefile in the config directory, then type: % make test | more 3. The template file Imake.tmpl Imake.tmpl defines the order in which the other files are processed. The top of the file defines some useful constants and then includes a file Imake.cf that contains a series of conditional "vendor blocks" for setting the platform type. This requires that there be a unique preprocessor symbol that can be used to identify which configuration block to use. It's assumed that your imake defines the proper symbol for your system as necessary. If it doesn't, you'll need to rebuild imake so it does. Each conditional block in Imake.cf defines several symbol names representing the type of system being configured: #define VendorIncludeFile #define VendorFile PLATFORM.cf #define ProjectVendorIncludeFile #define ProjectVendorFile PLATFORM.p-cf #define PLATFORMArchitecture where PLATFORM is the type of the system being configured. The redundant versions are needed because one is used by cpp to include the file and the other is used in generating filenames. The Architecture symbol may be used in Imakefiles to obtain vendor-specific rules or values. The unique symbols that were used to select the configuration block are then undefined to prevent Imakefiles from using system-dependent rules as opposed to platform-dependent (some platforms run on multiple systems). Under certain conditions, more than one Architecture symbol will be defined. For instance, if a vendor's OS has releases which run under different chipsets and it's necessary to be able to distinguish between them, hardware and software architecture symbols can both be defined. The template file should not be edited. Platform-specific changes can be made in the appropriate *.cf files and site-specific changes can be made in site.def. Project-specific changes can be made in Imake.p-params, the *.p-cf files, and site.p-def under the project's private config directory. Any parameter that is not set will be given a default value in Imake.params. 4. The parameters file Imake.params All of the common system and project description parameters are located in the file Imake.params. Boolean symbols should be defined as YES or NO. Imake.params provides defaults for the following variables, presented below by functional groups: General system characteristics: HasExecableScripts boolean for systems that can exec() #!/bin/sh HasGcc boolean for whether or not to use gcc HasGcc2 boolean for whether or not to use gcc 2.x HasRanlibCmd boolean for presence of ranlib program HasSoelim boolean for nroff/troff .so eliminator program HasSymLinks boolean for symbolic links HasStdarg boolean for presence of HasUnistdH boolean for presence of HasVarargs boolean for presence of HasVFork boolean for presence of vfork() system call HasVoidSignalReturn boolean for POSIX signal() procs OSMajorVersion major version number of operating system OSMinorVersion minor version number of operating system OSTeenyVersion teeny version number of operating system SystemV boolean for systems that are at least SVR2 SystemV4 boolean for SVR4 systems Configuration directory and program information: DependCmd command to run makedepend ImbootCmd command to run imboot MkdirHierCmd command to create directories MsubCmd command to run msub Configuration and project identification information: ConfigMajorRelease major release level of the group ConfigMinorRelease minor release level of the group ConfigName name of this group of configuration files ConfigRelease release level of the group ConfigRootDir path to root of public config file dirs ProjectMajorRelease major release level of the project ProjectMinorRelease minor release level of the project ProjectName name of the project ProjectRelease release level of the project Directory and filename information: AdmDir directory for administrative files BinDir directory for user programs CURDIR current directory relative to top of sources EtcDir directory for system maint. programs, servers IncludeRoot top of system include file hierarchy LintLibDir directory for lint libraries LocalAdmDir local directory for administrative program LocalBinDir local directory for user programs LocalEtcDir local directory for system maint. programs LocalIncludeRoot top of local include file hierarchy LocalLintLibDir local directory for lint libraries LocalRootDir root of local directory hierarchy LocalUsrLibDir local directory for library files ManDir directory in which to install program man pages ManRoot top of system manpage hierarchy ManSourcePath common prefix of man page directories ManSuffix man suffix for programs TOPDIR relative path to top of sources TmpDir directory for temporary files UsrLibDir directory for system library files Names of commands used during project build and install processes: ArCmd command used to create libraries AsCmd command used to run assembler AwkCmd command to run awk BourneShell command used to run Bourne Shell CatCmd command to run cat CcCmd command to run C compiler ChdirCmd command to change directories ChmodCmd command to run chmod CmpCmd command to run cmp CommCmd command to run comm CpCmd command to copy one file to another CppCmd command to run C preprocessor InstallCmd command to install files LdCmd command to run loader LintCmd command to run lint LnCmd command to link two files MakeCmd command to run make MvCmd command to rename a file PerlCmd command to run perl PerlPath pathname of perl Perl5Cmd command to run perl 5 Perl5Path pathname of perl 5 RanlibCmd command to clean up libraries RmCmd command to delete files SedCmd command to run sed SortCmd command to run sort TagsCmd command to run tags UniqCmd command to run uniq Local programs: DistarCmd distributed-archive interface FigenCmd form-info generator Flags to commands used during the build/install process: DefaultCCOptions default special C compiler options DefaultCDebugFlags default C compiler flags for debugging FilesToClean files to delete in make clean InstCopy install flags to copy without removing original InstDatFlags install flags for non-executables InstDatMode install mode for non-executables InstGidProgFlags install flags for setgid programs InstGidProgMode install mode for setgid programs InstGroup install flags to set group InstIncFlags install flags for include files InstIncMode install mode for include files InstLibFlags install flags for libraries InstLibMode install mode for libraries InstManFlags install flags for man pages InstManMode install mode for man pages InstOwner install flags to set owner InstProgFlags install flags for programs InstProgMode install mode for programs InstScriptFlags install flags for executable scripts InstScriptMode install mode for executable scripts InstStrip install flags to strip installed programs InstUGidProgFlags install flags for setuid/setgid programs InstUGidProgMode install mode for setuid/setgid programs InstUidProgFlags install flags for setuid programs InstUidProgMode install mode for setuid programs LintLibFlag flags to generate lint libraries LintLibs libraries needed to run lint LintOpts lint options to control strictness LoaderLibPrefix loader flags before library pathnames ProjectDefines any special project defines ProjectIncludes any special project include directories ProjectLoadFlags any special project loader flags ProjectLoadLibs any special project libraries needed to link RanlibInstFlags flags to ranlib after copying StandardCppDefines -D's for running cpp StandardDefines -D's for running C compiler StandardIncludes -I's for running C compiler StandardLoadFlags system-specific loader flags StandardLoadLibs system-specific libraries needed to link Document preparation command names and flags: EqnCmd equation layout program ManMacros macros for formatting manual pages MeMacros macros for formatting other documents MmMacros macros for formatting other documents MsMacros macros for formatting other documents NeqnCmd nroff version of eqn NroffCmd non-typesetter formatting program PicCmd picture layout program SoelimCmd .so-request eliminator TblCmd table layout program TroffCmd typesetter formatting program Miscellaneous: ConstructMFLAGS System V option to set MFLAGS make variable Library specifiers: There are many of these, two forms for each. Typically, for a library xxx, XxxLib is the link library specifier, and DepXxxLib is the dependency specifier. 5. Vendor-specific *.cf files The template files contain defaults for all platforms which can be overridden by including an appropriate definition in the .cf file. Differences between operating systems are handled by setting various configuration parameters in the vendor-specific *.cf files. The easiest way to create a new vendor file is to: o Find a configuration similar to yours or start with generic.cf. o Set the SystemV variable if your OS is based on SVR2 or SVR3. o Set the SystemV4 variable if your OS is based on SVR4. o Set the OSMajorVersion and OSMinorVersion variables. o read Imake.params to see if there is anything you'd like to override. o look at the other *.cf files to see if there are any variables you'd like to set; common ones include Has* symbols and *Cmd symbols. EVEN IF THERE IS ALREADY A VENDOR FILE FOR YOUR PLATFORM, BE SURE TO READ IT! It may contain other information you need to know before a build will proceed properly. It doesn't hurt to read several different vendor files to get a feel for how they work. If you add support for a particular vendor, please send your changes to dubois@primate.wisc.edu. 6. Site-specific site.def file The site.def file is used to set configuration parameters that apply to a given site. Use the #ifndef/#endif construction so that values you define may still be overridden in the vendor-specific files. Some important things that can be done in site.def are: Override values of parameters that specify system and local directories layout, such as TmpDir, IncludeRoot, LocalIncludeRoot, etc. Values of the LocalXXXDir parameters default to be the same as the corresponding XXXDir parameters. Change them if you want. Pay particular attention to the LocalXXXDir parameters, since install rule invocations in projects configured with the WRPRC2 files will often refer to one of these directories as the installation destination. Select document preparation preferences. The WRPRC2 defaults are surely wrong for many sites and should be changed. We use xroff, pstroff, and groff, all of which have been the default at different times. The soelim command is used in document formatting rules if you have it (i.e., if HasSoelim is YES). This is useful when running files through tbl, eqn, etc., since otherwise tables and equations in .so files don't get processed. An additional reason for using soelim at WRPRC is that our troff's are accessed through a mechanism that chooses the least loaded machine and runs the job there over the network; in this environment, .so files fail if troff isn't running on the local machine. 7. Imakefiles The easiest way to write an Imakefile is to find another one that does something similar and modify it. Look in the examples directory for sample Imakefiles. Individual Imakefiles may use any of the macros defined in Imake.rules. Many of these rules use auxiliary make variables that may be defined in your Imakefile for directory-specific purposes: SUBDIRS used by numerous directory-traversing rules SRCS used by DependTarget DEFINES extra flags used to compile C programs INCLUDES extra include directories used to compile C programs Conventions Rules that generate an entry to build a target "prog" usually also generate "all" and "clean" targets. Install rules for a program generate "install" and "i.prog" targets. Manual page install rules generate "install.man" and "i.prog.man" targets. This strategy allows "make all" and "make install" to build and install all programs in a directory in one fell swoop, yet also allows "make prog" and "make i.prog" to make or install a single program. "make install.man" installs all manual pages, and "make i.prog.man" installs a page for a single program. If there are files which should be removed by the "make clean" operation, specify them in the StuffToClean() rule. 8. Some differences between X11 and WRPRC configuration files Much of the WRPRC2 distribution was derived originally from the X11 configuration files, although there are now many differences. Some things that have been retained but in a slightly different form are listed below. If you are used to the X11 form of these, note the differences. X11's RemoveTargetProgram() rule is here known as RemoveTarget(). (The rule is more generally-useful than just for programs, so I renamed it.) The X11 Symbol ExecableScripts is HasExecableScripts in this project. X11 LibmanDir is WRPRC LibManDir. X11 LintlibDir is WRPRC LintLibDir. X11 NamedSubdirsTarget() has one more argument than WRPRC NamedSubdirsTarget(). X11 CleanTarget() removes *~ files. WRPRC CleanTarget() doesn't. ectory and program information: DependCmd command to run makedepend ImbootCmd command to run imboot MkdirHierCmd command to create directories MsubCmd command to run msub Configuration and project identification information: ConfigMajorRelease major release level of the group ConfigMinorRelease minor release level of the group ConfigName name of this group of configuration files ConfigRelease release level of the group ConfigRootDir path to root of public config file dirs ProjectMajorRWRPRC-2.11/config/hp.cf.orig010066400017710000151000000022210634140471700172060ustar00junkyarddatamgmt00000400000027/* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES * * Also, you'll need to install bsdinst before doing a "make install". * (Or, you may prefer install.sh to bsdinst.) */ #ifndef OSName #define OSName HP-UX 7.0 #endif #ifndef OSMajorVersion #define OSMajorVersion 7 #endif #ifndef OSMinorVersion #define OSMinorVersion 0 #endif XCOMM platform: hp.cf 93/06/30 XCOMM operating system: OSName #ifndef SystemV #define SystemV YES #endif #ifndef HasExecableScripts #define HasExecableScripts YES #endif #ifndef HasVFork #define HasVFork YES #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES #endif #ifndef StandardDefines #ifdef hp9000s800 #define StandardDefines -DSYSV #else #define StandardDefines -Wc,-Nd4000,-Ns3300,-Ne700,-Np200,-Nw300 -DSYSV #endif #endif #ifndef LintOpts #ifdef hp9000s800 #define LintOpts -ax -DSYSV #else #define LintOpts -ax -Nd4000 -Ns3300 -Ne700 -Np200 -Na25000 -DSYSV #endif #endif #ifndef OptimizedCDebugFlags #ifdef hp9000s800 #define OptimizedCDebugFlags +O1 #endif #endif #ifndef MvCmd #define MvCmd mv -f #endif WRPRC-2.11/config/bug.rpt010066400017710000151000000002030634140471700166300ustar00junkyarddatamgmt00000400000027 VERSION: R4 CLIENT MACHINE and OPERATING SYSTEM: DISPLAY TYPE: WINDOW MANAGER: AREA: SYNOPSIS: DESCRIPTION: REPEAT BY: WRPRC-2.11/config/sun.cf010066400017710000151000000073530634140471700164600ustar00junkyarddatamgmt00000400000027/* * This file works for SunOS 5.x/Solaris 2.x (SVR4-based) or for * SunOS 4.x/Solaris 1.x (BSD-based) systems. * * First, get the OS version numbers defined, then set the rest * of the symbols. Many of them are the same no matter what the * OS version. */ /* * SET OS VERSION NUMBERS BEFORE MAKING MAKEFILES */ #ifdef SVR4 /* SunOS 5.x or later */ #ifndef OSName #define OSName SunOS 5.5.0 #endif #ifndef OSMajorVersion #define OSMajorVersion 5 #endif #ifndef OSMinorVersion #define OSMinorVersion 5 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 0 #endif #ifndef SystemV4 #define SystemV4 YES #endif #ifndef InstallCmd #define InstallCmd /usr/ucb/install /* BSD-compatible version */ #endif #else /* pre-SunOS 5.x */ #ifndef OSName #define OSName SunOS 4.1.1 #endif #ifndef OSMajorVersion #define OSMajorVersion 4 #endif #ifndef OSMinorVersion #define OSMinorVersion 1 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 1 #endif #endif /* SVR4 */ XCOMM platform: sun.cf 96/06/21 XCOMM operating system: OSName #ifndef HasExecableScripts #define HasExecableScripts YES #endif #ifndef HasStdarg #if OSMajorVersion >= 5 #define HasStdarg YES #endif #endif #ifndef HasVarargs #define HasVarargs YES #endif #ifndef HasUnistdH #if OSMajorVersion >= 4 #define HasUnistdH YES #endif #endif #ifndef HasVoidSignalReturn #if OSMajorVersion <= 3 #define HasVoidSignalReturn NO #else #define HasVoidSignalReturn YES #endif #endif #ifndef SpoolRootDir #define SpoolRootDir /var/spool #endif /* * Compiler setup. This sun.cf file knows what options to use with * certain compilers, including Sun C and gcc. * * === C Compiler Setup ========================================== * * For SunPro C, define HasSunC to YES in site.def. * For gcc or gcc2, define HasGcc or HasGcc2 to YES in site.def * For other compilers, define HasSunC to NO in site.def, then * provide appropriate values for the various compiler related * configuration varibles used here. * * If you say you have the SunPro C compiler, we assume you have * version 4.0.x of the compiler. If you have a different version, * define CCompilerMajorVersion appropriately in site.def * * If you don't tell us which C compiler you have, we assume you have * the SunPro C compiler under Solaris 2.x, and the bundled /bin/cc * under SunOS 4.1.x */ #ifndef HasSunC #if (HasGcc || HasGcc2 || OSMajorVersion < 5) #define HasSunC NO #else #define HasSunC YES #endif #endif #if HasSunC #ifndef CCompilerMajorVersion #define CCompilerMajorVersion 4 #endif #endif #ifndef StandardDefines #if OSMajorVersion > 4 #ifdef i386Architecture #define StandardDefines -Dsun -DSVR4 -Di386 -D__i386 #else #define StandardDefines -Dsun -DSVR4 #endif #endif #endif #ifndef ExtraLibraries #if OSMajorVersion > 4 #define ExtraLibraries -lsocket -lnsl #endif #endif #ifndef HasVFork #if OSMajorVersion > 4 #define HasVFork NO #endif #endif #ifndef ExtraLoadFlags #if HasGcc2 #define ExtraLoadFlags -B/usr/bin/ #endif #endif #ifndef DefaultCCOptions #if HasGcc #if OSMajorVersion > 4 && defined(i386Architecture) #if OSMinorVersion == 1 #define DefaultCCOptions -DNO_ASM #else #define DefaultCCOptions -ansi -DNO_ASM #endif #endif #else /* Set up compiler-dependent options for Sun C */ #if HasSunC #ifdef Sun3Architecture #define DefaultCCOptions -f68881 -pipe #else /* not defined(Sun3Architecture) */ #if OSMajorVersion < 5 #define DefaultCCOptions -pipe #else /* * use -Xc so that __STDC__ will be defined as 1 (-Xt and -Xa define it, * but as 0, so that "#if __STDC__" tests fail even though the compiler * understands ANSI stuff */ #define DefaultCCOptions -Xc #endif /* OSMajorVersion < 5 */ #endif /* Sun3Architecture */ #endif /* HasSunC */ #endif /* HasGcc */ #endif /* DefaultCCOptions */ WRPRC-2.11/config/generic.p-cf010066400017710000151000000000000634140471700175020ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/ultrix.p-cf010066400017710000151000000000000634140471700174150ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/ibm.p-cf010066400017710000151000000000000634140471700166350ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/ibm.cf010066400017710000151000000047270634140471700164240ustar00junkyarddatamgmt00000400000027/* * Based on work for AIX by Shaul Wallach . * * Modified by Paul DuBois: * - Removed X11 stuff * - Removed AOS stuff * - Removed PCC stuff */ #ifdef RsArchitecture #ifndef OSName #define OSName AIX 3.2 #endif #ifndef OSMajorVersion #define OSMajorVersion 3 #endif #ifndef OSMinorVersion #define OSMinorVersion 2 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 0 #endif #else #ifdef RtArchitecture #ifdef AIXArchitecture #ifndef OSName #define OSName AIX 2.2 #endif #ifndef OSMajorVersion #define OSMajorVersion 2 #endif #ifndef OSMinorVersion #define OSMinorVersion 2 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 0 #endif #endif #else #ifndef OSName #define OSName AIX 1.2.1 #endif #ifndef OSMajorVersion #define OSMajorVersion 1 #endif #ifndef OSMinorVersion #define OSMinorVersion 2 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 1 #endif #endif #endif XCOMM operating system: OSName #ifdef RsArchitecture #ifndef BootstrapCFlags #define BootstrapCFlags -D_IBMR2 #endif #ifndef SystemV #define SystemV YES #endif #ifndef LnCmd #define LnCmd ln -s #endif #ifndef HasExecableScripts #define HasExecableScripts YES #endif #ifndef CppCmd #define CppCmd /usr/lpp/X11/Xamples/util/cpp/cpp #endif #ifndef InstallCmd #define InstallCmd /usr/ucb/install #endif #ifndef PerlPath #define PerlPath /usr/local/bin/perl #endif #ifndef Perl5Path #define Perl5Path /usr/local/bin/perl5 #endif #if OSMajorVersion > 3 #ifndef StandardDefines #define StandardDefines -DSYSV -DAIXV3 -DAIXV4 -D_ALL_SOURCE #endif /* AIX 4 appends all MAKEFLAGS (even dups), so cannot pass on command line. */ #ifndef ConstructMFLAGS #define ConstructMFLAGS NO #endif #else /* OSMajorVersion < 4 */ #ifndef StandardDefines #define StandardDefines -DSYSV -DAIXV3 -D_ALL_SOURCE #endif #endif /* OSMajorVersion */ #else /* !RsArchitecture */ #ifndef UnixCpp #define UnixCpp /**/ #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn NO #endif #ifndef StandardDefines #define StandardDefines -Dibm #endif #ifndef LintOpts #define LintOpts -ax -Dibm #endif #ifdef AIXArchitecture #ifndef SystemV #define SystemV YES #endif #ifndef LnCmd #define LnCmd ln -s #endif #ifdef RtArchitecture #ifndef BootstrapCFlags #define BootstrapCFlags -Daix #endif #else #ifndef HasExecableScripts #define HasExecableScripts YES #endif #ifndef InstallCmd #define InstallCmd /usr/ucb/install #endif #endif #endif /* AIXArchitecture */ #endif /* RsArchitecture */ WRPRC-2.11/config/Imake.cf010066400017710000151000000172400634140471700166750ustar00junkyarddatamgmt00000400000027/* * Vendor blocks for platform determination * * To add support for another platform: * * 1. Put a new #ifdef block below that defines VendorIncludeFile, * VendorFile, ProjectVendorIncludeFile and ProjectVendorFile for your * new platform and then #undefs the machine-specific preprocessor * symbols (to avoid problems with file names). * * 2. Create .cf and .p-cf files with the names given by VendorFile and * ProjectVendorFile. The .cf file should contain any platform-specific * parameter values to override the defaults in the *.tmpl files. The * .p-cf file should be empty. * * 3. You may also need to rebuild imake to know about the new symbol. * * WARNING: if you copy a vendor block from X11's Imake.cf, note that it * it probably uses MacroFile and MacroInclude file to define the vendor.cf * file, which is DIFFERENT than what the WRPRC config files use. * * If you add support for a new system, please send the changes to * dubois@primate.wisc.edu. */ #ifdef Mips /* * MIPS RISC/os cpp predefines nothing, so it has no unique symbol: * build imake with BOOTSTRAPCFLAGS="-DMips -DBSD43" or with * BOOTSTRAPCFLAGS="-DMips -DSYSV" */ #define VendorIncludeFile #define VendorFile Mips.cf #define ProjectVendorIncludeFile #define ProjectVendorFile Mips.p-cf #undef Mips #undef mips #ifdef SYSV #define MipsSysvArchitecture /* for SYSV OS environment */ #else #define MipsBsdArchitecture /* for BSD OS environment */ #endif #define MipsArchitecture /* for chipset type */ #endif /* Mips */ #ifdef ultrix #define VendorIncludeFile #define VendorFile ultrix.cf #define ProjectVendorIncludeFile #define ProjectVendorFile ultrix.p-cf #ifdef vax #undef vax #define VaxArchitecture #endif #ifdef mips #undef mips #define MipsArchitecture #endif #undef ultrix #define UltrixArchitecture #endif #if defined(vax) && !defined(UltrixArchitecture) #define VendorIncludeFile #define VendorFile bsd.cf #define ProjectVendorIncludeFile #define ProjectVendorFile bsd.p-cf #undef vax #define VaxArchitecture #endif #ifdef sun #define VendorIncludeFile #define VendorFile sun.cf #define ProjectVendorIncludeFile #define ProjectVendorFile sun.p-cf # ifdef SVR4 /*# undef SVR4*/ # define SVR4Architecture # endif #ifdef sparc #undef sparc #define SparcArchitecture #endif #ifdef mc68000 #undef mc68000 #define Sun3Architecture #endif #ifdef i386 #undef i386 #define i386Architecture #endif #undef sun #define SunArchitecture #endif /* sun */ #ifdef hpux #define VendorIncludeFile #define VendorFile hp.cf #define ProjectVendorIncludeFile #define ProjectVendorFile hp.p-cf #undef hpux #define HPArchitecture #endif /* hpux */ #ifdef __FreeBSD__ #define VendorIncludeFile #define VendorFile FreeBSD.cf #define ProjectVendorIncludeFile #define ProjectVendorFile FreeBSD.p-cf # undef __FreeBSD__ # define FreeBSDArchitecture # ifdef __i386__ # define i386BsdArchitecture # define i386Architecture # undef i386 # endif #endif /* __FreeBSD__ */ #ifdef __NetBSD__ # define VendorIncludeFile # define VendorFile NetBSD.cf # define ProjectVendorIncludeFile # define ProjectVendorFile NetBSD.p-cf # undef __NetBSD__ # define NetBSDArchitecture # ifdef __i386__ # define i386BsdArchitecture # define i386Architecture # undef i386 # endif # if defined(__sparc__) || defined(sparc) # define SparcArchitecture # undef sparc # endif # if defined(m68k) # undef mc68000 # define Mc68000Architecture # endif #endif /* NetBSD */ #ifdef att #define VendorIncludeFile #define VendorFile att.cf #define ProjectVendorIncludeFile #define ProjectVendorFile att.p-cf #undef att #define ATTArchitecture #endif /* att */ #ifdef apollo #define VendorIncludeFile #define VendorFile apollo.cf #define ProjectVendorIncludeFile #define ProjectVendorFile apollo.p-cf #undef apollo #define ApolloArchitecture #endif /* apollo */ #ifdef sony #define VendorIncludeFile #define VendorFile sony.cf #define ProjectVendorIncludeFile #define ProjectVendorFile sony.p-cf #undef sony #define SonyArchitecture #endif /* sony */ #ifdef M4310 #define VendorIncludeFile #define VendorFile pegasus.cf #define ProjectVendorIncludeFile #define ProjectVendorFile pegasus.p-cf #undef M4310 #define PegasusArchitecture #endif /* M4310 */ #ifdef M4330 #define VendorIncludeFile #define VendorFile m4330.cf #define ProjectVendorIncludeFile #define ProjectVendorFile m4330.p-cf #undef M4330 #define M4330Architecture #endif /* M4330 */ #ifdef macII /* A/UX cpp has no unique symbol: build imake with BOOTSTRAPCFLAGS=-DmacII */ #define VendorIncludeFile #define VendorFile macII.cf #define ProjectVendorIncludeFile #define ProjectVendorFile macII.p-cf #undef macII #define MacIIArchitecture #endif /* macII */ #ifdef CRAY #define VendorIncludeFile #define VendorFile cray.cf #define ProjectVendorIncludeFile #define ProjectVendorFile cray.p-cf #undef cray #undef CRAY #define CrayArchitecture #endif /* CRAY */ #ifdef sgi #define VendorIncludeFile #define VendorFile sgi.cf #define ProjectVendorIncludeFile #define ProjectVendorFile sgi.p-cf #undef sgi #define SGIArchitecture #undef mips #define MipsArchitecture #endif #ifdef stellar #define VendorIncludeFile #define VendorFile stellar.cf #define ProjectVendorIncludeFile #define ProjectVendorFile stellar.p-cf #undef stellar #define StellarArchitecture #endif #ifdef __OSF1__ #define VendorIncludeFile #define VendorFile osf1.cf #define ProjectVendorIncludeFile #define ProjectVendorFile osf1.p-cf #define OSF1Architecture #undef __OSF1__ #ifdef __mips__ #undef __mips__ #define MipsArchitecture #endif #endif /* * A convenience for people running on rt's since they define ibm032, and for * people running AIX (note that AOS will no longer be supported by IBM). * _IBMR2 added for RISC6000 */ #if defined(_IBMR2) && !defined(ibm) #define ibm #endif #if defined(ibm032) && !defined(ibm) #define ibm #endif #if defined(aix) && !defined(ibm) #define ibm #endif #if defined(ibm) #define VendorIncludeFile #define VendorFile ibm.cf #define ProjectVendorIncludeFile #define ProjectVendorFile ibm.p-cf #undef ibm #ifdef _IBMR2 #define RsArchitecture #undef _IBMR2 #else #define IBMArchitecture #ifdef i386 #undef i386 #define PS2Architecture #endif #ifdef ibm032 #undef ibm032 #define RtArchitecture #endif #ifdef aix #undef aix #define AIXArchitecture #endif #endif #endif /* ibm */ #ifdef linux #ifdef PPC #define VendorIncludeFile #define VendorFile linux-pmac.cf #define ProjectVendorIncludeFile #define ProjectVendorFile linux-pmac.p-cf #undef linux #define LinuxArchitecture #define PPCArchitecture #else #define VendorIncludeFile #define VendorFile linux.cf #define ProjectVendorIncludeFile #define ProjectVendorFile linux.p-cf #undef linux #define LinuxArchitecture #define i386Architecture #endif #endif /* linux */ #ifdef NeXT #define VendorIncludeFile #define VendorFile Next.cf #define ProjectVendorIncludeFile #define ProjectVendorFile Next.p-cf #undef Next #define NeXTArchitecture #endif /* Next */ #ifndef VendorIncludeFile XCOMM WARNING: Imake.tmpl not configured; guessing at definitions!!! XCOMM This might mean that BOOTSTRAPCFLAGS wasn't set when building imake. #define VendorIncludeFile #define VendorFile generic.cf #define ProjectVendorIncludeFile #define ProjectVendorFile generic.p-cf #endif WRPRC-2.11/config/linux-pmac.p-cf010066400017710000151000000000000634140471700201430ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/Next.cf010066400017710000151000000025130634140471700165620ustar00junkyarddatamgmt00000400000027XCOMM platform: $Header: $ /* * Originally based on X11 NeXT support by: * Douglas Scott -- U.C. Santa Barbara * doug@foxtrot.ccmrc.ucsb.edu * * Modified for WRPRC2 configuration files by: * -- Daniel L. Green | NeXT/MIME mail welcome! * [home mailto:dang@splunge.com http://www.mcs.com/~dang/ phone:(708)585-0890] * [work mailto:dang@fnbc.com http://www.fccm.com/ phone:(312)732-5532] * * Further modified by Paul DuBois */ #ifndef OSName #define OSName NeXT Release 3.3 #endif XCOMM operating system: OSName #ifndef OSMajorVersion #define OSMajorVersion 3 #endif #ifndef OSMinorVersion #define OSMinorVersion 3 #endif #if HasGcc #ifndef CcCmd #define CcCmd gcc -Wno-import /* dont use -fpcc-struct-return on NeXT */ #endif #endif #ifndef NeXT #define NeXT /* Define needed for Imakefiles */ #endif #ifndef StandardDefines #define StandardDefines -DX_NOT_POSIX -DX_NOT_STDC_ENV -DX_LOCALE #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES /* NO when compiling with -bsd */ #endif /* this next part added for makedepend under 3.0 -- DAS */ #if OSMajorVersion == 3 #ifndef DependFlags #define DependFlags -I/usr/include/ansi -I/usr/include/bsd #endif #endif #ifndef InstallCmd #define InstallCmd install -c /* unlink old */ #endif #ifndef RanlibCmd #define RanlibCmd ranlib -c -s #endif WRPRC-2.11/config/Next.p-cf010066400017710000151000000000000634140471700170040ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/FreeBSD.cf010066400017710000151000000023170634140471700170600ustar00junkyarddatamgmt00000400000027#ifndef OSName #define OSName FreeBSD 2.1.5 #endif XCOMM operating system: OSName #ifndef OSMajorVersion #define OSMajorVersion 2 #endif #ifndef OSMinorVersion #define OSMinorVersion 1 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 5 #endif #ifndef CppCmd #define CppCmd /usr/libexec/cpp -traditional #endif #ifndef PreProcessCmd #define PreProcessCmd /usr/libexec/cpp -traditional #endif #undef InstallCmd #define InstallCmd /usr/bin/install #ifndef HasGcc2 # define HasGcc2 YES #endif #ifndef MkdirHierCmd #define MkdirHierCmd mkdir -p #endif #ifndef CcCmd #define CcCmd gcc #endif #ifndef DefaultCCOptions #define DefaultCCOptions -pipe #endif #ifndef StandardDefines #define StandardDefines -DCSRG_BASED #endif #ifndef TroffCmd #define TroffCmd groff -Tps #endif #ifndef TblCmd #define TblCmd tbl #endif #ifndef EqnCmd #define EqnCmd eqn #endif #ifndef PerlPath #define PerlPath /usr/bin/perl #endif #ifndef SendmailPath #define SendmailPath /usr/sbin/sendmail #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES #endif #ifndef HasStdarg #define HasStdarg YES #endif #ifndef HasVarargs #define HasVarargs YES #endif #ifndef SpoolRootDir #define SpoolRootDir /var/spool #endif WRPRC-2.11/config/FreeBSD.p-cf010066400017710000151000000000000634140471700173000ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/linux-pmac.cf010066400017710000151000000040260634140471700177220ustar00junkyarddatamgmt00000400000027/* * This is based on the linux-pmac.cf that comes with the X Window System * support distributed for Linux/PPC. Many parameter definitions were * removed as they are unneeded for the WRPRC2 files. Many were removed * because they set values to what the defaults were already. * * The values below are current for Linux server 2.0.28. If you're running * a different server, set the OS{Major,Minor,Teeny}Version numbers to * something more appropriate. */ XCOMM platform: linux-pmac.cf #ifndef OSName #define OSName Linux #endif #ifndef OSMajorVersion #define OSMajorVersion 2 #endif #ifndef OSMinorVersion #define OSMinorVersion 0 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 28 #endif #ifndef HasGcc #define HasGcc YES #endif #ifndef HasGcc2 #define HasGcc2 YES #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES #endif /* stdarg.h and varargs.h are under /usr/lib/gcc-lib/ppc-linux/... */ #ifndef HasStdarg #define HasStdarg YES #endif #ifndef HasVarargs #define HasVarargs YES #endif #ifndef HasUnistdH #define HasUnistdH YES #endif /* hmm... */ #define AvoidNullMakeCommand YES #ifndef InstStrip #define InstStrip -s #endif #ifndef InstUidProgMode #define InstUidProgMode -m 4711 #endif #ifndef InstGidProgMode #define InstGidProgMode -m 2711 #endif #ifndef InstUGidProgMode #define InstUGidProgMode -m 6711 #endif #ifndef CcCmd #define CcCmd gcc #endif #ifndef MkdirHierCmd #define MkdirHierCmd mkdir -p #endif #ifndef StandardDefines #define StandardDefines -Dlinux -DPPC -D__powerpc__ -D_POSIX_SOURCE \ -D_BSD_SOURCE -D_GNU_SOURCE -DX_LOCALE #endif #ifndef StandardCppDefines #define StandardCppDefines -traditional StandardDefines #endif /* hmm... */ #define PostIncDir `CcCmd --print-libgcc-file-name | sed 's/libgcc.a/include/'` /* perl and perl5 are the same... */ #ifndef Perl5Cmd #define Perl5Cmd perl #endif #ifndef Perl5Path #define Perl5Path /usr/bin/perl #endif #ifndef SendmailPath #define SendmailPath /usr/sbin/sendmail #endif #ifndef SpoolRootDir #define SpoolRootDir /var/spool #endif WRPRC-2.11/config/Imake.rules~010066400017710000151000001121320634140471700176310ustar00junkyarddatamgmt00000400000027/***************************************************************************** * * * Imake rules * * * *****************************************************************************/ /* * Derived in part from X Window System X11R3-R6 imake rules, and from * WRPRC release 1 rules. * * Some conventions to use in Imakefiles: * * INCLUDES and DEFINES can be used in individual Imakefiles to specify * special include directories or defines that should apply only within a * given Makefile. * * PROJECT_INCLUDES and PROJECT_DEFINES may be used for includes and * definitions that should apply project-wide. The corresponding macros * ProjectIncludes and ProjectDefines are given default values in the * public Imake.params. A project may override the defaults by assigning * these macros values in the project-specific Imake.p-params file. */ #ifndef NullArg /* for specifying null (empty) arguments */ #define NullArg #endif #ifndef NullParameter /* same, but for compatibility with X11 */ #define NullParameter #endif /***************************************************************************** * Directory-making stuff * *****************************************************************************/ /* * If [ -d ] or [ ! -d ] causes make to fail, define this as - in your * system's vendor file */ #ifndef DirFailPrefix #define DirFailPrefix #endif /* * MakeDir() - make a directory if it does't already exist. Used by most * installation rules to ensure that the destination directory exists. * * This rule is used tab-indented as a command line in other rules. */ #ifndef MakeDir #define MakeDir(dir) DirFailPrefix@if [ -d dir ]; then set +x; \ @@\ else (set -x; $(MKDIRHIER) dir); fi #endif /* MakeDir */ /* * MakeDirectories() - make one or more directories as part of the named * operation. */ #ifndef MakeDirectories #define MakeDirectories(op,dirs) @@\ op:: @@\ $(MKDIRHIER) dirs #endif /* MakeDirectories */ /***************************************************************************** * * * Target-building rules * * * *****************************************************************************/ /***************************************************************************** * Rules for generating target names * *****************************************************************************/ #ifndef ProgramTargetName #define ProgramTargetName(target)target #endif #ifndef LibraryTargetName #define LibraryTargetName(libname)Concat(lib,libname.a) #endif #ifndef LintLibraryTargetName #define LintLibraryTargetName(libname)Concat(llib-l,libname.ln) #endif /***************************************************************************** * Rules for building executable programs * *****************************************************************************/ /* * BuildProgram() generates entries to build, remove, and * lint a single program. May be invoked multiple times * in the same Imakefile. * * This rule is the general interface for building programs. * * Arguments: * prog program name * srcs program's source files * objs program's object files * linklibs libraries needed to link program * deplibs libraries to check as dependencies * (must be given as pathnames) * * Targets produced: * all build prog (and all others in Imakefile) * prog build prog only * clean remove all programs in Imakefile * lint lint all programs in Imakefile * lint.prog lint prog only */ #ifndef BuildProgram #define BuildProgram(prog,srcs,objs,linklibs,deplibs) @@\ AllTarget(ProgramTargetName(prog)) @@\ HelpAuxTarget(ProgramTargetName(prog),build ProgramTargetName(prog)) @@\ ProgramTargetName(prog): objs deplibs @@\ RemoveTarget($@) @@\ $(CC) -o $@ objs $(LDOPTS) linklibs $(EXTRA_LDLIBS) @@\ StuffToClean(ProgramTargetName(prog)) @@\ LintSources(ProgramTargetName(prog),srcs) #endif /* BuildProgram */ /* * BuildSimpleProgram() is a simplified version of BuildProgram() that * assumes a single source file name.c, sets SRCS and OBJS, invokes * BuildProgram(), as well as installation and manpage installation rules, * and invokes DependTarget(). May be called only once per Imakefile, and * should not be used with any other program or library-building rules. * * The manual page is assumed to be named name.man. * * The program is installed in LOCALBINDIR and the manual page in MANDIR. */ #ifndef BuildSimpleProgram #define BuildSimpleProgram(name,linklibs,deplibs) @@\ SRCS = name.c @@\ OBJS = name.o @@\ @@\ BuildProgram(name,$(SRCS),$(OBJS),linklibs,deplibs) @@\ InstallProgram(name,$(LOCALBINDIR)) @@\ InstallManPage(name) @@\ @@\ DependTarget() #endif /* BuildSimpleProgram */ /* * SpecialObjectTarget() - compile an object file with special flags * * Arguments: * dst object file name * src source file name * flags special compile flags * depends any special dependencies (in addition to src) * * Targets produced: * dst compile this file */ #ifndef SpecialObjectTarget #define SpecialObjectTarget(dst,src,flags,depends) @@\ dst: src depends @@\ RemoveTarget($@) @@\ $(CC) -c $(CFLAGS) flags src #endif /* SpecialObjectTarget */ /* * SpecialCObjectTarget() - compile a C object file with special flags * * Arguments: * basename file basename (no suffix) * flags special compile flags * depends any special dependencies (in addition to src) * * Targets produced: * dst compile this file */ #ifndef SpecialCObjectTarget #define SpecialCObjectTarget(basename,flags,depends) @@\ SpecialObjectTarget(basename.Osuf,basename.c,flags,depends) #endif /* SpecialCObjectTarget */ /***************************************************************************** * Library-building rules * *****************************************************************************/ /* * NormalLibraryObjectRule() - For building objects in libraries. * Invoke when using BuildNormalLibrary(). Needs to be invoked only * once, even if you're building multiple libraries in a directory. * Since this rule overrides the normal *.c -> *.o transformation, * it's best not to build programs and libraries in the same directory. */ #ifndef NormalLibraryObjectRule #define NormalLibraryObjectRule() @@\ .c.o: @@\ RemoveTarget ($@) @@\ $(CC) -c $(CFLAGS) $*.c #endif /* NormalLibraryObjectRule */ /* * BuildNormalLibrary() - generate target entry to build a library from * the named object files. When you use this, invoke NormalLibraryObjectRule() * as well. * * Arguments: * name library name; this is the basename, the target name * is "libname.a" * srcs library's source files * objs library's object files * * Targets produced: * all build this library (and all others in Imakefile) * libname.a build this library only * clean remove all libraries in Imakefile * lint lint all sources in Imakefile * lint.libname.a lint sources for libname.a only */ #ifndef BuildNormalLibrary #define BuildNormalLibrary(name,srcs,objs) @@\ AllTarget(LibraryTargetName(name)) @@\ LibraryTargetName(name): objs @@\ RemoveTarget($@) @@\ $(AR) $@ objs @@\ RanLibrary($@) @@\ StuffToClean(LibraryTargetName(name)) @@\ LintSources(LibraryTargetName(name),srcs) @@\ HelpAuxTarget(LibraryTargetName(name),build the LibraryTargetName(name) library) #endif /* BuildNormalLibrary */ /* Build a lint library */ #ifndef BuildLintLibrary #define BuildLintLibrary(name,srcs) @@\ lintlib:: LintLibraryTargetName(name) @@\ @@\ LintLibraryTargetName(name):: srcs @@\ RemoveTarget($@) @@\ $(LINT) Concat($(LINTLIBFLAG),name) $(LINTFLAGS) srcs @@\ StuffToClean(LintLibraryTargetName(name)) @@\ HelpAuxTarget(LintLibraryTargetName(name),build the LintLibraryTargetName(name) lint library) #endif /* BuildLintLibrary */ /***************************************************************************** * Rules for building targets by running templates through filters * *****************************************************************************/ /* * FileFromTemplate() - Create a non-executable target file by running a * template through a filter. */ #ifndef FileFromTemplate #define FileFromTemplate(dst,src,filter,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ filter src > $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build dst) #endif /* FileFromTemplate */ /* * ScriptFromTemplate() - Create an executable target file (i.e., a script) * for some arbitrary program by running a template through some filter. * prog must be a full pathname. * * If the HasExecableScripts configuration parameter is not YES, make sure * the first line begins with a colon and write the script into a temp * file, have the program execute that, and remove the temp file when * done. Ugly ugly ugly. On the other hand, the template need not begin * with a #! line. */ #ifndef ScriptFromTemplate #if HasExecableScripts /* can use #! */ #define ScriptFromTemplate(prog,dst,src,filter,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo "#!"prog > $@ @@\ filter src >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #else #define ScriptFromTemplate(prog,dst,src,filter,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo \: > $@ @@\ echo 'x=$(TMPDIR)/xx$$$$' >> $@ @@\ echo "$(CAT) > "'$$x'" << 'EOF'" >> $@ @@\ filter src >> $@ @@\ echo EOF >> $@ @@\ echo prog '$$x' '$$@' >> $@ @@\ echo $(RM) '$$x' >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #endif /* HasExecableScripts */ #endif /* ScriptFromTemplate */ /* * Rules for building targets by running templates through msub * * FileFromMsubTemplate() - create non-executable target * FileFromMsubTemplateWithFlags() - create non-executable target, allowing * flags to be passed to Msub * ScriptFromMsubTemplate() - create executable script for arbitrary program * ShScriptFromMsubTemplate() - create executable shell script * ScriptFromMsubTemplateWithFlags() - create executable script for arbitrary * program, allowing flags to be passed to Msub * ShScriptFromMsubTemplateWithFlags() - create executable shell script, * allowing flags to be passed to Msub * * Arguments: * prog - program that should process script; must be full pathname * dst - name of file to produce * src - name of template from which file is produced * flags - flags to pass to msub * deps - dependencies that must exist before building dst */ #ifndef FileFromMsubTemplate #define FileFromMsubTemplate(dst,src,deps) @@\ FileFromTemplate(dst,src,$(MSUB),deps) #endif /* FileFromMsubTemplate */ #ifndef ScriptFromMsubTemplate #define ScriptFromMsubTemplate(prog,dst,src,deps) @@\ ScriptFromTemplate(prog,dst,src,$(MSUB),deps) #endif /* ScriptFromMsubTemplate */ #ifndef ShScriptFromMsubTemplate #define ShScriptFromMsubTemplate(dst,src,deps) @@\ ScriptFromTemplate($(SHELL),dst,src,$(MSUB),deps) #endif /* ShScriptFromMsubTemplate */ #ifndef FileFromMsubTemplateWithFlags #define FileFromMsubTemplateWithFlags(dst,src,flags,deps) @@\ FileFromTemplate(dst,src,$(MSUB) flags,deps) #endif /* FileFromMsubTemplateWithFlags */ #ifndef ScriptFromMsubTemplateWithFlags #define ScriptFromMsubTemplateWithFlags(prog,dst,src,flags,deps) @@\ ScriptFromTemplate(prog,dst,src,$(MSUB) flags,deps) #endif /* ScriptFromMsubTemplateWithFlags */ #ifndef ShScriptFromMsubTemplateWithFlags #define ShScriptFromMsubTemplateWithFlags(dst,src,flags,deps) @@\ ScriptFromTemplate($(SHELL),dst,src,$(MSUB) flags,deps) #endif /* ShScriptFromMsubTemplateWithFlags */ /* * Rules for building targets by running templates through cpp * * FileFromCppTemplate() - create non-executable target * ScriptFromCppTemplate() - create executable script for arbitrary program * ShScriptFromCppTemplate() - create executable shell script * * For all of these, translate XCOMM into pound sign with sed, rather than * passing -DXCOMM=XCOMM to cpp, because that trick does not work on all * ANSI C preprocessors. (Translation occurs at beginning of lines only.) * Also delete line numbers from the cpp output (-P is not portable, I guess). * * Arguments: * prog - program that should process script; must be full pathname * dst - name of file to produce * src - name of template from which file is produced * defs - defines to pass to cpp * deps - dependencies that must exist before building dst */ #ifndef CppSedMagic #define CppSedMagic sed -e '/^# *[0-9][0-9]* *.*$$/d' \ -e '/^XCOMM$$/s//#/' \ -e '/^XCOMM[^a-zA-Z0-9_]/s/^XCOMM/#/' #endif /* CppSedMagic */ #ifndef FileFromCppTemplate #define FileFromCppTemplate(dst,src,defs,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ $(CPP) defs < src | CppSedMagic >> $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build dst) #endif /* FileFromCppTemplate */ /* * ScriptFromCppTemplate() - generate target entry to create a script for * an arbitrary program by running the input through cpp. If the * HasExecableScripts configuration parameter is not YES, then make sure * that the first line begins with a colon and write the script into a * temp file, have the program execute that, and remove the temp file when * done. Ugly ugly ugly. On the other hand, the template need not begin * with a #! line. * * prog must be a full pathname. */ #ifndef ScriptFromCppTemplate #if HasExecableScripts /* can use #! */ #define ScriptFromCppTemplate(prog,dst,src,defs,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo "#!"prog > $@ @@\ $(CPP) defs < src | CppSedMagic >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #else #define ScriptFromCppTemplate(prog,dst,src,defs,deps) @@\ AllTarget(dst) @@\ dst:: src deps @@\ RemoveTarget($@) @@\ echo \: > $@ @@\ echo 'x=/tmp/xx$$$$' >> $@ @@\ echo "$(CAT) > "'$$x'" << 'EOF'" >> $@ @@\ $(CPP) defs < src | CppSedMagic >> $@ @@\ echo EOF >> $@ @@\ echo prog '$$x' '$$@' >> $@ @@\ echo $(RM) '$$x' >> $@ @@\ $(CHMOD) a+x $@ @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build the dst script) #endif /* HasExecableScripts */ #endif /* ScriptFromCppTemplate */ #ifndef ShScriptFromCppTemplate #define ShScriptFromCppTemplate(dst,src,defs,deps) @@\ ScriptFromCppTemplate($(SHELL),dst,src,defs,deps) #endif /* ShScriptFromCppTemplate */ /***************************************************************************** * Miscellaneous target-building rules * *****************************************************************************/ /* Generate a fake target entry that just announces a file is not built */ #ifndef FakeBuildFile #define FakeBuildFile(target) @@\ target:: @@\ @echo target" is not built here" #endif /* FakeBuildFile */ /* * LinkTarget() - Make a link to a target. Used when multiple targets use * the same file under different names. */ #ifndef LinkTarget #define LinkTarget(target,linkto) @@\ AllTarget(target) @@\ target:: linkto @@\ RemoveTarget(target) @@\ $(LN) linkto target @@\ StuffToClean(target) @@\ HelpAuxTarget(target,link target to linkto) #endif /* LinkTarget */ /* * FileFromIntermediary() - This is used when a file is created by processing * another file, but when that processing often will generate a file that's * identical to the current version (e.g., you create a header file from some * sort of template). By creating an intermediary file from the source and * comparing it to the destination, you can avoid touching the destination * if the intermediary isn't different. * * Useful to avoid triggering unnecessary builds of targets that depend on * dst. */ #ifndef FileFromIntermediary #define FileFromIntermediary(dst,inter,src) @@\ AllTarget(dst) @@\ dst:: src @@\ $(MAKE) $(MFLAGS) inter @@\ UpdateIfDifferent(dst,inter) @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,build dst) #endif /* * SimpleWorldTarget() - Generate a World target that can be used to build * the entire project from scratch with "make World". The initial "all" * target is simply to prevent "World" from being the default target if * there are no earlier rule invocations in the Imakefile. * * Useful for relatively simple or straightforward projects built along * "configure-depend-build" lines. Probably insufficient for projects with * special build requirements. */ #ifndef SimpleWorldTarget #define SimpleWorldTarget(project,release) @@\ all:: @@\ World:: @@\ @echo "Building "project", Release "release @@\ @echo "" @@\ @date @@\ @echo "" @@\ $(MAKE) $(MFLAGS) Makefile @@\ $(MAKE) $(MFLAGS) Makefiles @@\ $(MAKE) $(MFLAGS) clean @@\ $(MAKE) $(MFLAGS) depend @@\ $(MAKE) $(MFLAGS) all @@\ @echo "" @@\ @date @@\ @echo "" @@\ @echo "Done building "project @@\ HelpAuxTarget(World,build the entire project distribution) #endif /* SimpleWorldTarget */ /***************************************************************************** * * * Installation rules * * * *****************************************************************************/ /* * In general, install rules generate an "install" target entry so that * "make install" installs everything (but manual pages), and also an * "i.target" entry so that "make i.target" installs only the named target. * This allows single-target installation granularity. * * Manual page install rules generate an "install.man" target entry and an * "i.target.man" entry so "make install.man" installs all manual pages and * "make i.target.man" installs the man page for the named target only. * Note that the individual page installation target alway ends in ".man" * even if name of the installed man page ends in something else like ".1" * or ".3". */ /* * InstallFile() is the general interface for file installation. * Most of the other rules call it with various flags. (Manual pages * are handled differently; see below.) * * HelpAuxTarget() is not placed at the end of the rule, because if * it were, InstallLibrary() would get messed up. (InstallLibrary() * adds lines to the i.dstfile target entry; that's an ugly thing, * but it works.) */ #ifndef InstallFile #define InstallFile(target,dstfile,srcfile,dir,flags) @@\ target:: i.dstfile @@\ HelpAuxTarget(i.dstfile,install dstfile) @@\ i.dstfile:: srcfile @@\ MakeDir(dir) @@\ $(INSTALL) flags srcfile dir/dstfile #endif /* InstallFile */ /* Install a normal program */ #ifndef InstallProgram #define InstallProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTPROGFLAGS)) #endif /* InstallProgram */ /* Install a setuid program */ #ifndef InstallUidProgram #define InstallUidProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTUIDPROGFLAGS)) #endif /* InstallUidProgram */ /* Install a setgid program */ #ifndef InstallGidProgram #define InstallGidProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTGIDPROGFLAGS)) #endif /* InstallGidProgram */ /* Install a setuid/setgid program */ #ifndef InstallUGidProgram #define InstallUGidProgram(file,dir) @@\ InstallFile(install,ProgramTargetName(file),ProgramTargetName(file),dir,$(INSTUGIDPROGFLAGS)) #endif /* InstallUGidProgram */ /* Install an executable script */ #ifndef InstallScript #define InstallScript(file,dir) @@\ InstallFile(install,file,file,dir,$(INSTSCRIPTFLAGS)) #endif /* InstallScript */ /* Install a data file (non-executable file) */ #ifndef InstallDataFile #define InstallDataFile(file,dir) @@\ InstallFile(install,file,file,dir,$(INSTDATFLAGS)) #endif /* InstallDataFile */ /* Install an include file */ #ifndef InstallIncludeFile #define InstallIncludeFile(file,dir) @@\ InstallFile(install,file,file,dir,$(INSTINCFLAGS)) #endif /* InstallIncludeFile */ /* * Install a library. This must install the library *and* rerun ranlib. * The RanLibrary() line depends on InstallFile() not adding blank lines at * end! */ #ifndef InstallLibrary #define InstallLibrary(name,dir) @@\ InstallFile(install,LibraryTargetName(name),LibraryTargetName(name),dir,$(INSTLIBFLAGS)) @@\ RanLibrary(dir/LibraryTargetName(name)) #endif /* InstallLibrary */ /* Install a lint library */ #ifndef InstallLintLibrary #define InstallLintLibrary(name,dir) @@\ InstallFile(install.lint,LintLibraryTargetName(name),LintLibraryTargetName(name),dir,$(INSTLIBFLAGS)) #endif /* InstallLintLibrary */ /* Install a link to another file installed in the given directory */ #ifndef InstallLink #define InstallLink(target,linkto,dir) @@\ install:: i.target @@\ i.target:: i.linkto @@\ MakeDir(dir) @@\ RemoveTarget(dir/target) @@\ $(LN) dir/linkto dir/target @@\ HelpAuxTarget(i.target,install dir/target as a link to dir/linkto) #endif /* InstallLink */ /* Install a set of data files */ #ifndef InstallMultipleDataFiles #define InstallMultipleDataFiles(target,files,dir) @@\ target:: @@\ MakeDir(dir) @@\ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\ for i in files ;\ @@\ do \ @@\ (set -x; $(INSTALL) $(INSTDATFLAGS) $$i dir/$$i); \ @@\ done @@\ HelpAuxTarget(target,install files) #endif /* InstallMultipleDataFiles */ /* * Manual page installation rules * * It's assumed that the manual page source file always has a .man * suffix. * * InstallManFile() is the general interface to manual page install * rules. The other installers call it with the proper arguments, and * require only the basename of the manual page. * * InstallMan1Page() - install a section 1 manual page * InstallMan2Page() - install a section 2 manual page * InstallMan3Page() - install a section 3 manual page * InstallMan4Page() - install a section 4 manual page * InstallMan5Page() - install a section 5 manual page * InstallMan6Page() - install a section 6 manual page * InstallMan7Page() - install a section 7 manual page * InstallMan8Page() - install a section 8 manual page * InstallManLPage() - install a section l manual page * InstallManNPage() - install a section n manual page * InstallManPage() - install a "default" section manual page */ #ifndef InstallManFile #define InstallManFile(target,name,dstsuffix,dir) @@\ target:: i.name.man @@\ i.name.man:: name.man @@\ MakeDir(dir) @@\ $(INSTALL) $(INSTMANFLAGS) name.man dir/name.dstsuffix @@\ HelpAuxTarget(i.name.man,install name.man manual page) #endif /* InstallManFile */ #ifndef InstallMan1Page #define InstallMan1Page(file) @@\ InstallManFile(install.man,file,$(MAN1SUFFIX),$(MAN1DIR)) #endif /* InstallMan1Page */ #ifndef InstallMan2Page #define InstallMan2Page(file) @@\ InstallManFile(install.man,file,$(MAN2SUFFIX),$(MAN2DIR)) #endif /* InstallMan2Page */ #ifndef InstallMan3Page #define InstallMan3Page(file) @@\ InstallManFile(install.man,file,$(MAN3SUFFIX),$(MAN3DIR)) #endif /* InstallMan3Page */ #ifndef InstallMan4Page #define InstallMan4Page(file) @@\ InstallManFile(install.man,file,$(MAN4SUFFIX),$(MAN4DIR)) #endif /* InstallMan4Page */ #ifndef InstallMan5Page #define InstallMan5Page(file) @@\ InstallManFile(install.man,file,$(MAN5SUFFIX),$(MAN5DIR)) #endif /* InstallMan5Page */ #ifndef InstallMan6Page #define InstallMan6Page(file) @@\ InstallManFile(install.man,file,$(MAN6SUFFIX),$(MAN6DIR)) #endif /* InstallMan6Page */ #ifndef InstallMan7Page #define InstallMan7Page(file) @@\ InstallManFile(install.man,file,$(MAN7SUFFIX),$(MAN7DIR)) #endif /* InstallMan7Page */ #ifndef InstallMan8Page #define InstallMan8Page(file) @@\ InstallManFile(install.man,file,$(MAN8SUFFIX),$(MAN8DIR)) #endif /* InstallMan8Page */ #ifndef InstallManLPage #define InstallManLPage(file) @@\ InstallManFile(install.man,file,$(MANLSUFFIX),$(MANLDIR)) #endif /* InstallManLPage */ #ifndef InstallManNPage #define InstallManNPage(file) @@\ InstallManFile(install.man,file,$(MANNSUFFIX),$(MANNDIR)) #endif /* InstallManNPage */ #ifndef InstallManPage #define InstallManPage(file) @@\ InstallManFile(install.man,file,$(MANSUFFIX),$(MANDIR)) #endif /* InstallManPage */ /* * "Fake" install rules for targets that are built but not installed anywhere. * These may be used to indicate a file is explicitly not installed (as * opposed to your appearing to have forgotten to invoke an installation rule * in the Imakefile). */ #ifndef FakeInstallFile #define FakeInstallFile(file) @@\ install:: i.file @@\ i.file:: @@\ @echo file is not installed anywhere. #endif /* FakeInstallFile */ #ifndef FakeInstallLibrary #define FakeInstallLibrary(name) @@\ install:: i.LibraryTargetName(name) @@\ i.LibraryTargetName(name):: @@\ @echo LibraryTargetName(name) is not installed anywhere. #endif /* FakeInstallLibrary */ /***************************************************************************** * * * Rules that generate recursive target entries * * * *****************************************************************************/ /* * NamedTargetSubdirs() - recursively run the named operation in a set of * directories. */ #ifndef NamedTargetSubdirs #define NamedTargetSubdirs(op,dirs,verb,flags) @@\ op:: @@\ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\ for i in dirs ;\ @@\ do \ @@\ ($(CHDIR) $$i ; echo verb "in $(CURRENT_DIR)/$$i..."; \ @@\ $(MAKE) $(MFLAGS) flags op); \ @@\ done #endif /* NamedTargetSubdirs */ /* * MakeSubdirs() - generate recursive "all" target entry. If you want * CDEBUGFLAGS passed along to subdirectories, provide a line like the * following in the appropriate Imakefile: * * #define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' */ #ifndef MakeSubdirs #define MakeSubdirs(dirs) \ NamedTargetSubdirs(all,dirs,"making" all,PassCDebugFlags) #endif /* MakeSubdirs */ /* * DependSubdirs() - generate recursive "depend" target entry. */ #ifndef DependSubdirs #define DependSubdirs(dirs) \ NamedTargetSubdirs(depend,dirs,"depending",NullArg) #endif /* DependSubdirs */ /* * InstallSubdirs() - generate recursive "install" target entry to install * programs and files. */ #ifndef InstallSubdirs #define InstallSubdirs(dirs) \ NamedTargetSubdirs(install,dirs,"installing",NullArg) #endif /* InstallSubdirs */ /* * InstallManSubdirs() - generate recursive "install.man" target entry * to install manual pages. */ #ifndef InstallManSubdirs #define InstallManSubdirs(dirs) \ NamedTargetSubdirs(install.man,dirs,"installing man pages",NullArg) #endif /* InstallManSubdirs */ /* * CleanSubdirs() - generate recursive "clean" target entry. */ #ifndef CleanSubdirs #define CleanSubdirs(dirs) \ NamedTargetSubdirs(clean,dirs,"cleaning",RM_CMD='$(RM_CMD)') #endif /* CleanSubdirs */ /* * TagSubdirs() - generate recursive "tags" target entry. */ #ifndef TagSubdirs #define TagSubdirs(dirs) \ NamedTargetSubdirs(tags,dirs,"tagging",TAGS='$(TAGS)') #endif /* TagSubdirs */ /***************************************************************************** * * * Makefile-generating rules * * * *****************************************************************************/ /* * MakefileTarget() - generate target entry to build Makefile from * Imakefile by invoking imboot. */ #ifndef MakefileTarget #define MakefileTarget() @@\ Makefile:: @@\ $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) #endif /* MakefileTarget */ /* * MakefileSubdirs() - generate target entry to recursively recreate * Makefiles. * * Logic: * * - Turn on error ignoring if -i or -k found in make argument list * - Loop through each child directory named in argument * - Figure out value of TOP in child. If TOP is an absolute path, it's * the same in the child. If TOP is relative, prepend path from child * to parent onto it. * - Change into child, build the Makefile there using imboot, then * run "make Makefiles" in case child has its own subdirectories */ #ifndef MakefileSubdirs #define MakefileSubdirs(dirs) @@\ Makefiles:: @@\ @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ @@\ for i in dirs ;\ @@\ do \ @@\ echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \ @@\ case "$$i" in \ @@\ ./?*/?*/?*/?*) parent=../../../../;; \ @@\ ./?*/?*/?*) parent=../../../;; \ @@\ ./?*/?*) parent=../../;; \ @@\ ./?*) parent=../;; \ @@\ */?*/?*/?*) parent=../../../../;; \ @@\ */?*/?*) parent=../../../;; \ @@\ */?*) parent=../../;; \ @@\ *) parent=../;; \ @@\ esac; \ @@\ case "$(TOP)" in \ @@\ /?*) topadj= ;; \ @@\ *) topadj=$$parent ;; \ @@\ esac; \ @@\ ($(CHDIR) $$i ; \ @@\ $(IMBOOT_CMD) $$topadj$(TOP) $(CURRENT_DIR)/$$i ; \ @@\ $(MAKE) $(MFLAGS) Makefiles ) ; \ @@\ done #endif /* MakefileSubdirs */ /***************************************************************************** * * * Document-formatting rules (troff-based) * * * *****************************************************************************/ /* * TroffToPostScript() is the base rule; the others call it with * appropriate arguments for the various macro packages. * * Arguments: * dst output file (this is also the main target) * src source file(s) * formatter formatting program and its options * filters preprocessors * deps dependencies * * There is always some processs in * front of troff (either soelim or cat) so that filters can be * inserted in between as appropriate. filters can be empty, or * something like "|$(TBL)|$(EQN)" (without quotes). (If non-empty, * filters MUST begin with a "|".) * * TroffMsToPostScript() - Format a document that uses the -ms macros * TroffMeToPostScript() - Format a document that uses the -me macros * TroffMmToPostScript() - Format a document that uses the -mm macros * TroffManToPostScript() - Format a document that uses the -man macros * TroffMdocToPostScript() - Format a document that uses the -mdoc macros * * TROFFOPTS is for command line use. You can set it, e.g., to format * only certain pages. */ #ifndef TroffToPostScript #define TroffToPostScript(dst,src,formatter,filters,deps) @@\ dst:: src deps @@\ $(SOELIM) src filters | formatter > dst @@\ StuffToClean(dst) @@\ HelpAuxTarget(dst,format dst in PostScript) #endif /* TroffToPostScript */ #ifndef TroffMsToPostScript #define TroffMsToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(TROFF) $(MSMACROS) $(TROFFOPTS),filters,deps) #endif /* TroffMsToPostScript */ #ifndef TroffMeToPostScript #define TroffMeToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(TROFF) $(MEMACROS) $(TROFFOPTS),filters,deps) #endif /* TroffMeToPostScript */ #ifndef TroffMmToPostScript #define TroffMmToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(TROFF) $(MMMACROS) $(TROFFOPTS),filters,deps) #endif /* TroffMmToPostScript */ #ifndef TroffManToPostScript #define TroffManToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(TROFF) $(MANMACROS) $(TROFFOPTS),filters,deps) #endif /* TroffManToPostScript */ #ifndef TroffMdocToPostScript #define TroffMdocToPostScript(dst,src,filters,deps) @@\ TroffToPostScript(dst,src,$(TROFF) $(MDOCMACROS) $(TROFFOPTS),filters,deps) #endif /* TroffMdocToPostScript */ /***************************************************************************** * * * Odds and ends * * * *****************************************************************************/ /* * RemoveTarget() - generate a command to remove the target. * * This rule is used tab-indented as a command line in other rules. */ #ifndef RemoveTarget #define RemoveTarget(target) $(RM) target #endif /* RemoveTarget */ /* * RanLibrary() - run ranlib if it's present on the given machine, otherwise * do nothing. * * This rule is used tab-indented as a command line in other rules. */ #ifndef RanLibrary #if HasRanlibCmd #define RanLibrary(args) $(RANLIB) args #else #define RanLibrary(args) /**/ #endif #endif /* RanLibrary */ /* * StuffToClean() - generate a clean target entry to remove the files named * in the argument. Invoked by other rules to make sure that targets built * get removed by "make clean", but can also be used in Imakefiles to * explicitly name targets that should be cleaned. */ #ifndef StuffToClean #define StuffToClean(stuff) @@\ clean:: @@\ RemoveTarget (stuff) #endif /* StuffToClean */ /* * UpdateIfDifferent() - update dst with src if they're different. Otherwise * leave alone. */ #ifndef UpdateIfDifferent #define UpdateIfDifferent(dst,src) -@$(CMP) -s dst src; \ @@\ if [ $$? -ne 0 ]; then \ @@\ echo "$(MV) "src dst; \ @@\ $(MV) src dst; \ @@\ echo dst" updated"; \ @@\ else \ @@\ echo dst" not updated." ; \ @@\ fi #endif /* UpdateIfDifferent */ /* * AllTarget() - generate an all target entry to built the file named * in the argument. Invoked by other rules to make sure that targets get * built by "make all", but can also be used in Imakefiles to explicitly * name targets that should be built. */ #ifndef AllTarget #define AllTarget(target) @@\ all:: target #endif /* AllTarget */ /* * LintSources() - run the source files for a given program through lint. * Usually invoked by program-building rules to generate lint targets. * * Arguments: * target target (program or library) the source files belong to * srcs target's source files * * Targets produced: * lint lint these source files (and all others in Makefile) * lint.target lint target's source files only */ #ifndef LintSources #define LintSources(target,srcs) @@\ lint:: lint.target @@\ lint.target: @@\ $(LINT) $(LINTFLAGS) srcs $(LINTLIBS) @@\ HelpAuxTarget(lint.target,lint sources for target) #endif /* LintSources */ /* * DependTarget() - generate depend entry to compute dependencies for all * files listed in $(SRCS). This means that in the Imakefile, SRCS should * be assigned a value naming all the *.c files to be processed. */ #ifndef DependTarget #define DependTarget() @@\ depend:: @@\ $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) #endif /* DependTarget */ /* * CleanTarget() - generate target entry to remove any garbage files; the #* * is here instead of in the definition of RM_CMD because System V will treat * the pound sign in the RM_CMD variable as a comment. */ #ifndef CleanTarget #define CleanTarget() @@\ clean:: @@\ $(RM_CMD) "#"* #endif /* CleanTarget */ /* * TagsTarget() - generate target entry to compute tags files for C source * code. */ #ifndef TagsTarget #define TagsTarget() @@\ tags:: @@\ $(TAGS) -w *.[ch] @@\ $(TAGS) -xw *.[ch] > TAGS #endif /* TagsTarget */ /* * FiFiiSuffixRule() - provide suffix rule necessary to run figen to * produce a .fii file from a .fi file. */ #ifndef FiFiiSuffixRule #define FiFiiSuffixRule() @@\ .SUFFIXES: .fi .fii @@\ .fi.fii: @@\ $(FIGEN) $*.fi #endif /* FiFiiSuffixRule */ /* * Generate a help_aux target for the default help target. This is for * "make help" and can be placed inside target-building rules to print * for the user the command that builds a particular target. target is * the target name and description is a description of what "make target" * builds. */ #ifndef HelpAuxTarget #define HelpAuxTarget(target,description) @@\ help_aux:: @@\ @echo "'make "target"' to "description #endif /* HelpAuxTarget */ amedTargetSubdirs(depend,dirs,"depending",NullArg) #endif /* DependSubdirs */ /* * InstallSubdirs() - generate recursive "install" target entry to install * programs and files. */ #ifndef InstallSubdirs #define InstallSubdirs(dirs) \ NamedTargetSubdirs(install,dirs,"installing",NullArg) #endif /* InstallSubdirs */ /* * InstallManSubdirs() - generate recursive "install.man" target entry * to install manual pageWRPRC-2.11/config/NetBSD.p-cf010066400017710000151000000000000634140471700171450ustar00junkyarddatamgmt00000400000027WRPRC-2.11/config/NetBSD.cf010066400017710000151000000037400634140472000167200ustar00junkyarddatamgmt00000400000027#ifndef OSName #define OSName NetBSD 1.2.1 #endif XCOMM operating system: OSName #ifndef OSMajorVersion #define OSMajorVersion 1 #endif #ifndef OSMinorVersion #define OSMinorVersion 2 #endif #ifndef OSTeenyVersion #define OSTeenyVersion 1 #endif #ifndef CppCmd #define CppCmd /usr/libexec/cpp -traditional #endif #ifndef PreProcessCmd #define PreProcessCmd /usr/libexec/cpp -traditional #endif #undef InstallCmd #define InstallCmd /usr/bin/install #ifndef HasGcc2 # define HasGcc2 YES #endif #ifndef MkdirHierCmd #define MkdirHierCmd mkdir -p #endif #ifndef CcCmd #define CcCmd gcc #endif /* #ifndef DefaultCCOptions #define DefaultCCOptions -pipe #endif */ #ifndef StandardDefines #define StandardDefines -DCSRG_BASED #endif #ifndef TroffCmd #define TroffCmd groff -Tps #endif #ifndef TblCmd #define TblCmd tbl #endif #ifndef EqnCmd #define EqnCmd eqn -Tps #endif #ifndef NeqnCmd #define NeqnCmd neqn -Tascii /* not -Tlatin1 */ #endif /* #ifndef PerlPath #define PerlPath /usr/bin/perl #endif */ #ifndef SendmailPath #define SendmailPath /usr/sbin/sendmail #endif #ifndef HasVoidSignalReturn #define HasVoidSignalReturn YES #endif #ifndef HasStdarg #define HasStdarg YES #endif #ifndef HasVarargs #define HasVarargs YES #endif #ifndef SpoolRootDir #define SpoolRootDir /var/spool #endif /* * Man pages can be preformatted when installed; override the default * for InstallManPreformatted as YES. */ #ifndef InstallManPreformatted #define InstallManPreformatted NO #endif #if InstallManPreformatted #ifndef ManSourcePath #define ManSourcePath $(MANROOT)/cat #endif #ifndef InstallManFile #define InstallManFile(target,name,dstsuffix,dir) @@\ target:: i.name.man @@\ i.name.man:: name.man @@\ MakeDir(dir) @@\ x=$(TMPDIR)/man$$$$ ; \ @@\ $(NEQN) name.man | $(TBL) | $(NROFF) $(MANMACROS) | $(COL) > $$x ; \ @@\ $(INSTALL) $(INSTMANFLAGS) $$x dir/name.dstsuffix ; \ @@\ $(RM) $$x #endif /* InstallManFile */ #endif /* InstallManPreformatted */ WRPRC-2.11/examples/004077500017710000151000000000000634140472000156775ustar00junkyarddatamgmt00000400000027WRPRC-2.11/examples/library/004077500017710000151000000000000634140472000173435ustar00junkyarddatamgmt00000400000027WRPRC-2.11/examples/library/Imakefile010064000017710000151000000011030634140472000211360ustar00junkyarddatamgmt00000400000027/* * Simple Imakefile to build a library */ XCOMM Simple Makefile to build a library XCOMM List the source and object files SRCS = src1.c src2.c OBJS = src1.o src2.o XCOMM Invoke rules to build the libraries NormalLibraryObjectRule() BuildNormalLibrary(fake,$(SRCS),$(OBJS)) XCOMM Invoke rules for installing the library and the lint library. XCOMM Normally you'd use LOCALUSRLIBDIR and LOCALLINTLIBDIR, but we XCOMM don't want to really install these anywhere. InstallLibrary(fake,./play) InstallLintLibrary(fake,./play) XCOMM Invoke rule to depend sources DependTarget() WRPRC-2.11/examples/library/src1.c010064000017710000151000000000230634140472000203410ustar00junkyarddatamgmt00000400000027FakeLibFunc1() { } WRPRC-2.11/examples/library/src2.c010064000017710000151000000000230634140472000203420ustar00junkyarddatamgmt00000400000027FakeLibFunc2() { } WRPRC-2.11/examples/library/Makefile010064000017710000151000000234360634140472000210020ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $ # # The cpp used on this machine replaces all newlines and multiple tabs and # spaces in a macro expansion with a single space. Imake tries to compensate # for this, but is not always successful. # # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 93/06/30 # operating system: SunOS 4.1.1 # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 03 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = $(USRLIBDIR)/config # Project identfication - name and release level PROJECTNAME = no-project-name PROJECTMAJORRELEASE = 0 PROJECTMINORRELEASE = 00 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/local USRLIBDIR = /usr/lib TMPDIR = /tmp ADMDIR = /usr/adm ETCDIR = /usr/etc INCLUDEROOT = /usr/include INSTBINDIR = /usr/local INSTUSRLIBDIR = $(USRLIBDIR) INSTLINTLIBDIR = $(LINTLIBDIR) INSTLIBDIR = $(USRLIBDIR) INSTINCDIR = $(INCLUDEROOT)/local MANROOT = /usr/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MANLSUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar clq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) PREPROCESSCMD = cc -E $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -C LINTLIBDIR = $(USRLIBDIR)/lint LINTOPTS = -axz LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RANLIB = ranlib RANLIBINSTFLAGS = RM = rm -f TAGS = ctags PERL = perl PERLPATH = /usr/local/perl # Important local programs FIGEN = figen DISTAR = distar STD_CPP_DEFINES = STD_INCLUDES = STD_DEFINES = EXTRA_LOAD_FLAGS = EXTRA_LIBRARIES = ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) $(EXTRA_LOAD_FLAGS) # Project-specific include file directories, definitions, and libraries PROJECT_INCLUDES = -I$(INSTINCDIR) PROJECT_DEFINES = CDEBUGFLAGS = -O CCOPTIONS = RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = install INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0444 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TSLIB = -ltokenscan DEPTSLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile INSTLIBMODE = -m 644 # Simple Makefile to build a library # List the source and object files SRCS = src1.c src2.c OBJS = src1.o src2.o # Invoke rules to build the libraries .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libfake.a libfake.a: $(OBJS) $(RM) $@ $(AR) $@ $(OBJS) $(RANLIB) $@ clean:: $(RM) libfake.a lint:: lint.libfake.a lint.libfake.a: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) # Invoke rules for installing the library and the lint library. # Normally you'd use LOCALUSRLIBDIR and LOCALLINTLIBDIR, but we # don't want to really install these anywhere. install:: i.libfake.a i.libfake.a:: libfake.a @if [ -d ./play ]; then set +x; \ else (set -x; $(MKDIRHIER) ./play); fi $(INSTALL) -c $(INSTLIBFLAGS) libfake.a ./play/libfake.a $(RANLIB) ./play/libfake.a install.lint:: i.llib-lfake.ln i.llib-lfake.ln:: llib-lfake.ln @if [ -d ./play ]; then set +x; \ else (set -x; $(MKDIRHIER) ./play); fi $(INSTALL) -c $(INSTLIBFLAGS) llib-lfake.ln ./play/llib-lfake.ln # Invoke rule to depend sources depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend ed to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # platform-specific coWRPRC-2.11/examples/multiple/004077500017710000151000000000000634140472000175325ustar00junkyarddatamgmt00000400000027WRPRC-2.11/examples/README010064000017710000151000000002660634140472000165520ustar00junkyarddatamgmt00000400000027Not much here yet. What I will put here eventually is a single-directory project (1 Imakefile) and a multiple directory project (several Imakefiles) that you can use to practice on. WRPRC-2.11/examples/program010064000017710000151000000004720634140472000172630ustar00junkyarddatamgmt00000400000027To build a program, use BuildProgram(). You should also invoke DependTarget() so that "make depend" works properly. SRCS = program source files OBJS = program object files LIBS = link libraries needed DEPLIBS = dependency libraries BuildProgram(prog,$(SRCS),$(OBJS),$(LIBS),$(DEPLIBS)) DependTarget() WRPRC-2.11/examples/simple/004077500017710000151000000000000634140472000171705ustar00junkyarddatamgmt00000400000027WRPRC-2.11/examples/simple/Imakefile010064000017710000151000000002710634140472000207700ustar00junkyarddatamgmt00000400000027/* Simple Imakefile */ XCOMM "imboot -C WRPRC2" to build the Makefile. XCOMM If there's already a Makefile, you can use "make Bootstrap". BuildSimpleProgram(fakeprog,NullArg,NullArg) WRPRC-2.11/examples/simple/fakeprog.c010064000017710000151000000002020634140472000211130ustar00junkyarddatamgmt00000400000027# include int main (argc, argv) int argc; char **argv; { printf ("this program doesn't do much...\n"); return (0); } WRPRC-2.11/examples/simple/Makefile010064000017710000151000000261750634140472000206320ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $ # # The cpp used on this machine replaces all newlines and multiple tabs and # spaces in a macro expansion with a single space. Imake tries to compensate # for this, but is not always successful. # # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 93/06/30 # operating system: SunOS 4.1.1 # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system description parameters # Edit System.p-tmpl to change # ------------------------------------------------------------------------- # Standard system description parameters # Edit System.tmpl to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DVARARGS TOP = . CURRENT_DIR = . BINDIR = /usr/local USRLIBDIR = /usr/lib TMPDIR = /tmp ADMDIR = /usr/adm ETCDIR = /usr/etc INCLUDEROOT = /usr/include MANROOT = /usr/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MANLSUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) BOOTSTRAPCFLAGS = IMAKE = imake IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar clq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) PREPROCESSCMD = cc -E $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -C LINTOPTS = -axz LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RANLIB = ranlib RANLIBINSTFLAGS = RM = rm -f TAGS = ctags PERL = perl PERLPATH = /usr/local/perl STD_INCLUDES = STD_CPP_DEFINES = StandardCppDefines STD_DEFINES = EXTRA_LOAD_FLAGS = EXTRA_LIBRARIES = ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) CDEBUGFLAGS = -O CCOPTIONS = RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = install INSTSTRIP = -s INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0444 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTOWNER = INSTGROUP = INSTPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms # ------------------------------------------------------------------------- # project-specific configuration parameters # Edit Project.p-tmpl to change ########################################################################### # project-specific project group configuration parameters ########################################################################### # Section 1. Cpp symbols # Project identfication - name and release level # Project-specific system characteristics # Project-specific system directories and file locations # Project-specific include file directories # Configuration tools (files and directories) # Extra commands required # Extra libraries required ########################################################################### # Section 2. Makefile symbols; needs to be coordinated with Imake.tmpl # Project identfication - name and release level # Project-specific system characteristics # Project-specific system directories and file locations # Project-specific include file directories # Configuration tools (files and directories) # Extra commands required # Extra libraries required # ------------------------------------------------------------------------- # Standard project configuration parameters # Edit Project.tmpl to change # Configuration group identification - name and version CONFIGNAME = WRPRC2 CONFIGROOTDIR = $(USRLIBDIR)/config PUBCONFIGDIR = $(CONFIGROOTDIR)/$(CONFIGNAME) CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 00 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) # Project identfication - name and release level PRIVCONFIGDIR = $(TOP)/config PROJECTNAME = no-project-name PROJECTMAJORRELEASE = 0 PROJECTMINORRELEASE = 00 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) # Important local programs FIGEN = figen # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TSLIB = -ltokenscan DEPTSLIB = # Project-specific include file directories, definitions, and libraries INCLUDESRC = . LOCALINCLUDEINSTALLDIR = $(INCLUDEROOT)/local PROJECT_INCLUDES = -I$(INCLUDESRC) -I$(LOCALINCLUDEINSTALLDIR) PROJECT_DEFINES = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMAKE_DEFINES = MACROFILE = sun.cf IMAKE_CMD = $(IMAKE) -I$(NEWTOP)$(PRIVCONFIGDIR) -I$(PUBCONFIGDIR) \ $(IMAKE_DEFINES) IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # Simple Imakefile # "imboot -C WRPRC2" to build the Makefile. # If there's already a Makefile, you can use "make Bootstrap". SRCS = fakeprog.c OBJS = fakeprog.o all:: fakeprog fakeprog: $(OBJS) $(RM) $@ $(CC) -o $@ $(OBJS) $(LDOPTS) $(LDLIBS) clean:: $(RM) fakeprog lint:: lint.fakeprog lint.fakeprog: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) install:: i.fakeprog i.fakeprog:: fakeprog @if [ -d $(BINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(BINDIR)); fi $(INSTALL) -c $(INSTPROGFLAGS) fakeprog $(BINDIR)/fakeprog install.man:: i.fakeprog.man i.fakeprog.man:: fakeprog.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) -c $(INSTMANFLAGS) fakeprog.man $(MANDIR)/fakeprog.$(MANSUFFIX) depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) \#* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: -@if [ -f Makefile ]; then \ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ else exit 0; fi $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR) Bootstrap:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend WRPRC-2.11/R1-docs/004077500017710000151000000000000634140472000152715ustar00junkyarddatamgmt00000400000027WRPRC-2.11/R1-docs/config-WRPRC.ms010064000017710000151000000630060634140472000177660ustar00junkyarddatamgmt00000400000027.\" format with .\" ${TROFF} ${MSMACROS} this-file | ${PRINTER} .\" .\" C is a non-proportional font; if different at your site, change C .\" to something more appropriate. Then use .Cw to reference the font. .\" For in-line references, use \f\*(cW .fp 4 C \" this should be a non-proportional font .ds cW 4 .fp 5 CB \" this should be a non-proportional font .ds cB 5 .\" .\" revision date - change whenever this file is edited .ds Rd 28 August 1993 .\" document revision number - change each time document is released .ds Rn 1.05 .\" .nr PO 1.25i \" page offset 1.25 inches .nr PD .5v \" inter-paragraph distance .\" .EH 'Multiple-project \fIimake\fP'- % -'' .OH ''- % -'Multiple-project \fIimake\fP' .OF 'Revision date:\0\0\*(Rd''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(Rd''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .\" Ft - font reference .\" $1 = font to which to use for .ft switches .\" $2 = font for inline \f switches .\" $3 = thing to put in the given font .\" $4 = goes immediately after $3 .\" $5 = goes immediately before $4 .\" if $3-$5 are empty, simply switch font w/o switching back .de Ft .nr PQ \\n(.f .ie \(ts\\$3\\$4\\$5\(ts\(ts .ft \\$1 .el \&\\$5\\f\\$2\\$3\\f\\n(PQ\&\\$4 .. .\" .\" Cw - constant width font .de Cw .Ft \\*(cW \\*(cW "\\$1" "\\$2" "\\$3" .. .\" .\" Cb - constant bold font .de Cb .Ft \\*(cB \\*(cB "\\$1" "\\$2" "\\$3" .. .\" .\" I - italic font .de I .Ft I I "\\$1" "\\$2" "\\$3" .. .\" .\" B - bold font .de B .Ft B B "\\$1" "\\$2" "\\$3" .. .\" start of section of code .de cS .br .ie "\\$1"0" .DS "L" "\\$2" "\\$3" .el .DS "\\$1" "\\$2" "\\$3" .ps -2 .vs -2 .Cw .\" 8n doesn't work. How come? .\".ta 8n +8n +8n +8n +8n +8n +8n +8n +8n .nr Cw 8*\\w`n` .ta \\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu .rr Cw .. .\" end of section of code .de cE .ft R .vs +2 .ps +2 .br .DE .. .TL Using imake for Multiple Projects .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Document revision:\0\0\*(Rn Revision date:\0\0\*(Rd .NH Introduction .LP .I imake is a tool for generating Makefiles and is used to allow software projects to be configured easily on a wide variety of target machines. It is distributed with projects such as the X Window System and the Kerberos authentication system. The tool .I makedepend is typically used in conjunction with .I imake to generate .I Makefile dependencies. Another tool is used to bootstrap a .I Makefile from an .I Imakefile . This has traditionally been .I xmkmf ; a variant called .I imkmf is discussed here, too. .LP This document describes the use of .I imake to configure projects at the Wisconsin Regional Primate Research Center. The WRPRC configuration architecture allows multiple sets of configuration files to peacefully coexist on a single machine so that any of them can be applied to the configuration of an arbitrary number of distinct projects. It allows redundancy among project configurations to be exploited while providing for project-specific information which does not affect other projects. Information on obtaining these tools and configuration files is provided at the end of this document. .LP The method described here was patterned after the architecture of the configuration files used in the X Window System (version 11, release 4). This decision was made because that architecture was significantly more developed than that of either X11R3 or Kerberos (then at protocol revision 4). Since that time Kerberos V5 has been released (in beta) and its configuration too has been patterned after X11R4. X11R5 was released later yet; its architecture is essentially similar to that of X11R4. .LP A more-than-passing acquaintance with .I imake is assumed on the reader's part. Other documentation you might want to read includes ``Configuration Management in the X Window System'' by Jim Fulton (in .I mit/doc/config/usenixws/paper.ms from the X11 distribution) and the configuration and .I README files (in the .I mit/config directory). You should also be willing to look at the WRPRC configuration files firsthand. .NH Statement of Problem .LP .I imake is useful because it helps you keep system dependencies out of your source code and put them into a set of separate configuration files. The files are used to select, on a platform-specific basis, the proper configuration information for a particular system and to build Makefiles accordingly. Since .I make is assumed to be the main tool used to control a project's build process, reconfiguring the Makefiles for a different system amounts to running .I imake again, rather than having to edit all the Makefiles by hand. .LP Having discovered the flexibility .I imake provides as a configuration tool (once I figured out how to use it!), I began to use it on all my projects. Since these were all developed at the same site, the projects naturally had quite a bit of configuration information in common. At the same time, different projects had their own individual requirements. .LP The X11R4 project allows configuration files to be found either (a) in the .I config directory under the X top-level directory or (b) in a well-known system-wide location (e.g., .I /usr/lib/X11/config ). For my own projects I would have liked to adopt approach (b) and install a single set of system-wide configuration files and use them for all my projects. That wasn't suitable because the requirements for my projects tended to differ somewhat. Instead, I adopted approach (a) on a per-project basis: under each project's top-level directory I created a .I config directory and placed a full set of configuration files in it, modified as necessary for the project. .LP This was the brute force approach, of course, but it worked .\^.\^. sort of. It was most useful when moving a project to a .I different machine, since rebuilding the Makefiles to configure them on a per-machine basis was much easier. (That after all was the original purpose of .I imake ). The approach was less useful for sharing configuration information among projects on the .I same machine, because of the multiple sets of files: .IP \(bu There was a great deal of redundancy between these sets since projects were built and installed in similar ways. That was dissatisfactory because it seemed rather wasteful and silly not to take advantage of the overlap. .IP \(bu The many copies of files contributed to a certain amount of maintenance difficulty. For instance, if I decided to change the way a rule worked, and the rule was used in several projects, that meant changing the rules file for each of those projects. .LP The last result was somewhat paradoxical as .I imake is intended to reduce maintenance chores, not contribute to them. Evidently a boundary condition on .I imake 's capabilities was being reached, which led to two questions: how can the number of configuration files to be maintained be minimized, and how can configuration files be shared among projects without sacrificing the ability to specify project-specific information as necessary? .NH Solution to Problem .LP .I imake possesses the ability to look through multiple directories when looking for configuration files (via the .I \-I command line option), so to allow it to be used to configure multiple projects with the same set of files the simplest solution to the problem seemed to be: .IP \(bu Create a set of standard configuration files and store them in a well-known public location for any project's use. .IP \(bu Allow projects to define an alternate directory in which private project-specific configuration files can be placed. .IP \(bu Tell .I imake to look through the private project-specific directory first when searching for configuration files, then through the shared public directory for any files not found. .LP In this document .Cw PubConfigDir and .Cw PrivConfigDir denote the public and private configuration directories, respectively. .Cw PrivConfigDir is the .I config directory under the project's top-level directory, i.e., .Cw $(TOP)\fI/config\fP . .NH Implementation of Solution .LP This section describes the X11R4 configuration file architecture and how it was modified for multiple-project use. .NH 2 Imake.tmpl Architecture .LP The architecture of .I Imake.tmpl , the .I imake template used in X11R4 is, roughly: .LP .cS \fRvendor block section\fP #include <\fIplatform\fP.cf> \fR(platform-specific definitions)\fP #include \fR(site-specific definitions)\fP \fRsystem description, build definitions\fP #include \fR(project-specific definitions)\fP #include \fR(\fP\fIimake\fP\fR rules)\fP #include "./Imakefile" \fR(\fP\fIImakefile\fP\fR for current directory)\fP \fRdefault \fIMakefile\fP target entries\fP .cE .LP The vendor block section determines the machine type and the platform-specific file .I platform.cf to be included. Information in .I platform.cf controls the selection of configuration information from the other included files. .LP The X11R4 architecture can be modified to accommodate multiple projects. To do this, extra .Cw #include files are introduced into .I Imake.tmpl . The resulting modified architecture is shown below, with the new files in boldface: .LP .cS \fRvendor block section\fP .sp .2v \f(CB#include <\fP\fIplatform\fP\f(CB.pcf>\fP #include <\fIplatform\fP.cf> .sp .2v \f(CB#include \fP #include .sp .2v \fRsystem description, build definitions\fP .sp .2v \f(CB#include \fP #include .sp .2v \f(CB#include \fP #include .sp .2v #include "./Imakefile" \fRdefault \fIMakefile\fP target entries\fP .cE .LP This architecture differs from that used in X11R4 in the following respects: .IP \(bu The vendor block section now additionally determines the name of the project-specific platform file .I platform.pcf , not just .I platform.cf . For instance, the original and modified Sun vendor blocks look like this: .LP .cS .ta 2.5i \fBX11R4 vendor block Modified vendor block\fP .sp .2v #ifdef sun #ifdef sun #define MacroIncludeFile #define MacroIncludeFile #define MacroFile sun.cf #define MacroFile sun.cf #undef sun \f(CB#define ProjectMacroIncludeFile \fP #define SunArchitecture \f(CB#define ProjectMacroFile sun.pcf\fP #endif /* sun */ #undef sun #define SunArchitecture #endif /* sun */ .cE .IP \(bu .I Project.tmpl is renamed to .I ProjectGroup.tmpl to reflect that it applies to a group of projects, not a single project. .IP \(bu The template includes a number of additional files. This modification is based on the notion of override files. Before any of the platform, site, project-group or rules files are included, another related file is included which may contain project-specific information. Default versions of these project-specific files .I *.pcf , ( .I site.pdef , .I ProjectGroup.ptmpl and .I Imake.prules ) are present in .Cw PubConfigDir (to prevent .I cpp from issuing file-inclusion errors) but are all empty. When a given project has special configuration requirements, it supplies its own versions of any of these files in its private configuration directory, .Cw PrivConfigDir . Telling .I imake to search that directory before .Cw PubConfigDir causes the project-specific versions to be used, overriding the empty dummy versions. .LP The disadvantages of this architecture are obvious: .IP \(bu .I Imake.tmpl is more complex. .IP \(bu .Cw PubConfigDir must be populated with the additional .I *.pcf , .I site.pdef , .I ProjectGroup.ptmpl and .I Imake.prules files, although this is easy since they are all empty: .LP .cS % touch site.pdef % touch ProjectGroup.ptmpl % touch Imake.prules % ... .cE .LP The advantages are: .IP \(bu Configuration information is centralized. Multiple projects may use files in .Cw PubConfigDir cooperatively. .IP \(bu Flexibility is maintained. Changes can be made to the configuration of one project without affecting other projects, by specifying those changes in the project's private files. This contributes to configuration file stability, since the public files don't change just because a single project changes. .IP \(bu On the other hand, when changes (e.g., improvements, bug fixes) .I do need to be made to the public files, the changes are immediately available to any project using them via a normal configuration step, i.e.: .LP .cS % make Makefile % make Makefiles .cE .IP (Of course, it is prudent to exercise due caution \*- it becomes possible to break a lot of projects if an erroneous change is made.) .IP \(bu The number of configuration files referenced by .I Imake.tmpl is greater, but when multiple projects are maintained, the overall number of configuration files involved is smaller and less space is used since only one set of public files in needed. .IP \(bu The public configuration files need not be distributed with every project that uses them. They can be made into a separate distribution; only the project-specific configuration files need be distributed with projects that use the public files. .LP The philosophy underlying the architecture is that the public files .I Imake.tmpl , .I *.cf , .I site.def , .I ProjectGroup.tmpl and .I Imake.rules describe a common ``baseline'' or standard configuration, and individual projects need to specify configuration information using private .I *.pcf , .I site.pdef , .I ProjectGroup.ptmpl and .I Imake.prules files only to the extent that they .I differ from the standard. Thus, private override files minimize the need for individual projects to modify the baseline files directly. .LP Some of the ramifications of this architectural change include: .IP \(bu At the one extreme, when projects have no special project-specific configuration requirements (no .I config directory, or an empty one), only the files in .Cw PubConfigDir are used to create Makefiles. Since the default project-specific files are empty, the new architecture of .I Imake.tmpl is functionally equivalent to the old. At the other extreme, projects can supply .I all the configuration files if they wish so that only files in .Cw PrivConfigDir are used. .IP \(bu The public .I site.def file might be used by the system administrator to set the value of a macro such as .Cw BinDir to some public directory in which general access user programs are installed. Invocations of installation rules would then normally refer to the corresponding .I make variable .Cw BINDIR . If a project needs its programs installed somewhere else, this could be done by defining .Cw BinDir in the project-specific site file .I site.pdef to override the value in .I site.def . .IP \(bu Override files may also be used to extend the standard configuration by defining symbols not appearing at all in the public files. For instance, if some of a project's programs were to be installed in the public .Cw BinDir , but others were to be installed in a private directory, a symbol such as .Cw ProjBinDir could be defined for the latter purpose in .I ProjectGroup.ptmpl . .NH 2 Other Architecture-related Changes .LP The architecture change described above required modification of those things which cause .I imake to be executed, such as the configuration file definitions used to construct .I imake commands, and the procedure for bootstrapping a .I Makefile from an .I Imakefile . .NH 3 IMAKE_CMD .LP .I imake is invoked when ``make Makefile'' is performed, through the use of the .I Makefile variable .Cw IMAKE_CMD . The definition of this variable in the configuration file .I ProjectGroup.tmpl was changed. .LP .B Old (from X11R4): .cS #ifdef UseInstalled IRULESRC = $(CONFIGDIR) IMAKE_CMD = $(IMAKE) -DUseInstalled \e -I$(IRULESRC) \e $(IMAKE_DEFINES) #else IRULESRC = $(CONFIGSRC) IMAKE_CMD = $(NEWTOP)$(IMAKE) \e -I$(NEWTOP)$(IRULESRC) \e $(IMAKE_DEFINES) #endif .cE .\" allow page break here if necessary... .LP .B New : .cS #ifdef UseInstalled IMAKE_CMD = $(IMAKE) -DUseInstalled \e -I$(NEWTOP)$(PROJCONFIGDIR) -I$(GROUPCONFIGIR) \e $(IMAKE_DEFINES) #else IMAKE_CMD = $(NEWTOP)$(IMAKE) \e -I$(NEWTOP)$(PROJCONFIGDIR) -I$(GROUPCONFIGIR) \e $(IMAKE_DEFINES) #endif .cE .LP The old rule determines, based on whether .Cw UseInstalled is defined or not, whether to use a version of .I imake already installed in some public directory or build it in the source tree. That symbol also determines where to look for configuration files and defines the value of .Cw IRULESRC accordingly. If .Cw UseInstalled is undefined, searches look in .Cw CONFIGSRC , the project's .I config directory, otherwise in .Cw CONFIGDIR , the system-wide configuration directory. .LP This behavior is unsuitable for the purposes described here, since there are two directories which should be searched, if they exist. The new rule makes .Cw UseInstalled relevant only for determining where to find (and possibly build) .I imake , not where to look for configuration files. The file are always searched for in both places, which renders .Cw IRULESRC obsolete. .LP .Cw UseInstalled is typically relevant only for configuring the WRPRC configuration distribution itself, which must build .I imake and cannot assume it's already installed somewhere. Other projects most likely will be configured on the assumption that .I imake is publicly installed. .NH 3 Bootstrapping Makefiles \*- xmkmf and imkmf .LP .I xmkmf is used to bootstrap a .I Makefile from an .I Imakefile , but will not accommodate the two-directory-search scheme outlined above. To handle this, .I imkmf was developed, essentially as a copy of .I xmkmf modified to search .Cw PrivConfigDir and .Cw PubConfigDir , not just .Cw PubConfigDir . .LP The name .I imkmf was chosen to better reflect the .I imake -related function of the program; the name .I xmkmf reflects its X-specific orientation. .NH 2 Test of Implementation .LP After making the changes described above, a flight test was arranged. Nine projects developed under six different logins were converted to use the public files. Projects supplied override files where necessary. These projects were all initially developed using configuration files that bore a fairly strong relationship to the public set, so it was expected that conversion would not be unbearably odious. The degree of relationship broke down as follows: .IP \(bu Two projects used configuration files that were identical (or nearly so) to the public files. Each of these projects, unlike the other seven, comprised only a single source directory. As expected, conversion was completely trivial, once the top-level .I Makefile was rebuilt with .I imkmf . .IP \(bu Four projects required additional project-specific specification beyond the public configuration (special include file directories, link libraries, installation directories, etc.). These usually required only .I site.pdef and .I ProjectGroup.ptmpl files in their local .I config directories. One project required a .I platform.pcf file. Project owner and group names (used for install operations) were moved into .I site.pdef files from .I site.def files, which were then deleted from the sets of private configuration files. .IP \(bu Three projects diverged from the public files fairly significantly, because although their configuration files were initially set up from files similar to the public ones, less effort had been exerted to keep them in sync as project development progressed. As cladists would say, they developed autapomorphies.\** .FS Although most cladists might decline to attribute these to a designer. .FE Besides the changes made to the projects described in the previous paragraph, there were additional special commands for compilation, special .I Imakefile rules, etc. Nevertheless, conversion proceeded smoothly and without incident. .LP One thing I had done in my original .I Project.tmpl files was to define certain .I Makefile variables directly (e.g., .Cw INCLUDESRC=$(TOP)/h ), rather with the standard X11R4 technique of using a previously .Cw #define 'd .I cpp symbol (e.g., .Cw INCLUDESRC=IncludeSrc , where .Cw IncludeSrc is .Cw #define 'd within an .Cw #ifndef/#endif block). This was a short-cut that works in a non-shared environment but needed to be fixed to work in a shared environment. A default value of .Cw IncludeSrc was placed in .I ProjectGroup.tmpl , and individual projects redefine that symbol as necessary in .I ProjectGroup.ptmpl . .LP It was also necessary to place a number of .I cpp symbol definitions in .I ProjectGroup.tmpl within .Cw #ifndef/#endif blocks, since they became liable to being overridden in .I ProjectGroup.ptmpl . .LP Overall, conversion was reasonably simple and straightforward. I judged the ``conversion odiousness coefficient'' acceptably low. .NH Accommodating Multiple Groups of Projects .LP The architecture described so far allows a group of similarly-configured projects to share configuration files and selectively override or extend them as necessary. This provides a solution to the original problem (how to avoid maintaining multiple full sets of configuration files while maintaining flexibility), but leads to another. Suppose that instead of a group of projects, there exist several groups of projects, such that projects within a group are similar, but differences between groups are quite large. This can happen, for instance, if projects are installed that originated at several different sites. It is likely that developers at different sites will, at the least, use different sets of rules and test for different sets of system characteristics. .LP The difficulty here is that there are multiple sets of public configuration files, and they cannot all be installed in the same well-known location. This problem can be overcome quite simply. Instead of using .Cw PubConfigDir as the single well-known location in which the public files are installed, define that directory as .Cw PubConfigPath and use it as the root of a set of subdirectories, each of which corresponds to a set of configuration files. Each set of files is installed in the appropriate directory, and .Cw PubConfigDir for that set is defined in .I ProjectGroup.tmpl as that directory (e.g., .Cw PubConfigDir for group .I abc is .Cw PubConfigPath\fI/abc\fP ). .LP To allow .I imkmf to be used for bootstrapping, it was modified slightly again to allow selection of any of the configuration group subdirectories with a .I \-C option. For flexibility, the argument following .I \-C may be absolute or relative. If absolute, it is used unchanged. If relative, .Cw PubConfigPath is prepended. .LP .I imkmf as described has some significant differences from the .I xmkmf program distributed with X11R4. However, .I imkmf can be used in a way compatible with .I xmkmf and thus used to configure X projects. If the X configuration files are installed in .I /usr/lib/X11/config and the value of .Cw PubConfigPath is .I /usr/lib/config , the X11R4 configuration files can be linked into the directory structure used by .I imkmf : .LP .cS % cd /usr/lib/config % ln -s /usr/lib/X11/config X11 .cE .LP For sites without symbolic links, .I /usr/lib/config/X11 can be created as a regular directory into which the files from .I /usr/lib/X11/config are copied: .LP .cS % cd /usr/lib/config % mkdir X11 % cp /usr/lib/X11/config/* X11 .cE .LP Ugly, but workable. (Also known as ``crude, but effective.'') .LP With these conventions, projects within groups can share configuration files (as before), project groups can coexist peacefully, and WRPRC .I imkmf is compatible with the behavior of X11R4 .I xmkmf . .LP The nine projects previously converted were tested against these additional modifications. They required only the following to properly reset the configuration information in the Makefiles: .LP .cS % imkmf -C WRPRC % make Makefiles .cE .LP .I "\-C WRPRC" "" ( selects the standard Primate Center configuration files.) .NH Developing New Projects .NH 2 Describing the Configuration .LP If a new project has any special configuration requirements, create a .I config directory and specify those requirements in private configuration files. Also, create a .I README file explaining what they are. .NH 2 Distributing Your Project .LP The mechanism described in this document solves the problem of reusing configuration files while allowing for extension and override within individual projects. However, when a project is packaged for distribution, it's very little use to include only those configuration files which are unique to the project if the receiving site doesn't have the public files. It seems simplest to provide the public files as a separate distribution, along with the sources to the configuration tools. This is perhaps inconvenient for the recipient, as it is another distribution that needs to be retrieved. On the other hand, it only needs to be done once, and then it's not necessary to distribute all the configuration files with each project that uses them. .NH Distribution and Update Availability .LP The WRPRC configuration distribution may be freely circulated and is available for anonymous FTP access in the file .I ~ftp/pub/imake-stuff/config-WRPRC.tar.Z on host .I ftp.primate.wisc.edu . Updates appear there as they become available. .LP The WRPRC distribution illustrates the concepts discussed in this document. It also includes (modified) parts of the X11R4 .I mit/util source tree (where .I makedepend is found) as well as .I msub , a locally-developed utility for yanking the values of .I make variables out of Makefiles and using them to process templates to produce target files such as shell or .I perl scripts, help files that reflect local convention, etc. .LP The same directory contains the X11R4 configuration files, in .I config-X11R4.tar.Z . It might be instructive to compare them against the WRPRC files. There is also a paper describing the X11R4 configuration architecture in some detail. .LP If you do not have FTP access, send requests to .I software@primate.wisc.edu . Bug reports, questions, suggestions, and comments may be sent to this address as well. if .cE .\" allow page break here if necessary... .LP .B New : .cS #ifdef UseInstalled IMAKE_CMD = $(IMAKE) -DUseInstalled \e -I$(NEWTOP)$(PROJCONFIGDIR) -I$(GROUPCONFIGIR) \e $(IMAKE_DEFINES) #else IMAKE_CMD = $(NEWTOP)$(IMAKE) \e -I$(NEWTOP)$(PROJCONFIGDIR) -I$(GROUPCONFIGIR) \e $(IMAKE_DEFINES) #endif .cE .LP The old rule determines, based on whether .Cw UseInstalled is defined or not, whether to use a version of .I imake already installed in some public directory or build it in the sourceWRPRC-2.11/R1-docs/installation.ms010064000017710000151000000371550634140472000203350ustar00junkyarddatamgmt00000400000027.\" .\" ${SOELIM} this-file | ${TBL} | ${TROFF} ${MSMACROS} .\" .\" C is a non-proportional font; if different at your site, change C .\" to something more appropriate. Then use .Cw to reference the font. .\" For in-line references, use \f\*(cW .fp 4 C \" this should be a non-proportional font .ds cW 4 .fp 5 CB \" this should be a bold non-proportional font .ds cB 5 .\" .\" revision date - change whenever this file is edited .ds Rd 28 August 1993 .\" document revision number - change each time document is released .ds Rn 1.05 .\" .nr PO 1.25i \" page offset 1.25 inches .nr PD .5v \" inter-paragraph distance .\" .EH 'WRPRC Configuration Distribution'- % -'' .OH ''- % -'WRPRC Configuration Distribution' .OF 'Revision date:\0\0\*(Rd''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(Rd''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .\" Ft - font reference .\" $1 = font to which to use for .ft switches .\" $2 = font for inline \f switches .\" $3 = thing to put in the given font .\" $4 = goes immediately after $3 .\" $5 = goes immediately before $4 .\" if $3-$5 are empty, simply switch font w/o switching back .de Ft .nr PQ \\n(.f .ie \(ts\\$3\\$4\\$5\(ts\(ts .ft \\$1 .el \&\\$5\\f\\$2\\$3\\f\\n(PQ\&\\$4 .. .\" .\" Cw - constant width font .de Cw .Ft \\*(cW \\*(cW "\\$1" "\\$2" "\\$3" .. .\" .\" Cb - constant bold font .de Cb .Ft \\*(cB \\*(cB "\\$1" "\\$2" "\\$3" .. .\" .\" I - italic font .de I .Ft I I "\\$1" "\\$2" "\\$3" .. .\" .\" B - bold font .de B .Ft B B "\\$1" "\\$2" "\\$3" .. .\" start of section of code .de cS .br .ie "\\$1"0" .DS "L" "\\$2" "\\$3" .el .DS "\\$1" "\\$2" "\\$3" .ps -2 .vs -2 .Cw .\" 8n doesn't work. How come? .\".ta 8n +8n +8n +8n +8n +8n +8n +8n +8n .nr Cw 8*\\w`n` .ta \\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu .rr Cw .. .\" end of section of code .de cE .ft R .vs +2 .ps +2 .br .DE .. .TL WRPRC Configuration Project .sp .4v Installation Notes .AU Paul DuBois dubois@primate.wisc.edu .AI Wisconsin Regional Primate Research Center Document revision:\0\0\*(Rn Revision date:\0\0\*(Rd .LP .NH Introduction .LP This document describes how to install the WRPRC configuration distribution, which includes: .DS .I imake .I makedepend .I imkmf .I msub a set of general-purpose configuration files documentation .DE In addition, the following are also included if you need them on your system: .DS .I soelim .I mkdirhier .I bsdinst .DE The distribution is known to compile on the following systems: .DS VAX running Ultrix 3.1 Mips M/120 running RISC/os 4.01 (BSD or System V environments) SPARCstation 2 running SunOS 4.1.1 (Rev. B) .DE This release might run successfully on earlier or later versions of these systems; try it and see. Let me know. .LP This document doesn't motivate or justify the architecture of the configuration files. They are derived from those distributed with X11R4. The general philosophy underlying them is described in another document, .I "Using imake for Multiple Projects" (included in this distribution). .NH Distribution Layout .LP There are two main directories with which you should be concerned, .I config and .I util . The .I config directory contains configuration files and the source for .I imake . The .I util directory contains four subdirectories of interest: .I makedepend , the C source for the .I makedepend program; .I scripts , containing shell scripts for the script version of .I makedepend as well as for .I imkmf and some other miscellaneous things; .I msub , a program for generating scripts from templates using values of .I Makefile variables; and .I soelim , if one doesn't come with your version of UNIX. .NH Initial Configuration .LP If you've used .I imake before (e.g., to install the X Window System), you probably won't have much trouble installing the WRPRC configuration distribution. The way it builds itself is quite similar. Otherwise, be sure to read .I config/README very carefully and proceed with caution. .LP Every .I Makefile is generated by .I imake from an .I Imakefile in the same directory. There are also several other files used by .I imake which are found in .I config . Change into that directory and browse around. The files are: .LP .TS center tab(:); lfB lfB lfI lfI . Configuration-group Baseline Files:Dummy Project-specific Override Files Imake.tmpl:Imake.ptmpl ProjectGroup.tmpl:ProjectGroup.ptmpl *.cf:*.pcf site.def:site.pdef Imake.rules:Imake.prules .TE .LP .I Imake.tmpl contains overall configuration defaults describing your system. .I ProjectGroup.tmpl contains defaults for the group of projects configured with this set of configuration files. The .I *.cf files contain vendor-dependent defaults. .I Imake.rules contains rules for turning .I Imakefile definitions into .I Makefile dependencies. .LP The dummy override files supplied with the distribution are all empty, as they exist only to prevent file-inclusion errors. Individual projects may supply their own private versions of these files to override or extend the configuration information provided in the baseline files. .LP The only vendor-specific .I .cf files currently supported are .I mipsriscos.cf , .I sun.cf and .I ultrix.cf . The .I hp.cf file might work but it has seen only pre-``snake'' testing, and not much of that. .LP For advice on supporting other systems, take a look at .I config/Imake.tmpl . Also, the .I unsupported directory in .I config contains a number of other vendor files from the X11R4 distribution. These are included in case you want to compile the distribution on one of those systems, as a hint on how to start, but they will not work without modification. If you do this, please send me the .I .cf and .I .pcf files, as well as a description of any other changes you find necesssary. .LP If you want to read more about configuring software with .I imake , a paper which may be helpful is \fIUsing Imake to Configure the X Window System, Version 11, Release 4\fR, which discusses the issues involved in detail. This paper is available for anonymous FTP on .I ftp.primate.wisc.edu in the .I pub/imake-stuff directory. .LP If you can use one of the supported .I .cf files, you may only need to edit .I site.def. Take a look at it, and see what .I config/README says about it. Be sure to .B read the .I .cf file you plan to use; even if it requires no modification, you may need to set some environment or bootstrap variables. .NH The Build .LP Once all the above is done, change into the top-level source directory and, if you're intrepid, type the following command: .cS % make World BOOTSTRAPCFLAGS=\fIvalue\fR >& make.world & .cE .LP The value of .Cw BOOTSTRAPCFLAGS should be as follows: .LP SunOS 4.1.1: .cS % make World BOOTSTRAPCFLAGS= .cE Mips RISC/os 4.0, 4.01: .cS % make World BOOTSTRAPCFLAGS=-Dmipsriscos .cE Ultrix 3.1: .cS % make World BOOTSTRAPCFLAGS= .cE .LP Note: it is important to specify the value of .Cw BOOTSTRAPCFLAGS , even if it's empty. .LP A more modest approach is to do the build in stages, as follows (this is roughly what .I make .I World does): .LP Change into the configuration directory: .cS % cd config .cE Get .I imake to compile (read .I config/README first): .cS % make -f Makefile.ini BOOTSTRAPCFLAGS=\fIvalue\fR .cE If that works, edit .I site.def and (possibly) the .I .cf file, then: .cS % cd .. % make Makefile % make Makefiles % make clean .cE Build .I makedepend . If you define .Cw UseCCMakeDepend : .cS % cd ../util/scripts % make makedepend .cE If you don't: .cS % cd ../util/makedepend % make .cE Make sure .I makedepend works: .cS % cd ../.. % make depend .cE (After running .I make .I depend , look at some Makefiles to see if the header file dependencies look correct.) .sp .5v Build everything: .cS % make all .cE If you have problems, contact me for assistance. .NH Installation .LP Once everything builds properly, type .I make .I install to install the configuration files (you may need to become .I root first). Installation puts the configuration files into .I /usr/lib/config/WRPRC by default. All of the programs must be installed by hand: .I imake , .I imkmf , .I makedepend and .I msub . To install .I makedepend , you need to know whether the compiled version or the script version was built. Look at .I make.world to find out if you don't know. .LP .DS .ta 2i \fBProgram Where to find it\fR \fIimake\fP \fIconfig\fP \fImakedepend\fP \fIutil/makedepend\fP (or) \fIutil/scripts\fP (depending on which version gets built on your system) \fIimkmf\fP \fIutil/scripts\fP \fImsub\fP \fIutil/msub\fP .DE .LP If your system doesn't understand the .Cw #! '' `` mechanism for starting shell scripts, you may have to replace the first line of .I imkmf with a line that says .Cw : '' `` instead. Ditto for .I makedepend , if you use the script version. .LP If you have previously installed .I imake and/or .I makedepend (e.g., from the X Window System or Kerberos), you may not need to install the versions included with this release. However, it shouldn't hurt to do so. .LP Mips systems running RISC/os are weird; see notes later in this document for some installation suggestions. .NH Miscellaneous .NH 2 bsdinst .LP This is a compatibility script for systems without a BSD-style .I install program. You should install it if you have a System V-style .I install , because they behave differently. .NH 2 soelim .LP If your system doesn't have .I soelim and you want to use it, you can build and install a version using the source in .I util/soelim . .NH 2 xmkmf Compatibility .LP It is possible to set up the directory named by .Cw PubConfigPath so that .I imkmf can be used to configure other systems (i.e., rebuild the Makefiles) such as X11R4. This is done by making a link under .Cw PubConfigPath pointing to the installed X11R4 configuration files. Assuming .Cw PubConfigPath is .I /usr/lib/config and the X11R4 configuration files are installed under .I /usr/lib/X11/config , do the following: .LP .cS % cd /usr/lib/config % ln -s /usr/lib/X11/config X11 .cE .LP These steps establish the X11R4 configuration files as the default project group. You can then say run these command in the X11R4 top-level directory to build the X11 Makefiles: .LP .cS % imkmf -C X11 % make Makefiles .cE .LP It should be possible to do the same for other systems such as Kerberos V5 and Motif 1.1.2; unfortunately, the stock configuration files for each appear to assume, in slightly different ways, that they will not be used with .Cw UseInstalled defined. (That is, I think they are broken; easily fixed, but broken as distributed.) .LP .NH 2 Mips RISC/os Systems .LP You'll probably need to look at .I imakemdep.h and .I mipsriscos.cf in the .I config directory to understand this section. After you get done reading it, you may wonder why you'd even bother with all this messing around. The answer is that you mess with .I imake once, and then it helps you forever. Without .I imake you repeat your labors for each project. .LP Mips RISC/os supports program development under either the System V or BSD environments. It is desirable to compile the tools so that they support configuration for either environment. There are essentially two problems: (i) compiling .I imake ; (ii) compiling and using .I makedepend . .SH imake .LP There are a couple of approaches one might take for compiling .I imake : (i) compile it twice, once for each environment. It each case it would be compiled to pass .I \-Dmipsriscos (the trigger symbol) and also an environment type symbol to .I cpp so the correct information would be selected from the configuration files. (ii) compile a generic .I imake that passes only .I \-Dmipsriscos to .I cpp , but that can be told on the fly at configuration time which environment to use. .LP The problem in either case is how to specify the environment. RISC/os .I cc takes a .I \-systype option, so that you can specify .I "\-systype sysv" or .I "\-systype bsd43" to select an environment other than your default. These also cause the effect of .I \-DSYSTYPE_SYSV or .I \-DSYSTYPE_BSD43 . It seems likely that this mechanism could be used to compile .I imake . .LP However, the .I \-systype option can't be passed in .Cw BOOTSTRAPCFLAGS , since .I imake takes a .I \-s option, and it interprets .I \-systype to mean that output is to be written to a file named ``ystype''. Not so good. .Cw BOOTSTRAPCFLAGS is basically for .I \-D 's and .I \-U 's. How about passing the .Cw SYSTYPE_SYSV or .Cw SYSTYPE_BSD43 flags? No good, either. .I cc will defined one or the other of them anyway, even if you don't specify a .I \-systype to force which one. Thus, you might end up with both .Cw SYSTYPE_SYSV and .Cw SYSTYPE_BSD43 defined. That's not much help in compiling .I imake , or in getting .I imake to pass the right defines to .I cpp for selecting information from configuration files. .LP Nevertheless, it's possible to do an end run around this problem by using some other symbol. .Cw SYSV works well. If the project is built with .LP .cS % make World BOOTSTRAPCFLAGS="-Dmipsriscos -DSYSV" .cE .LP then a System V specific .I imake is compiled (one that always passes .I \-DSYSV to .I cpp ). This is probably what you should do if you always and only want to use the System V environment on your machine, and everyone else does, too. .LP If the project is built with .LP .cS % make World BOOTSTRAPCFLAGS=-Dmipsriscos .cE .LP then .I imake does not pass .I \-DSYSV to .I cpp and the BSD configuration information will be selected. This is probably what you should do if you always and only want to use the BSD environment on your machine, and everyone else does, too. .LP If you want to support a mixed environment, then compile for whichever one is most prevalent. To configure your Makefiles for a particular environment, rebuild them with .I imkmf . .LP For System V: .cS % imkmf -DSYSV -C WRPRC . % make Makefiles .cE For BSD: .cS % imkmf -USYSV -C WRPRC . % make Makefiles .cE .LP .I imkmf passes the SYSV argument to .I imake (which passes it to .I cpp ). .I mipsriscos.cf is set up to select the configuration environment based on whether SYSV is defined or not. .SH makedepend .LP There are two versions of .I makedepend ; a slow shell script version, and a fast compiled version. The shell script version works for either environment, but it's a pig. The compiled version can be compiled under either environment (by hacking .I util/makedepend/Imakefile ), but to make sure it .I works properly under either environment, it has to know the proper include-file hierarchy root. This means that the value of .Cw INCLUDEPATH must be passed to it, which is achieved by setting .Cw StandardIncludes to .Cw \fI\-I\fP$(INCLUDEPATH) . .NH 2 Some Changes From Previous Releases .SH Release 1.03 .LP There was no .I imkmf in releases of this project prior to 1.03. A modified version of .I xmkmf was used. If you installed that one, you can throw it away and reinstall the .I xmkmf distributed with X11R4. .LP On Mips RISC/os systems, the public configuration files were stored under .I /usr/lib/config or .I /bsd43/usr/lib/config , depending on the environment. Since the files can be used to configure projects either way (for either environment), there's no need to store them both places. Now .I /usr/lib/config is the default for both environments; you can toss any superfluous ones in .I /bsd43/usr/lib/config . .LP Also on Mips systems, it was previously recommended that the script version of .I makedepend be used for the System V environment, and the compiled version for the BSD environment, and that they be installed as .I makedepend.sysv and .I makedepend.bsd . The .I mipsriscos.cf file was set up to configure these names according to the configuration environment if .Cw UseInstalled was defined. That's all in the past; .I util/makedepend/Imakefile was hacked so that .I makedepend would compile under the System V environment (it wouldn't before). You can toss out any old versions of .I makedepend.sysv or .I makedepend.bsd . find necesssary. .LP If you want to read more about configuring software with .I imake , a paper which may be helpful is \fIUsing Imake to Configure the X Window System, Version 11, Release 4\fR, which discusses the issues involved in detail. This paper is available for anonymous FTP on .I ftp.primate.wisc.edu in the .I pub/imake-stuff directory. .LP If you can use one of the supported .I .cf files,WRPRC-2.11/R1-docs/Imakefile010064000017710000151000000004520634140472000170720ustar00junkyarddatamgmt00000400000027XCOMM This directory contains the main documents from Release 1 all:: @echo "You must say what you want to build" XCOMM Release 1 documents (out of date) TroffMsToPostScript(config-WRPRC.ps,config-WRPRC.ms,NullArg,NullArg) TroffMsToPostScript(installation.ps,installation.ms,|$(TBL),NullArg) WRPRC-2.11/R1-docs/Makefile010066400017710000151000000246250634140472000167370ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./R1-docs # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = no-project-name PROJECTMAJORRELEASE = 0 PROJECTMINORRELEASE = 00 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # This directory contains the main documents from Release 1 all:: @echo "You must say what you want to build" # Release 1 documents (out of date) config-WRPRC.ps:: config-WRPRC.ms $(SOELIM) config-WRPRC.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > config-WRPRC.ps clean:: $(RM) config-WRPRC.ps help_aux:: @echo "'make "config-WRPRC.ps"' to "format config-WRPRC.ps in PostScript installation.ps:: installation.ms $(SOELIM) installation.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > installation.ps clean:: $(RM) installation.ps help_aux:: @echo "'make "installation.ps"' to "format installation.ps in PostScript # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) WRPRC-2.11/R1-docs/README010064000017710000151000000010270634140472000161400ustar00junkyarddatamgmt00000400000027These documents are from Release 1.05 of the WRPRC imake configuration files. Since Release 2 has superceded Release 1, these documents are somewhat out of date. However, the essential concepts remain in use in Release 2, so they're are still useful reading. Note that the imkmf program described here is the original name of what is now known as imboot. The name imkmf was also used by the Khoros project, so sometime between Releases 1 and 2, the WRPRC imkmf was renamed to imboot. (Its capabilities were also extended somewhat.) WRPRC-2.11/R1-docs/R5-notes010064000017710000151000000043200634140472000166160ustar00junkyarddatamgmt00000400000027.bp .SH Appendix B \*- X11R5 Notes .LP X11R5 uses essentially the same architecture as X11R4, with two small changes. The platform-specific file is called the vendor-specific file, and the .I site.def file is included once before and once after the vendor-specific file: .LP .cS .ta 3i \fRvendor block section\fP .sp .2v #define BeforeVendorCF #include #undef BeforeVendorCF .sp .2v #include <\fIvendor\fR.cf> .sp .2v #define AfterVendorCF #include #undef AfterVendorCF .sp .2v \fRsystem description, build definitions\fP .sp .2v #include #include .sp .2v #include "./Imakefile" \fRdefault \fIMakefile\fP target entries\fP .cE .LP This allows .I site.def to be split into two sections to handle the case where site-specific definitions need to be known at the time the vendor file is included. It might have been simpler in some ways to include two different files. On the other hand, since instances in which the vendor file needs to know site-specific things tend to be rare, the before-vendor file would be empty much of the time. .LP The multiple-project architecture described in this document was patterned after the X11R4 architecture, but can easily be modified slightly to reflect the X11R5 changes. .LP .cS \fRvendor block section\fP .sp .2v #define BeforeVendorCF #include #include #undef BeforeVendorCF .sp .2v #include <\fIvendor\fR.pcf> #include <\fIvendor\fR.cf> .sp .2v #define AfterVendorCF #include #include #undef AfterVendorCF .sp .2v \fRsystem description, build definitions\fP .sp .2v #include #include .sp .2v #include #include .sp .2v #include "./Imakefile" .sp .2v \fRdefault \fIMakefile\fP target entries\fP .cE The .I site.def file is split in halves to conform to the BeforeVendorCF/AfterVendorCF usage. The default dummy .I site.pdef can be empty, but if you supply a version of .I site.pdef in a project's private configuration directory, it should not be empty. Rather, it should look like this: .LP .cS #ifdef BeforeVendorCF #endif .sp .2v #ifdef AfterVendorCF #endif .cE .LP I have found it more useful to have .I imkmf define .Cw UseInstalled by default. troffcvt-1.04.orig/tarballs/imboot-1.03.tar100644 1750 1750 144000 6431756100 16314 0ustar blpblpimboot-1.03/004077500017710000151000000000000632403366300144625ustar00junkyarddatamgmt00000400000027imboot-1.03/Imakefile010064400017710000151000000013660632401401000162550ustar00junkyarddatamgmt00000400000027/* * IMPORTANT: * Take a look at the extras.tmpl file and make any changes that * are appropriate for your system. */ #include "./extras.tmpl" XCOMM ---- imboot stuff ----- #if defined(Win32Architecture) || UsePerlImboot PerlScriptTarget(imboot,imboot.pl,NullParameter) #else AllTarget(ProgramTargetName(imboot)) CppScriptTarget(ProgramTargetName(imboot),imboot.cpp,-DCONFIGROOTDIR=$(CONFIGROOTDIR) -DRM='"$(RM)"' -DMV='"$(MV)"',NullParameter) install:: install.ProgramTargetName(imboot) InstallMultipleDestFlags(install.ProgramTargetName(imboot),ProgramTargetName(imboot),$(BINDIR),$(INSTBINFLAGS)) #endif AllTarget(imboot.man) CppFileTarget(imboot.man,imboot.man.cpp,-DCONFIGROOTDIR=$(CONFIGROOTDIR),NullParameter) InstallManPage(imboot,$(MANDIR)) imboot-1.03/Makefile010066400017710000151000000332700632403364400161230ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ---------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and # $XConsortium: Imake.tmpl /main/243 1996/11/13 14:42:56 lehors $ # all:: .SUFFIXES: .i # $XConsortium: Imake.cf /main/26 1996/09/28 16:05:09 rws $ # ----------------------------------------------------------------------- # site-specific configuration parameters that need to come before # the platform-specific parameters - edit site.def to change # site: $XConsortium: site.def /main/revisionist/4 1996/12/31 08:02:07 kaleb $ # ---------------------------------------------------------------------- # platform-specific configuration parameters - edit sun.cf to change # platform: $XConsortium: sun.cf /main/160 1996/12/26 08:52:18 kaleb $ # operating system: SunOS 5.5 Generic sun4u (5.5.0) # $XConsortium: svr4.cf /main/16 1996/09/28 16:13:41 rws $ # $XConsortium: sv4Lib.rules /main/18 1996/09/28 16:13:29 rws $ # ---------------------------------------------------------------------- # site-specific configuration parameters that go after # the platform-specific parameters - edit site.def to change # site: $XConsortium: site.def /main/revisionist/4 1996/12/31 08:02:07 kaleb $ # --------------------------------------------------------------------- # Imake rules for building libraries, programs, scripts, and data files # rules: $XConsortium: Imake.rules /main/217 1996/12/05 09:48:26 kaleb $ PATHSEP = / SHELL = /bin/sh TOP = . CURRENT_DIR = . IMAKE = imake DEPEND = makedepend MKDIRHIER = mkdirhier EXPORTLISTGEN = exportlistgen CONFIGSRC = $(TOP)/config IMAKESRC = $(CONFIGSRC)/imake DEPENDSRC = $(CONFIGSRC)/makedepend INCROOT = /usr/X11R6.3/include USRLIBDIR = /usr/X11R6.3/lib SHLIBDIR = /usr/X11R6.3/lib LINTLIBDIR = $(USRLIBDIR)/lint MANPATH = /usr/X11R6.3/man MANSOURCEPATH = $(MANPATH)/man MANDIR = $(MANSOURCEPATH)1 LIBMANDIR = $(MANSOURCEPATH)3 FILEMANDIR = $(MANSOURCEPATH)$(FILEMANSUFFIX) AR = /usr/ccs/bin/ar cq BOOTSTRAPCFLAGS = -DSVR4 CC = cc AS = /usr/ccs/bin/as COMPRESS = compress GZIP = gzip CPP = /usr/ccs/lib/cpp $(STD_CPP_DEFINES) PREPROCESSCMD = cc -E $(STD_CPP_DEFINES) INSTALL = /usr/ucb/install INSTALLFLAGS = -c LD = /usr/ccs/bin/ld LEX = /usr/ccs/bin/lex LEXLIB = -ll YACC = /usr/ccs/bin/yacc CCYACC = /usr/ccs/bin/yacc LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LN = ln -s MAKE = /usr/ccs/bin/make MV = mv CP = cp RM = rm -f MANSUFFIX = 1x LIBMANSUFFIX = 3x FILEMANSUFFIX = 4 TROFF = psroff NROFF = nroff MSMACROS = -ms MANMACROS = -man TBL = tbl EQN = eqn NEQN = neqn COL = col DVIPS = dvips LATEX = latex STD_INCLUDES = STD_CPP_DEFINES = -Dsun -DSVR4 $(PROJECT_DEFINES) STD_DEFINES = -Dsun -DSVR4 $(PROJECT_DEFINES) EXTRA_LOAD_FLAGS = EXTRA_LDOPTIONS = EXTRA_LIBRARIES = -lsocket -lnsl TAGS = ctags SHAREDCODEDEF = SHLIBDEF = SHLIBLDFLAGS = -G -z text PICFLAGS = -Kpic CXXPICFLAGS = -K PIC PROTO_DEFINES = INSTPGMFLAGS = INSTBINFLAGS = -m 0755 INSTUIDFLAGS = -m 4711 INSTLIBFLAGS = -m 0644 INSTINCFLAGS = -m 0444 INSTMANFLAGS = -m 0444 INSTDATFLAGS = -m 0444 INSTKMEMFLAGS = -g sys -m 2711 PROJECTROOT = /usr/X11R6.3 CDEBUGFLAGS = -O CCOPTIONS = -Xa ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(THREADS_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(THREADS_CFLAGS) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) $(DEPEND_DEFINES) LDPRELIB = -L$(USRLIBDIR) LDPOSTLIB = LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(EXTRA_LDOPTIONS) $(THREADS_LDFLAGS) $(LOCAL_LDFLAGS) $(LDPRELIBS) CXXLDOPTIONS = $(CXXDEBUGFLAGS) $(CXXOPTIONS) $(EXTRA_LDOPTIONS) $(THREADS_CXXLDFLAGS) $(LOCAL_LDFLAGS) $(LDPRELIBS) LDLIBS = $(LDPOSTLIBS) $(THREADS_LIBS) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) CCENVSETUP = LD_RUN_PATH=$(USRLIBDIRPATH) CCLINK = $(CCENVSETUP) $(CC) CXXENVSETUP = LD_RUN_PATH=$(USRLIBDIRPATH) CXXLINK = $(CXXENVSETUP) $(CXX) LDSTRIPFLAGS = -x LDCOMBINEFLAGS = -r DEPENDFLAGS = MACROFILE = sun.cf RM_CMD = $(RM) IMAKE_DEFINES = IRULESRC = $(CONFIGDIR) IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES) ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/X11.tmpl \ $(IRULESRC)/site.def $(IRULESRC)/$(MACROFILE) \ $(EXTRA_ICONFIGFILES) # $XConsortium: X11.rules /main/2 1996/12/04 10:13:00 swick $ # ---------------------------------------------------------------------- # X Window System Build Parameters and Rules # $XConsortium: X11.tmpl /main/290 1996/12/27 16:14:21 kaleb $ # ----------------------------------------------------------------------- # X Window System make variables; these need to be coordinated with rules XTOP = $(TOP) BINDIR = /usr/X11R6.3/bin BUILDINCROOT = $(TOP)/exports BUILDINCDIR = $(BUILDINCROOT)/include BUILDINCTOP = ../.. BUILDLIBDIR = $(TOP)/exports/lib BUILDLIBTOP = ../.. BUILDBINDIR = $(TOP)/exports/bin BUILDBINTOP = ../.. XBUILDINCROOT = $(XTOP)/exports XBUILDINCDIR = $(XBUILDINCROOT)/include/X11 XBUILDINCTOP = ../../.. XBUILDBINDIR = $(XBUILDINCROOT)/bin INCDIR = $(INCROOT) ADMDIR = /usr/adm LIBDIR = $(USRLIBDIR)/X11 TOP_X_INCLUDES = FONTDIR = $(LIBDIR)/fonts XINITDIR = $(LIBDIR)/xinit XDMDIR = $(LIBDIR)/xdm TWMDIR = $(LIBDIR)/twm XSMDIR = $(LIBDIR)/xsm NLSDIR = $(LIBDIR)/nls XLOCALEDIR = $(LIBDIR)/locale PEXAPIDIR = $(LIBDIR)/PEX LBXPROXYDIR = $(LIBDIR)/lbxproxy PROXYMANAGERDIR = $(LIBDIR)/proxymngr XPRINTDIR = $(LIBDIR) XAPPLOADDIR = $(LIBDIR)/app-defaults FONTCFLAGS = -t INSTAPPFLAGS = $(INSTDATFLAGS) RGB = rgb FONTC = bdftopcf MKFONTDIR = mkfontdir DOCUTILSRC = $(XTOP)/doc/util XDOCMACROS = $(DOCUTILSRC)/macros.t XIDXMACROS = $(DOCUTILSRC)/indexmacros.t PROGRAMSRC = $(TOP)/programs LIBSRC = $(XTOP)/lib FONTSRC = $(XTOP)/fonts INCLUDESRC = $(BUILDINCROOT)/include XINCLUDESRC = $(INCLUDESRC)/X11 SERVERSRC = $(XTOP)/programs/Xserver CONTRIBSRC = $(XTOP)/../contrib UNSUPPORTEDSRC = $(XTOP)/unsupported DOCSRC = $(XTOP)/doc RGBSRC = $(XTOP)/programs/rgb BDFTOPCFSRC = $(PROGRAMSRC)/bdftopcf MKFONTDIRSRC = $(PROGRAMSRC)/mkfontdir FONTSERVERSRC = $(PROGRAMSRC)/xfs FONTINCSRC = $(XTOP)/include/fonts EXTINCSRC = $(XTOP)/include/extensions TRANSCOMMSRC = $(LIBSRC)/xtrans TRANS_INCLUDES = -I$(TRANSCOMMSRC) XENVLIBDIR = $(USRLIBDIR) CLIENTENVSETUP = LD_LIBRARY_PATH=$(XENVLIBDIR) # $XConsortium: sunLib.tmpl /main/44 1996/12/09 16:34:30 kaleb $ ICONV_INBUF_DEFINE = -DICONV_INBUF_CONST=const # $XConsortium: sv4Lib.tmpl /main/23 1996/12/04 10:11:01 swick $ XMULIBONLY = -lXmu REGEXSYSLIB = -lgen DYNLIBSYSLIB = -ldl IAFSYSLIB = XLIBSRC = $(LIBSRC)/X11 SOXLIBREV = 6.1 DEPXONLYLIB = XONLYLIB = -lX11 LINTXONLY = $(LINTLIBDIR)/llib-lX11.ln XLIBONLY = $(XONLYLIB) XEXTLIBSRC = $(LIBSRC)/Xext SOXEXTREV = 6.3 DEPEXTENSIONLIB = EXTENSIONLIB = -lXext LINTEXTENSION = $(LINTLIBDIR)/llib-lXext.ln LINTEXTENSIONLIB = $(LINTEXTENSION) DEPXLIB = $(DEPEXTENSIONLIB) $(DEPXONLYLIB) XLIB = $(EXTENSIONLIB) $(XONLYLIB) LINTXLIB = $(LINTXONLYLIB) XAUTHSRC = $(LIBSRC)/Xau DEPXAUTHLIB = $(USRLIBDIR)/libXau.a XAUTHLIB = -lXau LINTXAUTH = $(LINTLIBDIR)/llib-lXau.ln XDMCPLIBSRC = $(LIBSRC)/Xdmcp DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a XDMCPLIB = -lXdmcp LINTXDMCP = $(LINTLIBDIR)/llib-lXdmcp.ln XMUSRC = $(LIBSRC)/Xmu SOXMUREV = 6.0 DEPXMULIB = XMULIB = -lXmu LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln OLDXLIBSRC = $(LIBSRC)/oldX SOOLDXREV = 6.0 DEPOLDXLIB = OLDXLIB = -loldX LINTOLDX = $(LINTLIBDIR)/llib-loldX.ln XPLIBSRC = $(LIBSRC)/Xp SOXPREV = 6.2 DEPXPLIB = XPLIB = -lXp LINTXP = $(LINTLIBDIR)/llib-lXp.ln TOOLKITSRC = $(LIBSRC)/Xt SOXTREV = 6.0 DEPXTOOLONLYLIB = XTOOLONLYLIB = -lXt LINTXTOOLONLY = $(LINTLIBDIR)/llib-lXt.ln DEPXTOOLLIB = $(DEPXTOOLONLYLIB) $(DEPSMLIB) $(DEPICELIB) XTOOLLIB = $(XTOOLONLYLIB) $(SMLIB) $(ICELIB) LINTXTOOLLIB = $(LINTXTOOLONLYLIB) XALIBSRC = $(LIBSRC)/Xa DEPvarLIB = $(USRLIBDIR)/libXa.a varLIB = -lXa LINTvar = $(LINTLIBDIR)/llib-lXa.ln AWIDGETSRC = $(LIBSRC)/Xaw SOXAWREV = 6.1 DEPXAWLIB = XAWLIB = -lXaw LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln XILIBSRC = $(LIBSRC)/Xi SOXINPUTREV = 6.0 DEPXILIB = XILIB = -lXi LINTXI = $(LINTLIBDIR)/llib-lXi.ln XTESTLIBSRC = $(LIBSRC)/Xtst SOXTESTREV = 6.1 DEPXTESTLIB = XTESTLIB = -lXtst LINTXTEST = $(LINTLIBDIR)/llib-lXtst.ln PEXLIBSRC = $(LIBSRC)/PEX5 SOPEXREV = 6.0 DEPPEXLIB = PEXLIB = -lPEX5 LINTPEX = $(LINTLIBDIR)/llib-lPEX5.ln XIELIBSRC = $(LIBSRC)/XIE SOXIEREV = 6.0 DEPXIELIB = XIELIB = -lXIE LINTXIE = $(LINTLIBDIR)/llib-lXIE.ln PHIGSLIBSRC = $(LIBSRC)/PHIGS DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a PHIGSLIB = -lphigs LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a XBSDLIB = -lXbsd LINTXBSD = $(LINTLIBDIR)/llib-lXbsd.ln ICESRC = $(LIBSRC)/ICE SOICEREV = 6.3 DEPICELIB = ICELIB = -lICE LINTICE = $(LINTLIBDIR)/llib-lICE.ln SMSRC = $(LIBSRC)/SM SOSMREV = 6.0 DEPSMLIB = SMLIB = -lSM LINTSM = $(LINTLIBDIR)/llib-lSM.ln XKEYSRC = $(LIBSRC)/Xkey SOXKEYREV = 6.0 DEPXKEYLIB = XKEYLIB = -lXkey LINTXKEY = $(LINTLIBDIR)/llib-lXkey.ln FSLIBSRC = $(LIBSRC)/FS DEPFSLIB = $(USRLIBDIR)/libFS.a FSLIB = -lFS LINTFS = $(LINTLIBDIR)/llib-lFS.ln FONTLIBSRC = $(LIBSRC)/font DEPFONTLIB = $(USRLIBDIR)/libfont.a FONTLIB = -lfont LINTFONT = $(LINTLIBDIR)/llib-lfont.ln XKBFILELIBSRC = $(LIBSRC)/xkbfile DEPXKBFILELIB = $(USRLIBDIR)/libxkbfile.a XKBFILELIB = -lxkbfile LINTXKBFILE = $(LINTLIBDIR)/llib-lxkbfile.ln XKBCOMPCMD = xkbcomp DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB) DEPLIBS1 = $(DEPLIBS) DEPLIBS2 = $(DEPLIBS) DEPLIBS3 = $(DEPLIBS) DEPLIBS4 = $(DEPLIBS) DEPLIBS5 = $(DEPLIBS) DEPLIBS6 = $(DEPLIBS) DEPLIBS7 = $(DEPLIBS) DEPLIBS8 = $(DEPLIBS) DEPLIBS9 = $(DEPLIBS) DEPLIBS10 = $(DEPLIBS) CONFIGDIR = $(LIBDIR)/config USRLIBDIRPATH = $(USRLIBDIR) LDPRELIBS = -L$(USRLIBDIR) LDPOSTLIBS = TOP_INCLUDES = -I$(INCROOT) $(TOP_X_INCLUDES) PROJECT_DEFINES = # ---------------------------------------------------------------------- # start of Imakefile CONFIGROOTDIR = /usr/local/lib/config PERLPATH = /usr/local/bin/perl MSUB = msub # ---- imboot stuff ----- all:: imboot imboot:: imboot.cpp $(RM) $@ $(CPP) -DCONFIGROOTDIR=$(CONFIGROOTDIR) -DRM='"$(RM)"' -DMV='"$(MV)"' $@ clean:: $(RM) imboot imboot:: chmod a+x $@ install:: install.imboot install.imboot:: imboot @if [ -d $(DESTDIR)$(BINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DESTDIR)$(BINDIR)); fi @for flag in ${MAKEFLAGS} ''; do \ case "$$flag" in *=*) ;; *[i]*) set +e;; esac; done; \ for i in imboot; do \ (set -x; $(INSTALL) $(INSTALLFLAGS) $(INSTBINFLAGS) $$i $(DESTDIR)$(BINDIR)); \ done all:: imboot.man imboot.man:: imboot.man.cpp $(RM) $@ $(CPP) -DCONFIGROOTDIR=$(CONFIGROOTDIR) $@ clean:: $(RM) imboot.man install.man:: imboot.man @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi $(INSTALL) $(INSTALLFLAGS) $(INSTMANFLAGS) imboot.man $(DESTDIR)$(MANDIR)/imboot.$(MANSUFFIX) # ---------------------------------------------------------------------- # common rules for all Makefiles - do not edit .c.i: $(RM) $@ $(CC) -E $(CFLAGS) $(_NOOP_) $*.c > $@ emptyrule:: clean:: $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut "#"* Makefile:: -@if [ -f Makefile ]; then set -x; \ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ else exit 0; fi $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR) tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS man_keywords:: catman -M $(DESTDIR)$(MANPATH) -w # ---------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS - do not edit install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" install.linkkit:: @echo "install.linkkit in $(CURRENT_DIR) done" Makefiles:: includes:: depend:: # ---------------------------------------------------------------------- # dependencies generated by makedepend DMDIR = $(LIBDIR)/xdm TWMDIR = $(LIBDIR)/twm XSMDIR = $(LIBDIR)/xsm NLSDIR = $(LIBDIR)/nls XLOCALEDIR = $(LIBDIR)/locale PEXAPIDIR = $(LIBDIR)/PEX LBXPROXYDIR = $(LIBDIR)/lbxproxy PROXYMANAGERDIR = $(LIBDIR)/proxymngr XPRINTDIR = $(LIBDIR) XAPPLOADDIR = $(LIimboot-1.03/Log010066400017710000151000000010260632403323500151150ustar00junkyarddatamgmt0000040000002711 Apr 93 V1.00 - Created. 02 Jun 93 V1.01 - Bug fixes. 02 Mar 96 V1.02 - Modified to check first for top/config/cf, then top/config if within-project configuration files are used. This is allows imboot to work within the X11R6 source tree, which changed the location of the configuration files relative to earlier X11 releases. 31 Mar 97 V1.03 - Created Perl version that can be used under Windows NT 12 Apr 97 - Eliminated "use of uninitialized variable" warning for imboot.pl under Windows NT. (Not fatal, but annoying.) imboot-1.03/README010064400017710000151000000154440632403351100153350ustar00junkyarddatamgmt00000400000027README for imboot Paul DuBois 12 April 1997 imboot is a bootstrapper for imake; it generates a Makefile from an Imakefile by passing appropriate arguments to imake. imboot is similar in nature to xmkmf, the imake bookstrapper for projects that use the X11 configuration files. However, imboot is not tied to any particular set of configuration files. Instead, you specify on the imboot command line which set of files you want to use: % imboot -c NAME (or) % imboot -C NAME imboot looks for a directory with the given name under the configuration root directory (typically /usr/local/lib/config) and tells imake to use the configuration files in that directory. imboot comes in sh or Perl versions. It runs on UNIX and Windows NT. Windows NT notes: - You can use the Perl version of imboot if you have NT Perl installed. - cp commands below would use copy, and chmod commands may be ignored. This README has the following sections: I) Building and installing imboot by hand II) Building and installing imboot using imake III) Using imboot ----------------------------------------------------------------------------- Section I. Building and installing imboot by hand Decide whether to use the sh or Perl version of imboot. Both are functionally equivalent. (Under Windows NT you must use the Perl version, but to do so you must have NT Perl installed.) To configure the sh version of imboot: 1) Copy imboot.cpp to imboot: % cp imboot.cpp imboot 2) Edit imboot, replacing all instances of XCOMM with # and all instances of CONFIGROOTDIR with /usr/local/lib/config (or with the full pathname of whatever directory you use for your configuration root). 3) Make imboot executable: % chmod a+x imboot 4) Install imboot in a location appropriate for your system. To configure the Perl version of imboot: 1) Copy imboot.pl to imboot: % cp imboot.pl imboot 2) Edit imboot, replacing $(PERLPATH) with the full patname to your Perl executable (either Perl 4 or Perl 5), and and $(CONFIGROOTDIR) with /usr/local/lib/config (or with the full pathname of whatever directory you use for your configuration root). 3) Make imboot executable: % chmod a+x imboot 4) (Windows NT only.) Convert imboot to a batch file imboot.bat: pl2bat imboot 5) Install imboot (or imboot.bat, for Windows NT) in a location appropriate for your system. To configure the manual page: 1) Copy imboot.man.cpp to imboot.man: % cp imboot.man.cpp imboot.man 2) Edit imboot.man, replacing all instances of XCOMM with # and all instances of CONFIGROOTDIR with /usr/local/lib/config (or with the full pathname of whatever directory you use for your configuration root). 3) Install imboot.man in a location appropriate for your system. ----------------------------------------------------------------------------- Section II. Building and installing imboot using imake If you have xmkmf, imake, msub, and the X11 configuration files, you can use the instructions in this section. To use the default configuration values, do this: % xmkmf Generate the Makefile % make clean Remove anything extraneous % make Build imboot and the manual page % make install Install imboot % make install.man Install the imboot manual page This will build the sh version of imboot, configure the configuration root directory as /usr/local/lib/config, and install imboot and its manual page in the X11 bin and manpage directories. To change the defaults, take a look at extras.tmpl and use the instructions below. 1) Find the line that sets the value of CONFIGROOTDIR: CONFIGROOTDIR = /usr/local/lib/config This is the imboot configuration root; it's the directory that holds the various sets of configuration files that imboot should know about. Each set of files is installed in its own directory under the configuration root. If you want to use a directory other than the one that's listed in the extras.tmpl file, change the value of CONFIGROOTDIR. (For Windows NT, you probably should make sure to add the drive letter of the partition in which you want to locate the directory.) 2) UNIX systems: If you want to use the sh version of imboot, the "#define UsePerlImboot" line should be commented out: /*#define UsePerlImboot YES*/ If you want to use the Perl version of imboot, the line should be uncommented: #define UsePerlImboot YES Then you should also make sure the value of PERLPATH is correct for your system. It can be the full pathname of either Perl 4 or Perl 5. 3) Windows NT systems: If you have the Windows NT version of Perl, you can use the Perl version of imboot. Uncomment the "#define WinNTHasPerl" line: #define WinNTHasPerl YES If you don't have Perl, the line should be commented out: /*#define WinNTHasPerl YES*/ 4) Build the Makefile, then build imboot and the manual page imboot.man: % xmkmf % make 5) Determine whether the installation directories for imboot and imboot.man are appropriate for your system: % make -n install % make -n install.man These commands show you where the Makefile will install the files. If the locations are suitable, install the files: % make install % make install.man Otherwise install the files by hand. imboot can be installed in any directory in your search path. Be sure to make the installed copy executable. ----------------------------------------------------------------------------- Section III. Using imboot If the configuration root directory has not been created on your system already, create it: % mkdir /usr/local/lib/config (or whatever pathname you're using) To install a set of configuration files for use with imboot, they need to have a name. Suppose they're called XYZ. Create a directory called XYZ under the configuration root directory for them to live in: % mkdir /usr/local/lib/config/XYZ Then copy the files into that directory. The next step is to make sure that the self-reference for the files is correct. That is, the configuration parameter that tells the files where they live needs to point to /usr/local/lib/config/XYZ. The self-reference is typically specified as the value of ConfigDir in one of the configuration files. You can either change the definition in the file where it's defined, or add a definition to site.def (which is perhaps preferable): #ifndef ConfigDir #define ConfigDir /usr/local/lib/config/XYZ #endif If the parameter that specifies the location is something other than ConfigDir, change the definition of that parameter instead. For a set of configuration files that is already located elsewhere, you may be able to hook it into the configuration root directory so that it can be used with imboot. For instance, if the X11R6.3 files are located in /usr/X11R6.3/lib/X11/config, you can make them useable with imboot like this: % ln -s /usr/X11R6.3/lib/X11/config /usr/local/lib/config/X11R6.3 Then these two commands become equivalent: % xmkmf % imboot -c X11R6.3 imboot-1.03/imboot.cpp010064400017710000151000000076370632370032600164630ustar00junkyarddatamgmt00000400000027XCOMM!/bin/sh XCOMM imboot - imake bootstrapper (bootstrap Makefile from Imakefile) XCOMM Usage: imboot [ flags ] [ topdir [ curdir ] ] XCOMM flags can be: XCOMM -c name specify name of configuration files XCOMM -C name specify name of configuration files, extensible XCOMM architecture XCOMM -Danything pass -Danything to imake XCOMM -Ianything pass -Ianything to imake XCOMM -d force UseInstalled on XCOMM -u force UseInstalled off XCOMM topdir = path to top of project tree (default ".") XCOMM curdir = path to current directory from top of project tree (default ".") XCOMM If no -c name or -C name option is given, configuration files from XCOMM the config directory under the project root (i.e., from topdir/config) XCOMM are used. UseInstalled is not defined. XCOMM If -c name is given, configuration files from CONFIGROOTDIR/name XCOMM are used instead of the files in topdir/config. UseInstalled is defined. XCOMM If -c name is given, configuration files from CONFIGROOTDIR/name XCOMM are used in conjunction with the files in topdir/config. UseInstalled XCOMM is defined. XCOMM For -c or -C, if name is an absolute path, CONFIGROOTDIR is not XCOMM prepended. XCOMM You can also specify other -D and -I flags, to allow arbitrary XCOMM symbols to be defined or undefined, or other search directories to XCOMM be given. XCOMM The -d and -u options may be used to force UseInstalled on or off, XCOMM overriding the default behavior. XCOMM 11 Apr 93 Paul DuBois dubois@primate.wisc.edu XCOMM 11 Apr 93 V1.00 XCOMM - Created. XCOMM 02 Jun 93 V1.01 XCOMM - Bug fixes. XCOMM 02 Mar 96 V1.02 XCOMM - Modified to check first for top/config/cf, then top/config if XCOMM within-project configuration files are used. This is allows XCOMM imboot to work within the X11R6 source tree, which changed the XCOMM location of the configuration files relative to earlier X11 releases. usage="usage: $0 [-c|-C name] [-d] [-u] [-Dsym] [-Idir] [topdir [curdir]]" configrootdir=CONFIGROOTDIR mv=MV rm=RM configname= topdir=. curdir=. dopt=n uopt=n args= XCOMM check for -c, -C, -D, -I, -d, -u options while [ $# -gt 0 ]; do case "$1" in -c) if [ $# -lt 2 ]; then echo "$usage" 1>&2 exit 1 fi configname=$2 shift;shift ;; -C) if [ $# -lt 2 ]; then echo "$usage" 1>&2 exit 1 fi configname=$2 useboth=y shift;shift ;; -d) # force UseInstalled on unconditionally dopt=y uopt=n shift ;; -u) # force UseInstalled off unconditionally dopt=n uopt=y shift ;; -[DI]*) # pass through -D, -I options args="$args $1" shift ;; -*) # unrecognized flag echo "imboot: unknown flag: $1" echo "$usage" 1>&2 exit 1 ;; *) # non-flag; quit flag processing break ;; esac done if [ $# -gt 0 ]; then topdir="$1" shift fi if [ $# -gt 0 ]; then curdir="$1" fi XCOMM find within-project configuration file directory, if there is one if [ -d "$topdir/config/cf" ]; then wpconfigdir="$topdir/config/cf" else wpconfigdir="$topdir/config" fi if [ "$configname" = "" ]; then useinstalled= configdir="-I$wpconfigdir" elif [ "$useboth" != "y" ]; then useinstalled=-DUseInstalled case "$configname" in /?*) configdir="-I$configname" ;; *) configdir="-I$configrootdir/$configname" ;; esac else useinstalled=-DUseInstalled case "$configname" in /?*) configdir="-I$wpconfigdir -I$configname" ;; *) configdir="-I$wpconfigdir -I$configrootdir/$configname" ;; esac fi XCOMM force UseInstalled on/off if -d/-u were given if [ "$dopt" = "y" ]; then useinstalled=-DUseInstalled fi if [ "$uopt" = "y" ]; then useinstalled= fi XCOMM backup current Makefile if it exists if [ -f Makefile ]; then echo $rm Makefile.bak $rm Makefile.bak echo $mv Makefile Makefile.bak $mv Makefile Makefile.bak fi XCOMM echo command, then run it echo imake $args $useinstalled $configdir -DTOPDIR=$topdir -DCURDIR=$curdir imake $args $useinstalled $configdir -DTOPDIR=$topdir -DCURDIR=$curdir imboot-1.03/imboot.man.cpp010064400017710000151000000075160632374303500172350ustar00junkyarddatamgmt00000400000027.TH IMBOOT 1 .\" .SH NAME imboot \- bootstrap a .I Makefile from an .I Imakefile .\" .SH SYNOPSIS .B imboot [ .B \-c .I name ] [ .B \-C .I name ] [ .BI \-D define ] [ .BI \-I dir ] [ .B \-d ] [ .B \-u ] [ .I topdir [ .I curdir ] ] .\" .SH DESCRIPTION .I imboot is a general-purpose .I imake bootstrapper for generating a .I Makefile from an .IR Imakefile . By default, .I imboot looks for configuration files in a private project-specific directory (i.e., located within the current project's source tree). The .I \-c (or .IR \-C ) option may be given to tell .I imboot to use a set of publicly installed configuration files instead of (or in addition to) any files in the project's private directory. .PP The private configuration file directory, if used, is taken to be .I config or .I config/cf at the top of the project source tree. .I config is the usual location, but by looking in .I config/cf as well, .I imboot works within the X11R6 source tree. The public configuration file directory will be one of those located under .IR CONFIGROOTDIR . The name of the directory is specified by the .I \-c and .I \-C options. .PP The .I topdir argument specifies the location of the project root. The default is ``\fB.\fP'' and thus may be omitted if the current directory is the project root. Otherwise it may be specified as an absolute pathname or as a path relative to the current directory. .IR curdir , if given, specifies the name of the current directory, relative to the project root. .I curdir is usually omitted. .\" .SH OPTIONS .I imboot understands the following options: .TP 8 .B "\-c \fIname\fP Use the named set of public configuration files instead of the files in the project's private configuration file directory. .TP 8 .B "\-C \fIname\fP Use the named set of public configuration files in addition to the files in the project's private configuration file directory. .I imboot tells .I imake to look in the private directory under the project root before looking in the public directory when searching for configuration files. The intent is to support an extensible configuration file architecture such that the public files define a baseline configuration that individual projects can extend or override by providing project-specific information in files in their private configuration file directory. .TP 8 .BI \-D define This option is passed directly to .IR imake , which passes it to .IR cpp . .TP 8 .BI \-I dir This option is passed directly to .IR imake , which passes it to .IR cpp . It can be used to specify additional directories in which to look to look for configuration files. .TP 8 .B \-d Force definition of UseInstalled. This is shorthand for .BR \-DUseInstalled , which is turned on automatically when you specify .I \-c or .IR \-C . .TP 8 .B \-u Force undefinition of UseInstalled. .PP For the .I \-c .I name or .I \-C .I name options, the .I name argument may also be an absolute pathname, in which case it is used as given for locating configuration files. .\" .SH EXAMPLES Suppose you want to use a set of public configuration files named XYZ. If you're in the root directory of a project, you can bootstrap a .I Makefile using the XYZ configuration files like this: .sp .5v .RS % imboot \-c XYZ .RE .sp .5v If you're in a subdirectory, say, .IR src/prog1 (two levels down), the location of the project root is .B ..\^/.. and you bootstrap the .I Makefile with: .sp .5v .RS % imboot \-c XYZ \fB..\^/..\fR .RE .sp .5v If the XYZ configuration files use an extensible architecture and your project has private configuration files in a .I config directory, you can use the private files as well. The commands just shown become: .sp .5v .RS .nf % imboot \-C XYZ % imboot \-C XYZ \fB..\^/..\fR .fi .RE .sp .5v .\" .SH "WHO-TO-BLAME" Paul DuBois, dubois@primate.wisc.edu .\" .SH "BUGS" It's difficult to get .B \-D or .B \-I arguments that require quotes passed through to .IR imake. imboot-1.03/.depend010066400017710000151000000005100632370032600157070ustar00junkyarddatamgmt00000400000027# DO NOT DELETE msub.o: /usr/include/stdio.h /usr/include/sys/types.h msub.o: /usr/include/sys/cdefs.h /usr/include/machine/endian.h msub.o: /usr/include/machine/ansi.h /usr/include/machine/types.h msub.o: /usr/include/ctype.h /usr/include/runetype.h /usr/include/sys/stat.h msub.o: /usr/include/sys/time.h /usr/include/time.h imboot-1.03/imboot.pl010066400017710000151000000074420632403324500163100ustar00junkyarddatamgmt00000400000027#!$(PERLPATH) # imboot - imake bootstrapper (bootstrap Makefile from Imakefile) # Usage: imboot [ flags ] [ topdir [ curdir ] ] # flags can be: # -c name specify name of configuration files # -C name specify name of configuration files, extensible # architecture # -Danything pass -Danything to imake # -Ianything pass -Ianything to imake # -d force UseInstalled on # -u force UseInstalled off # topdir = path to top of project tree (default ".") # curdir = path to current directory from top of project tree (default ".") # If no -c name or -C name option is given, configuration files from # the config directory under the project root (i.e., from topdir/config) # are used. UseInstalled is not defined. # If -c name is given, configuration files from "/usr/local/lib/config"/name # are used instead of the files in topdir/config. UseInstalled is defined. # If -c name is given, configuration files from "/usr/local/lib/config"/name # are used in conjunction with the files in topdir/config. UseInstalled # is defined. # For -c or -C, if name is an absolute path, "/usr/local/lib/config" is not # prepended. # You can also specify other -D and -I flags, to allow arbitrary # symbols to be defined or undefined, or other search directories to # be given. # The -d and -u options may be used to force UseInstalled on or off, # overriding the default behavior. # 11 Apr 93 Paul DuBois dubois@primate.wisc.edu # 11 Apr 93 V1.00 # - Created. # 02 Jun 93 V1.01 # - Bug fixes. # 02 Mar 96 V1.02 # - Modified to check first for top/config/cf, then top/config if # within-project configuration files are used. This is allows # imboot to work within the X11R6 source tree, which changed the # location of the configuration files relative to earlier X11 releases. # 31 Mar 97 V1.03 # - Modified to work under Windows NT ($prog = $0) =~ s|.*/||; # get script name for messages $usage="usage: $prog [-c|-C name] [-d] [-u] [-Dsym] [-Idir] [topdir [curdir]]"; $configrootdir = "$(CONFIGROOTDIR)"; $configname = ""; $topdir = "."; $curdir = "."; $dopt = "n"; $uopt = "n"; $useboth = "n"; $args = ""; # check for -c, -C, -D, -I, -d, -u options while (@ARGV && $ARGV[0] =~ /^-/) { $_ = shift (@ARGV); if (/^-[cC]$/) { die "$usage\n" unless @ARGV; $configname = shift (@ARGV); $useboth = "y" if $_ eq "-C"; } elsif ($_ eq "-d") # force UseInstalled on unconditionally { $dopt = "y"; $uopt = "n"; } elsif ($_ eq "-u") # force UseInstalled off unconditionally { $dopt = "n"; $uopt = "y"; } elsif (/^-[DI]/) # pass through -D, -I options { $args .= " $_"; } else # unrecognized flag { die "$prog: unknown flag: $_\n$usage\n"; } } $topdir = shift (@ARGV) if @ARGV; $curdir = shift (@ARGV) if @ARGV; # find within-project configuration file directory, if there is one if (-d "$topdir/config/cf") { $wpconfigdir = "$topdir/config/cf"; } else { $wpconfigdir = "$topdir/config"; } if ($configname eq "") { $useinstalled = ""; $configdir = "-I$wpconfigdir"; } elsif ($useboth ne "y") { $useinstalled = "-DUseInstalled"; if ($configname =~ m|^/\.|) { $configdir = "-I$configname"; } else { $configdir = "-I$configrootdir/$configname"; } } else { $useinstalled = "-DUseInstalled"; if ($configname =~ m|^/\.|) { $configdir = "-I$wpconfigdir -I$configname"; } else { $configdir = "-I$wpconfigdir -I$configrootdir/$configname"; } } # force UseInstalled on/off if -d/-u were given $useinstalled = "-DUseInstalled" if $dopt eq "y"; $useinstalled = "" if $uopt eq "y"; # back up current Makefile if it exists if (-f "Makefile") { print "rm Makefile.bak\n"; unlink "Makefile.bak"; print "mv Makefile Makefile.bak\n"; rename ("Makefile", "Makefile.bak"); } $cmd = "imake $args $useinstalled $configdir -DTOPDIR=$topdir -DCURDIR=$curdir"; # echo command, then run it print "$cmd\n"; system "$cmd"; imboot-1.03/extras.tmpl010066400017710000151000000053140632403506700166660ustar00junkyarddatamgmt00000400000027 /* * Change CONFIGROOTDIR if you are going to install imboot and the value * below is incorrect for your system. (You need to create the directory, * too, if it doesn't exist.) */ CONFIGROOTDIR = /usr/local/lib/config /* * For UNIX: * Change PERLPATH if perl is installed somewhere else on your system * Uncomment the UsePerlImboot #define below if you want to use the perl * version of imboot. Comment it out if you want to use the sh version. * Uncomment the UsePerlXmkmf #define below if you want to use the perl * version of xmkmf. Comment it out if you want to use the sh version. */ PERLPATH = /usr/local/bin/perl /*#define UsePerlImboot YES*/ /* * For WinNT: * If you have NT perl installed, you can build and use the imdent script * and the perl version of imboot. To do so, uncomment the next * WinNTHasPerl define below. (This requires that you have perl and pl2bat * in your path.) Comment out the #define if you don't have perl. */ #define WinNTHasPerl YES /* * Do not modify anything past this point */ MSUB = msub #ifndef UsePerlImboot #define UsePerlImboot NO #endif #ifndef UsePerlXmkmf #define UsePerlXmkmf NO #endif #ifndef WinNTHasPerl #define WinNTHasPerl NO #endif /* * PerlScriptTarget() creates a perl script by running a template through * msub. This works differently on UNIX and NT. * * For WinNT, the rule is a nop if perl is not available. Otherwise a * script xxx.pl is used to construct a batch script xxx.bat using the * following steps: * - build xxx from xxx.pl * - run pl2bat to build xxx.bat from xxx */ #ifndef PerlScriptTarget #ifdef Win32Architecture #if WinNTHasPerl #define PerlScriptTarget(dst,src,deps) @@\ AllTarget(dst.bat) @@\ dst.bat:: src deps @@\ ProgramTargetName($(MSUB:/=\)) src > dst @@\ pl2bat dst @@\ RemoveFile(dst) @@\ clean:: @@\ RemoveFile(dst.bat) @@\ install:: install.dst.bat @@\ InstallMultipleDestFlags(install.dst.bat,dst.bat,$(BINDIR),$(INSTBINFLAGS)) #else #define PerlScriptTarget(dst,src,deps) @@\ AllTarget(dst.bat) @@\ dst.bat:: @@\ @echo sorry, dst.bat cannot be built unless you have perl #endif /* WinNTHasPerl */ #else /* !Win32Architecture */ #define PerlScriptTarget(dst,src,deps) @@\ AllTarget(ProgramTargetName(dst)) @@\ ProgramTargetName(dst):: src deps @@\ ProgramTargetName($(MSUB)) src > ProgramTargetName(dst) @@\ chmod a+x ProgramTargetName(dst) @@\ clean:: @@\ RemoveFile(ProgramTargetName(dst)) @@\ install:: install.ProgramTargetName(dst) @@\ InstallMultipleDestFlags(install.ProgramTargetName(dst),ProgramTargetName(dst),$(BINDIR),$(INSTBINFLAGS)) #endif /* Win32Architecture */ #endif /* PerlScriptTarget */ imboot-1.03/imboot.html010066400017710000151000000116170632403366100166420ustar00junkyarddatamgmt00000400000027 IMBOOT manual page

IMBOOT manual page

Table of Contents


NAME

imboot - bootstrap a Makefile from an Imakefile

SYNOPSIS

imboot [ -c name ] [ -C name ] [ -Ddefine ] [ -Idir ] [ -d ] [ -u ] [ topdir [ curdir ] ]

DESCRIPTION

imboot is a general-purpose imake bootstrapper for generating a Makefile from an Imakefile. By default, imboot looks for configuration files in a private project-specific directory (i.e., located within the current project's source tree). The -c (or -C) option may be given to tell imboot to use a set of publicly installed configuration files instead of (or in addition to) any files in the project's private directory.

The private configuration file directory, if used, is taken to be config or config/cf at the top of the project source tree. config is the usual location, but by looking in config/cf as well, imboot works within the X11R6 source tree. The public configuration file directory will be one of those located under /usr/local/lib/config. The name of the directory is specified by the -c and -C options.

The topdir argument specifies the location of the project root. The default is "." and thus may be omitted if the current directory is the project root. Otherwise it may be specified as an absolute pathname or as a path relative to the current directory. curdir, if given, specifies the name of the current directory, relative to the project root. curdir is usually omitted.

OPTIONS

imboot understands the following options:
-c name
Use the named set of public configuration files instead of the files in the project's private configuration file directory.
-C name
Use the named set of public configuration files in addition to the files in the project's private configuration file directory. imboot tells imake to look in the private directory under the project root before looking in the public directory when searching for configuration files. The intent is to support an extensible configuration file architecture such that the public files define a baseline configuration that individual projects can extend or override by providing project-specific information in files in their private configuration file directory.
-Ddefine
This option is passed directly to imake, which passes it to cpp.
-Idir
This option is passed directly to imake, which passes it to cpp. It can be used to specify additional directories in which to look to look for configuration files.
-d
Force definition of UseInstalled. This is shorthand for -DUseInstalled, which is turned on automatically when you specify -c or -C.
-u
Force undefinition of UseInstalled.

For the -c name or -C name options, the name argument may also be an absolute pathname, in which case it is used as given for locating configuration files.

EXAMPLES

Suppose you want to use a set of public configuration files named XYZ. If you're in the root directory of a project, you can bootstrap a Makefile using the XYZ configuration files like this:
    % imboot -c XYZ
If you're in a subdirectory, say, src/prog1 (two levels down), the location of the project root is ../.. and you bootstrap the Makefile with:
    % imboot -c XYZ ../..
If the XYZ configuration files use an extensible architecture and your project has private configuration files in a config directory, you can use the private files as well. The commands just shown become:
    % imboot -C XYZ
    % imboot -C XYZ ../..

WHO-TO-BLAME

Paul DuBois, dubois@primate.wisc.edu

BUGS

It's difficult to get -D or -I arguments that require quotes passed through to imake.
troffcvt-1.04.orig/tarballs/msub-1.13.tar100644 1750 1750 223000 6431756100 15770 0ustar blpblpmsub-1.13/004077500017710000151000000000000632403333500141345ustar00junkyarddatamgmt00000400000027msub-1.13/Imakefile010064400017710000151000000007600632403334500157440ustar00junkyarddatamgmt00000400000027DEPLIBS = SimpleProgramTarget(msub) XCOMM "make test" to run a test XCOMM "make regression" to run the test, compare output with reference result #ifdef Win32Architecture test:: .\\ProgramTargetName(msub) .\\ProgramTargetName(msub) -f test.makefile testfile #else test:: ./ProgramTargetName(msub) ./ProgramTargetName(msub) -f test.makefile testfile #endif /* Win32Architecture */ regression:: ./ProgramTargetName(msub) ./ProgramTargetName(msub) -f test.makefile testfile | diff test.out - msub-1.13/imake.support010064400017710000151000000050630632055745300166670ustar00junkyarddatamgmt00000400000027Below is some sample configuration stuff showing how to incorporate msub support into your imake configuration files. 1) Put the following in Imake.tmpl or Project.tmpl to define an MSUB parameter: #ifndef MsubCmd #define MsubCmd msub #endif MSUB = MsubCmd 2) Add the following rules to Imake.rules. These actually are not msub-specific; they allow you to create scripts using templates by passing them through some arbitrary filter. To use them with msub, invoke them, e.g., like this: For non-executable script: ScriptFromTemplateTarget(script,template,$(MSUB),deps) For executable script (here, a shell script): ExecScriptFromTemplateTarget($(SHELL),dst,src,$(MSUB),deps) Note that AllTarget() generates an all:: target for its argument, StuffToClean() generates a clean:: target for its argument, and HasExecableScripts is equivalent to X11R6's ExecableScripts. If you don't have them, look at the end of this file. /* * Create a target by running a template through some filter. */ #ifndef ScriptFromTemplateTarget #define ScriptFromTemplateTarget(dst,src,command,deps) @@\ AllTarget(dst) @@\ StuffToClean(dst) @@\ dst:: src deps @@\ command src > $@ #endif /* * Create an executable target for some arbitrary program by running a * template through some filter. prog must be a full pathname. * * If the HasExecableScripts configuration parameter is not YES, make sure * the first line begins with a colon and write the script into a temp * file, have the program execute that, and remove the temp file when * done. Ugly ugly ugly. */ #ifndef ExecScriptFromTemplateTarget #if HasExecableScripts /* can use #! */ #define ExecScriptFromTemplateTarget(prog,dst,src,command,deps) @@\ AllTarget(dst) @@\ StuffToClean(dst) @@\ dst:: src deps @@\ $(RM) $@ @@\ echo "#!"prog > $@ @@\ command src >> $@ @@\ chmod a+x $@ #else #define ExecScriptFromTemplateTarget(prog,dst,src,command,deps) @@\ AllTarget(dst) @@\ StuffToClean(dst) @@\ dst:: src deps @@\ $(RM) $@ @@\ echo \: > $@ @@\ echo 'x=/tmp/xx$$$$' >> $@ @@\ echo "cat > "'$$x'" << 'EOF'" >> $@ @@\ command src >> $@ @@\ echo EOF >> $@ @@\ echo prog '$$x' '$$@' >> $@ @@\ echo $(RM) '$$x' >> $@ @@\ chmod a+x $@ #endif /* HasExecableScripts */ #endif /* ExecScriptFromTemplateTarget */ #ifndef StuffToClean #define StuffToClean(extra) @@\ clean:: @@\ $(RM) extra #endif /* StuffToClean */ #ifndef AllTarget #define AllTarget(depends) @@\ all:: depends #endif /* AllTarget */ msub-1.13/msub.c010064400017710000151000000332770632055745300152650ustar00junkyarddatamgmt00000400000027/* * msub - Read file(s) and perform substitutions using values of * variables defined in makefile. * * Syntax: msub [ -e ] [ -f makefile ] [ +Rstr -Rstr] [ file ... ] * * * -e Environment variables override makefile variables. * -f makefile Specify alternate makefile. Multiple -f options may * be given. * +Rstr Specify variable reference initiator string. * -Rstr Specify variable reference terminator string. * * +R and -R options must be given in pairs, although multiple pairs may * be specified. * * 27 Mar 1990 Paul DuBois dubois@primate.wisc.edu * * 27 Mar 1990 V1.0 * - Created. * 16 Apr 1993 V1.1 * - Rewritten. * 25 Oct 1993 V1.11 * - Added support for -e and var=value on command line. * 09 Mar 1996 V1.12 * - Coercion of arguments to Malloc() and read() to avoid coredump * on NetBSD systems. * 30 Mar 1997 V1.13 * - Under WinNT, the read() on the Makefile returns less than the requested * number of bytes if \r\n -> \n mapping is done, so make the failure test * less stringent. */ # ifdef WIN32 # include "X11/Xw32defs.h" # endif # include # include # include # include #define Malloc(n) _Malloc((int) n) # define bufSiz 2048 # define FromMakefile(vp) (vp->source == precMakefile) extern char *malloc (); extern char *strcpy (); extern char *strncpy (); extern char *strcat (); extern char *getenv (); typedef struct Var Var; struct Var { char *var; char *value; int expanded; int source; Var *next; }; static void ReadMake (); static int CheckAssignment (); static Var *AddVar (); static Var *FindVar (); static Var *FindVarUsingEnv (); static int FindVarRef (); static int FindEndVarRef (); static void Expand (); static void Substitute (); static char *_Malloc(); static char *NewString(); static void Panic (); static char *usage = "Usage: msub [ +Rstr -Rstr] [ -f makefile ] file"; static char *makefile = (char *) NULL; static Var *vvList = (Var *) NULL; static int nVars = 0; static char *mfRefInit[2] = { "${", "$(" }; static char *mfRefTerm[2] = { "}", ")" }; static char *usrRefInit[10]; static char *usrRefTerm[10]; static int usrRefSeqCnt = 0; static char **refInit; static char **refTerm; static int refSeqCnt; static int refInitIdx; static int varIdx; static int refTermIdx; static int restIdx; /* * Assignment source precedences. Command line assignments always override * assignments from Makefile or environment variable values. Normally * assignments with Makefiles override environment variables, but if -e is * specified on the command line, their precedences are reversed. */ static int precCmdLine = 3; static int precMakefile = 2; static int precEnvVar = 1; int main (argc, argv) int argc; char *argv[]; { FILE *f; Var *vp; char *p, *q; int pass; int needExpand; int toggle = 0; --argc; ++argv; while (argc > 0) { /* see if it's a var=value argument */ if (CheckAssignment (argv[0], precCmdLine)) { --argc; ++argv; continue; } /* if not, and it's not a flag, stop processing arguments */ if (argv[0][0] != '-' && argv[0][0] != '+') break; if (strcmp (argv[0], "-e") == 0) { int tmp; /* reverse precedence of makefile/env. assignments */ tmp = precMakefile; precMakefile = precEnvVar; precEnvVar = tmp; } else if (strcmp (argv[0], "-f") == 0) { if (argc < 2) Panic (usage); if ((f = fopen (makefile = argv[1], "r")) == (FILE *) NULL) Panic ("cannot open makefile argument"); ReadMake (f); (void) fclose (f); --argc; ++argv; } else if (strncmp (argv[0], "+R", 2) == 0) { if (toggle == 1) Panic ("missing -R argument after +R"); toggle = 1; if (strlen (argv[0]) == 2) Panic ("empty reference initiator specified"); usrRefInit[usrRefSeqCnt] = &argv[0][2]; } else if (strncmp (argv[0], "-R", 2) == 0) { if (toggle == 0) Panic ("missing +R argument before -R"); toggle = 0; if (strlen (argv[0]) == 2) Panic ("empty reference terminator specified"); usrRefTerm[usrRefSeqCnt] = &argv[0][2]; ++usrRefSeqCnt; } else Panic (usage); /* bad flag */ --argc; ++argv; } if (toggle == 1) Panic ("missing -R argument after +R"); if (usrRefSeqCnt == 0) /* no reference sequences specified */ { refInit = mfRefInit; refTerm = mfRefTerm; refSeqCnt = 2; } else { refInit = usrRefInit; refTerm = usrRefTerm; refSeqCnt = usrRefSeqCnt; } if (makefile == (char *) NULL) /* no -f options were given */ { if ((f = fopen ("makefile", "r")) == (FILE *) NULL) { if ((f = fopen ("Makefile", "r")) == (FILE *) NULL) Panic ("cannot open makefile or Makefile"); } ReadMake (f); (void) fclose (f); } /* Replace instances of '$$' with a single ^A */ /* (only for assignments from Makefile) */ for (vp = vvList; vp != (Var *) NULL; vp = vp->next) { if (!FromMakefile (vp)) continue; for (p = q = vp->value; *p != '\0'; p++, q++) { *q = *p; if (*p == '$' && *(p+1) == '$') { *q = '\01'; p++; } } *q = '\0'; } /* determine which variable values contain embedded references */ for (vp = vvList; vp != (Var *) NULL; vp = vp->next) { if (!FromMakefile (vp)) vp->expanded = 1; else vp->expanded = !FindVarRef (vp->value, 2, mfRefInit, mfRefTerm); } /* expand values to eliminate embedded references */ for (pass = 0; pass < nVars; pass++) { needExpand = 0; for (vp = vvList; vp != (Var *) NULL; vp = vp->next) { if (!vp->expanded) Expand (vp); if (!vp->expanded) needExpand = 1; } if (needExpand == 0) /* loop while values need expanding */ break; } /* sanity check: shouldn't have to make more than nVars passes */ if (pass >= nVars) Panic ("Too many expansion passes. Something's wrong!"); /* Replace instances of ^A with a '$' */ /* (only for assignments from Makefile) */ for (vp = vvList; vp != (Var *) NULL; vp = vp->next) { if (!FromMakefile (vp)) continue; for (p = vp->value; *p != '\0'; p++) { if (*p == '\01') *p = '$'; } } /* read source file(s) and perform substitutions */ if (argc == 0) Substitute (stdin); else while (argc > 0) { if ((f = fopen (*argv, "r")) == (FILE *) NULL) { (void) fprintf (stderr, "cannot open \"%s\".\n", *argv); Panic ("Quitting."); } Substitute (f); (void) fclose (f); --argc; ++argv; } return (0); } /* * Read a makefile, combine continuation lines (by joining lines with a space * and stripping leading whitespace on next line), null-terminate each line, * find variable assignments */ static void ReadMake (f) FILE *f; { struct stat st; int fd; char *p, *s; char *sNext; char *mfBuf; /* makefile buffer */ int i; fd = fileno (f); if (fstat (fd, &st) != 0) Panic ("cannot stat Makefile"); mfBuf = Malloc (st.st_size + 1); i = read (fd, mfBuf, (int) st.st_size); #ifdef WIN32 /* just test for reading > 0 bytes if file size is > 0 */ if (i <= 0 && st.st_size > 0) Panic ("cannot read Makefile"); #else if (i != st.st_size) Panic ("cannot read Makefile"); #endif mfBuf[st.st_size] = '\0'; /* make sure it's null-terminated */ p = s = mfBuf; while (s <= mfBuf + st.st_size) { if (*s == '\\' && *(s+1) == '\n') { *p++ = ' '; s += 2; /* skip continuation characters */ while (isspace (*s)) ++s; } else { if (*s == '\n') /* convert linefeeds to nulls */ *s = '\0'; *p++ = *s++; } } *p = '\0'; s = mfBuf; while (s <= p) { /* need sNext because CheckAssignment() modifies current line */ sNext = s + strlen (s) + 1; /* find next line */ (void) CheckAssignment (s, precMakefile); s = sNext; } free (mfBuf); /* done with Makefile; jettison it */ } /* * Determine whether the line contains a variable assignment, i.e., * an identifier, an equals sign, and optionally a value following. * * If the value contains a comment afterward, the comment becomes * part of the value. This is a bug, but it's too much trouble to * do the parsing necessary to find such things. Just don't use them. * * This is called to process assignments from command line arguments and * from the makefile. * * Return non-zero if assignment was found, zero otherwise. */ static int CheckAssignment (s, source) char *s; int source; { char name[bufSiz], *np; int len; while (isspace (*s)) /* skip whitespace */ ++s; if (!isalpha (*s) && *s != '_') /* no variable */ return (0); np = name; while (isalnum (*s) || *s == '_') *np++ = *s++; *np = '\0'; while (isspace (*s)) /* skip whitespace */ ++s; if (*s != '=') /* no '=' */ return (0); ++s; /* skip '=' */ while (isspace (*s)) /* skip whitespace */ ++s; /* take rest of line as definition after trimming trailing whitespace */ len = strlen (s); while (len > 0 && isspace (s[len-1])) s[--len] = '\0'; (void) AddVar (name, s, source); return (1); } static Var * FindVar (var) char *var; { Var *vp; for (vp = vvList; vp != (Var *) NULL; vp = vp->next) { if (strcmp (vp->var, var) == 0) return (vp); } return ((Var *) NULL); } /* * Find a variable and return pointer to Var structure. Never returns NULL. * If the variable isn't found, create an instance (either with an empty * value or the value from the environment variable of the same name if one * exists). If the variable is found and is from the makefile, override it * from the environment if environment variabless have higher precedence (i.e., * if -e was specified on the command line). */ static Var * FindVarUsingEnv (var) char *var; { Var *vp; char *val; if ((vp = FindVar (var)) == (Var *) NULL) { if ((val = getenv (var)) == (char *) NULL) val = ""; vp = AddVar (var, val, precEnvVar); } else if (FromMakefile (vp) && precMakefile < precEnvVar) { if ((val = getenv (var)) != (char *) NULL) vp = AddVar (var, val, precEnvVar); } return (vp); } static Var * AddVar (var, value, source) char *var, *value; int source; { Var *vp; if ((vp = FindVar (var)) == (Var *) NULL) { vp = (Var *) Malloc (sizeof (Var)); vp->var = NewString (var); vp->value = NewString (value); vp->source = source; vp->expanded = 0; vp->next = vvList; vvList = vp; ++nVars; } else if (vp->source <= source) /* exists; replace previous value if */ { /* new source has higher priority */ free (vp->value); vp->value = NewString (value); vp->source = source; } return (vp); } /* * Find a variable reference in a string. Return zero if no reference * found. Otherwise return non-zero and set four globals: * * refInitIdx index within s of beginning of reference initiator * varIdx index within s of beginning of variable * refTermIdx index within s of beginning of reference terminator * restIdx index within s of rest of string following reference */ static int FindVarRef (s, nRefSeqs, initRef, termRef) char *s; int nRefSeqs; char *initRef[]; char *termRef[]; { char *p, *pi; int len, i; p = s; while (*p != '\0') { /* look for reference initiation sequence */ for (i = 0; i < nRefSeqs; i++) { len = strlen (initRef[i]); if (strncmp (p, initRef[i], len) == 0 && FindEndVarRef (s, p-s+len, termRef[i])) { refInitIdx = p - s; varIdx = p - s + len; return (1); } } ++p; } return (0); } static int FindEndVarRef (s, idx, term) char *s; int idx; char *term; { char *p = s + idx; /* point to first char past reference initiator */ int len = strlen (term); if (!isalpha (*p) && *p != '_') /* no variable name present */ return (0); while (isalnum (*p) || *p == '_') { if (strncmp (p+1, term, len) == 0) { refTermIdx = p + 1 - s; restIdx = refTermIdx + len; return (1); } ++p; } return (0); } /* * Look for variable references in a variable value and expand them * when possible. If a variable is referenced that has not itself * been fully expanded, defer expansion until another pass, at which * time the referenced variable might then be expanded. This * prevents infinite expansions on circular references. */ static void Expand (vp) Var *vp; { Var *vp2; char buf[bufSiz * 4], *p; while (FindVarRef (vp->value, 2, mfRefInit, mfRefTerm)) { (void) strncpy (buf, vp->value+varIdx, refTermIdx-varIdx); buf[refTermIdx-varIdx] = '\0'; if ((vp2 = FindVarUsingEnv (buf)) != (Var *) NULL) { if (!vp2->expanded) return; /* can't substitute yet */ p = vp2->value; } else p = ""; /* substitute value for reference, replace value */ (void) strncpy (buf, vp->value, refInitIdx); (void) strcpy (buf+refInitIdx, p); (void) strcpy (buf+refInitIdx+strlen(p), vp->value+restIdx); free (vp->value); vp->value = NewString (buf); } vp->expanded = 1; /* no more embedded references */ } /* * Read through file, substituting variable values for variable * references. If a variable reference is found that is for an * unknown variable, substitute the empty string. * * This really should check write() return values... */ static void Substitute (f) FILE *f; { Var *vp; char buf[bufSiz * 4], name[bufSiz], *p; while (fgets (buf, (int) sizeof (buf), f) != (char *) NULL) { p = buf; while (FindVarRef (p, refSeqCnt, refInit, refTerm)) { (void) write (1, p, (int) refInitIdx); (void) strncpy (name, p+varIdx, refTermIdx-varIdx); name[refTermIdx-varIdx] = '\0'; if ((vp = FindVarUsingEnv (name)) != (Var *) NULL) (void) write (1, vp->value, (int) strlen (vp->value)); p += restIdx; } (void) write (1, p, (int) strlen (p)); } } /* * Allocate space. */ static char * _Malloc (size) int size; { char *p; if ((p = (char *) malloc ((size_t) size)) == (char *) NULL) Panic ("Malloc: out of space"); return (p); } /* * Allocate space for a string, copy the string into it, and return * a pointer to the copy. */ static char * NewString (s) char *s; { return (strcpy (Malloc (strlen (s) + 1), s)); } static void Panic (s) char *s; { (void) fprintf (stderr, "msub: %s\n", s); exit (1); } msub-1.13/msub.man010064400017710000151000000134300632374311200155730ustar00junkyarddatamgmt00000400000027.TH MSUB 1 .SH NAME msub \- substitute \fImake\fR variables into template to produce script .SH SYNOPSIS .B msub [ .B \-e ] [ .B \-f .I file ] [ .BI \+R str ] [ .BI \-R str ] [ .IB variable = value ] [ .I file \&... ] .SH DESCRIPTION Makefiles often contain project configuration information specified as .I make variables, and it is often desirable to make use of that information in other files. .I msub allows targets to be produced easily from templates that contain references to those variables. .I msub is particularly useful in software projects that use .IR imake because virtually all configuration parameters are written into Makefiles and are thus available for propagation into other files. .PP First .I msub reads the .I Makefile and finds all variable definition lines of the form ``\fIvar\fR = \fIvalue\fR''. Then .I msub reads any files named on the command line (or the standard input if none), looks for references to those variables, and replaces the references with the corresponding variable values. References to undefined variables are replaced by the empty string. The result is written to the standard output. .PP .I msub takes the following options: .TP .B \-e Environment variable values override assignments within Makefiles. Normally assignments within Makefiles override environment variables. .TP .BI \-f \ file By default, variable values are extracted from .I Makefile (or .I makefile if .I Makefile is missing) in the current directory. If the .B \-f .I file option is given, variable values are extracted from .I file instead. Multiple .B \-f options may be specified. (Note: .I make recognizes .B \-f\ \- to mean the .I Makefile should be read from .IR stdin . .I msub doesn't, because template input may come from .IR stdin .) .TP .BI +R str .TP .BI \-R str The default variable reference indicators within templates are the same as in Makefiles, i.e., ``$('' and ``)'', and ``${'' and ``}''. These can be changed with the .B +R and .B \-R options, which must be specified in pairs. .B +R specifies the string that initiates a variable reference and .B \-R specifies the string that terminates it. Multiple pairs of reference indicators may be given. .TP .IB variable = value Variable definition. This definition overrides any regular definition for the specified variable within the makefile itself or in the environment. .SH EXAMPLES Suppose you want to produce for a program a help file that indicates the local e-mail address to which questions may be directed. If this address is specified as the variable EMAILHELPADDR in the .IR Makefile , you can write a template .I helpfile.msub like this: .sp .5v .RS .nf \&.\|.\|.\|\fIstuff\fP\|.\|.\|. Please direct questions to ${EMAILHELPADDR}. \&.\|.\|.\|\fImore stuff\fP\|.\|.\|. .fi .RE .sp .5v Process the template to produce the help file like this: .sp .5v .RS msub helpfile.msub > helpfile .RE .sp .5v If the .I Makefile contains the following lines: .sp .5v .RS .nf EMAILHELPADDR = postmaster@$(DOMAIN) DOMAIN = primate.wisc.edu .fi .RE .sp .5v then .I helpfile will look like this: .sp .5v .RS .nf \&.\|.\|.\|\fIstuff\fP\|.\|.\|. Please direct questions to postmaster@primate.wisc.edu. \&.\|.\|.\|\fImore stuff\fP\|.\|.\|. .fi .RE .sp .5v .I msub can produce executable scripts, too. If the processor for which you're producing the script allows variable references, make sure you refer to .I make variables in the template in a different way than the processor refers to variables. For instance, ``${\fIvar\fP}'' is ambiguous in a shell script template \- is it a reference to a shell variable that you want .I msub to leave alone, or to a .I make variable for which you want .I msub to substitute the variable's value? To resolve the ambiguity, you can refer to shell variables as ``$\fIvar\fP'' (which the shell recognizes, but .I msub doesn't), or you can use different indicators than the defaults to refer to .I make variables in the template. For example, you could use ``@<'' and ``>@'' and refer to variables as ``@<\fIvar\fP>@''. Suppose you have a simple shell script to print your home directory pathname. You might write it like this: .sp .5v .RS .nf #!@@ echo ${HOME} .fi .RE .sp .5v Then you can process the template like this (note that you must quote the arguments because ``<'' and ``>'' are special to the shell): .sp .5v .RS msub +R"@<" \-R">@" template > script .RE .sp .5v The .B +R/\-R arguments cause .I msub to recognize ``@@'' but not ``${HOME}''. The result looks like this: .sp .5v .RS .nf #!/bin/sh echo ${HOME} .fi .RE .\" .SH "WHO-TO-BLAME" Paul DuBois, dubois@primate.wisc.edu .SH "BUGS AND RESTRICTIONS" CC, YACC, etc., have implicit values in .I make even if they're not defined in the .IR Makefile , which isn't true for .IR msub . However, when .I msub is used with .IR imake , this isn't normally a problem since .IR imake -generated Makefiles tend to contain explicit definitions for every parameter in the known universe. .PP .I msub is more restrictive in the variable names it recognizes and performs substitutions on than .IR make . .I make allows single character names to be referenced as ``$\fIc\fP'', where .I c is a letter; .I msub doesn't. .I msub also ignores .I make variables like ``$*'' and ``$@''. .PP Recursive references in .I Makefile variables aren't expanded. If a .I Makefile contains the definition ``X = ${X}'', X won't be expanded. Indirectly recursive references aren't expanded, either. If a .I Makefile contains the definitions ``X = ${Y}'' and ``Y = ${X}'', neither X nor Y will be expanded. (These actually aren't bugs in .IR msub , they're problems in the .IR Makefile .) .PP A comment at the end of a variable assignment line become part of the variable's value. If .I Makefile contains the following line: .sp .5v .RS SHELL = /bin/shell # default shell .RE then .I msub takes the value of SHELL to be ``/bin/shell # default shell''. msub-1.13/test.makefile010064400017710000151000000002650632055745300166200ustar00junkyarddatamgmt00000400000027foo = ${bar} bar = ${ugh} ugh = Huh? space = x a = ${wildcard x} c : ${xyz} xyz = abc dollar = $$ doubledollar = ${dollar}${dollar} X1 = Y X2 = 1 Y1 = y1 Y2 = ${${X1}${X2}} msub-1.13/test.out010064400017710000151000000003330632055745300156460ustar00junkyarddatamgmt00000400000027foo = Huh? bar = Huh? ugh = Huh? xy ${wildcard x} The stuff in parens should be "abc": (abc) This should be a single dollar-sign: $ This should be a double dollar-sign: $$ So should this: $$ This should say "y1": y1 msub-1.13/testfile010064400017710000151000000004120632055745300156760ustar00junkyarddatamgmt00000400000027foo = ${foo} bar = ${bar} ugh = ${ugh} ${space}y ${a} The stuff in parens should be "abc": (${xyz}) This should be a single dollar-sign: ${dollar} This should be a double dollar-sign: ${dollar}${dollar} So should this: ${doubledollar} This should say "y1": ${Y2} msub-1.13/Makefile010066400017710000151000000327670632403332500156070ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ---------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and # $XConsortium: Imake.tmpl /main/243 1996/11/13 14:42:56 lehors $ # all:: .SUFFIXES: .i # $XConsortium: Imake.cf /main/26 1996/09/28 16:05:09 rws $ # ----------------------------------------------------------------------- # site-specific configuration parameters that need to come before # the platform-specific parameters - edit site.def to change # site: $XConsortium: site.def /main/revisionist/4 1996/12/31 08:02:07 kaleb $ # ---------------------------------------------------------------------- # platform-specific configuration parameters - edit sun.cf to change # platform: $XConsortium: sun.cf /main/160 1996/12/26 08:52:18 kaleb $ # operating system: SunOS 5.5 Generic sun4u (5.5.0) # $XConsortium: svr4.cf /main/16 1996/09/28 16:13:41 rws $ # $XConsortium: sv4Lib.rules /main/18 1996/09/28 16:13:29 rws $ # ---------------------------------------------------------------------- # site-specific configuration parameters that go after # the platform-specific parameters - edit site.def to change # site: $XConsortium: site.def /main/revisionist/4 1996/12/31 08:02:07 kaleb $ # --------------------------------------------------------------------- # Imake rules for building libraries, programs, scripts, and data files # rules: $XConsortium: Imake.rules /main/217 1996/12/05 09:48:26 kaleb $ PATHSEP = / SHELL = /bin/sh TOP = . CURRENT_DIR = . IMAKE = imake DEPEND = makedepend MKDIRHIER = mkdirhier EXPORTLISTGEN = exportlistgen CONFIGSRC = $(TOP)/config IMAKESRC = $(CONFIGSRC)/imake DEPENDSRC = $(CONFIGSRC)/makedepend INCROOT = /usr/X11R6.3/include USRLIBDIR = /usr/X11R6.3/lib SHLIBDIR = /usr/X11R6.3/lib LINTLIBDIR = $(USRLIBDIR)/lint MANPATH = /usr/X11R6.3/man MANSOURCEPATH = $(MANPATH)/man MANDIR = $(MANSOURCEPATH)1 LIBMANDIR = $(MANSOURCEPATH)3 FILEMANDIR = $(MANSOURCEPATH)$(FILEMANSUFFIX) AR = /usr/ccs/bin/ar cq BOOTSTRAPCFLAGS = -DSVR4 CC = cc AS = /usr/ccs/bin/as COMPRESS = compress GZIP = gzip CPP = /usr/ccs/lib/cpp $(STD_CPP_DEFINES) PREPROCESSCMD = cc -E $(STD_CPP_DEFINES) INSTALL = /usr/ucb/install INSTALLFLAGS = -c LD = /usr/ccs/bin/ld LEX = /usr/ccs/bin/lex LEXLIB = -ll YACC = /usr/ccs/bin/yacc CCYACC = /usr/ccs/bin/yacc LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LN = ln -s MAKE = /usr/ccs/bin/make MV = mv CP = cp RM = rm -f MANSUFFIX = 1x LIBMANSUFFIX = 3x FILEMANSUFFIX = 4 TROFF = psroff NROFF = nroff MSMACROS = -ms MANMACROS = -man TBL = tbl EQN = eqn NEQN = neqn COL = col DVIPS = dvips LATEX = latex STD_INCLUDES = STD_CPP_DEFINES = -Dsun -DSVR4 $(PROJECT_DEFINES) STD_DEFINES = -Dsun -DSVR4 $(PROJECT_DEFINES) EXTRA_LOAD_FLAGS = EXTRA_LDOPTIONS = EXTRA_LIBRARIES = -lsocket -lnsl TAGS = ctags SHAREDCODEDEF = SHLIBDEF = SHLIBLDFLAGS = -G -z text PICFLAGS = -Kpic CXXPICFLAGS = -K PIC PROTO_DEFINES = INSTPGMFLAGS = INSTBINFLAGS = -m 0755 INSTUIDFLAGS = -m 4711 INSTLIBFLAGS = -m 0644 INSTINCFLAGS = -m 0444 INSTMANFLAGS = -m 0444 INSTDATFLAGS = -m 0444 INSTKMEMFLAGS = -g sys -m 2711 PROJECTROOT = /usr/X11R6.3 CDEBUGFLAGS = -O CCOPTIONS = -Xa ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(THREADS_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(THREADS_CFLAGS) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) $(DEPEND_DEFINES) LDPRELIB = -L$(USRLIBDIR) LDPOSTLIB = LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(EXTRA_LDOPTIONS) $(THREADS_LDFLAGS) $(LOCAL_LDFLAGS) $(LDPRELIBS) CXXLDOPTIONS = $(CXXDEBUGFLAGS) $(CXXOPTIONS) $(EXTRA_LDOPTIONS) $(THREADS_CXXLDFLAGS) $(LOCAL_LDFLAGS) $(LDPRELIBS) LDLIBS = $(LDPOSTLIBS) $(THREADS_LIBS) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) CCENVSETUP = LD_RUN_PATH=$(USRLIBDIRPATH) CCLINK = $(CCENVSETUP) $(CC) CXXENVSETUP = LD_RUN_PATH=$(USRLIBDIRPATH) CXXLINK = $(CXXENVSETUP) $(CXX) LDSTRIPFLAGS = -x LDCOMBINEFLAGS = -r DEPENDFLAGS = MACROFILE = sun.cf RM_CMD = $(RM) IMAKE_DEFINES = IRULESRC = $(CONFIGDIR) IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES) ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/X11.tmpl \ $(IRULESRC)/site.def $(IRULESRC)/$(MACROFILE) \ $(EXTRA_ICONFIGFILES) # $XConsortium: X11.rules /main/2 1996/12/04 10:13:00 swick $ # ---------------------------------------------------------------------- # X Window System Build Parameters and Rules # $XConsortium: X11.tmpl /main/290 1996/12/27 16:14:21 kaleb $ # ----------------------------------------------------------------------- # X Window System make variables; these need to be coordinated with rules XTOP = $(TOP) BINDIR = /usr/X11R6.3/bin BUILDINCROOT = $(TOP)/exports BUILDINCDIR = $(BUILDINCROOT)/include BUILDINCTOP = ../.. BUILDLIBDIR = $(TOP)/exports/lib BUILDLIBTOP = ../.. BUILDBINDIR = $(TOP)/exports/bin BUILDBINTOP = ../.. XBUILDINCROOT = $(XTOP)/exports XBUILDINCDIR = $(XBUILDINCROOT)/include/X11 XBUILDINCTOP = ../../.. XBUILDBINDIR = $(XBUILDINCROOT)/bin INCDIR = $(INCROOT) ADMDIR = /usr/adm LIBDIR = $(USRLIBDIR)/X11 TOP_X_INCLUDES = FONTDIR = $(LIBDIR)/fonts XINITDIR = $(LIBDIR)/xinit XDMDIR = $(LIBDIR)/xdm TWMDIR = $(LIBDIR)/twm XSMDIR = $(LIBDIR)/xsm NLSDIR = $(LIBDIR)/nls XLOCALEDIR = $(LIBDIR)/locale PEXAPIDIR = $(LIBDIR)/PEX LBXPROXYDIR = $(LIBDIR)/lbxproxy PROXYMANAGERDIR = $(LIBDIR)/proxymngr XPRINTDIR = $(LIBDIR) XAPPLOADDIR = $(LIBDIR)/app-defaults FONTCFLAGS = -t INSTAPPFLAGS = $(INSTDATFLAGS) RGB = rgb FONTC = bdftopcf MKFONTDIR = mkfontdir DOCUTILSRC = $(XTOP)/doc/util XDOCMACROS = $(DOCUTILSRC)/macros.t XIDXMACROS = $(DOCUTILSRC)/indexmacros.t PROGRAMSRC = $(TOP)/programs LIBSRC = $(XTOP)/lib FONTSRC = $(XTOP)/fonts INCLUDESRC = $(BUILDINCROOT)/include XINCLUDESRC = $(INCLUDESRC)/X11 SERVERSRC = $(XTOP)/programs/Xserver CONTRIBSRC = $(XTOP)/../contrib UNSUPPORTEDSRC = $(XTOP)/unsupported DOCSRC = $(XTOP)/doc RGBSRC = $(XTOP)/programs/rgb BDFTOPCFSRC = $(PROGRAMSRC)/bdftopcf MKFONTDIRSRC = $(PROGRAMSRC)/mkfontdir FONTSERVERSRC = $(PROGRAMSRC)/xfs FONTINCSRC = $(XTOP)/include/fonts EXTINCSRC = $(XTOP)/include/extensions TRANSCOMMSRC = $(LIBSRC)/xtrans TRANS_INCLUDES = -I$(TRANSCOMMSRC) XENVLIBDIR = $(USRLIBDIR) CLIENTENVSETUP = LD_LIBRARY_PATH=$(XENVLIBDIR) # $XConsortium: sunLib.tmpl /main/44 1996/12/09 16:34:30 kaleb $ ICONV_INBUF_DEFINE = -DICONV_INBUF_CONST=const # $XConsortium: sv4Lib.tmpl /main/23 1996/12/04 10:11:01 swick $ XMULIBONLY = -lXmu REGEXSYSLIB = -lgen DYNLIBSYSLIB = -ldl IAFSYSLIB = XLIBSRC = $(LIBSRC)/X11 SOXLIBREV = 6.1 DEPXONLYLIB = XONLYLIB = -lX11 LINTXONLY = $(LINTLIBDIR)/llib-lX11.ln XLIBONLY = $(XONLYLIB) XEXTLIBSRC = $(LIBSRC)/Xext SOXEXTREV = 6.3 DEPEXTENSIONLIB = EXTENSIONLIB = -lXext LINTEXTENSION = $(LINTLIBDIR)/llib-lXext.ln LINTEXTENSIONLIB = $(LINTEXTENSION) DEPXLIB = $(DEPEXTENSIONLIB) $(DEPXONLYLIB) XLIB = $(EXTENSIONLIB) $(XONLYLIB) LINTXLIB = $(LINTXONLYLIB) XAUTHSRC = $(LIBSRC)/Xau DEPXAUTHLIB = $(USRLIBDIR)/libXau.a XAUTHLIB = -lXau LINTXAUTH = $(LINTLIBDIR)/llib-lXau.ln XDMCPLIBSRC = $(LIBSRC)/Xdmcp DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a XDMCPLIB = -lXdmcp LINTXDMCP = $(LINTLIBDIR)/llib-lXdmcp.ln XMUSRC = $(LIBSRC)/Xmu SOXMUREV = 6.0 DEPXMULIB = XMULIB = -lXmu LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln OLDXLIBSRC = $(LIBSRC)/oldX SOOLDXREV = 6.0 DEPOLDXLIB = OLDXLIB = -loldX LINTOLDX = $(LINTLIBDIR)/llib-loldX.ln XPLIBSRC = $(LIBSRC)/Xp SOXPREV = 6.2 DEPXPLIB = XPLIB = -lXp LINTXP = $(LINTLIBDIR)/llib-lXp.ln TOOLKITSRC = $(LIBSRC)/Xt SOXTREV = 6.0 DEPXTOOLONLYLIB = XTOOLONLYLIB = -lXt LINTXTOOLONLY = $(LINTLIBDIR)/llib-lXt.ln DEPXTOOLLIB = $(DEPXTOOLONLYLIB) $(DEPSMLIB) $(DEPICELIB) XTOOLLIB = $(XTOOLONLYLIB) $(SMLIB) $(ICELIB) LINTXTOOLLIB = $(LINTXTOOLONLYLIB) XALIBSRC = $(LIBSRC)/Xa DEPvarLIB = $(USRLIBDIR)/libXa.a varLIB = -lXa LINTvar = $(LINTLIBDIR)/llib-lXa.ln AWIDGETSRC = $(LIBSRC)/Xaw SOXAWREV = 6.1 DEPXAWLIB = XAWLIB = -lXaw LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln XILIBSRC = $(LIBSRC)/Xi SOXINPUTREV = 6.0 DEPXILIB = XILIB = -lXi LINTXI = $(LINTLIBDIR)/llib-lXi.ln XTESTLIBSRC = $(LIBSRC)/Xtst SOXTESTREV = 6.1 DEPXTESTLIB = XTESTLIB = -lXtst LINTXTEST = $(LINTLIBDIR)/llib-lXtst.ln PEXLIBSRC = $(LIBSRC)/PEX5 SOPEXREV = 6.0 DEPPEXLIB = PEXLIB = -lPEX5 LINTPEX = $(LINTLIBDIR)/llib-lPEX5.ln XIELIBSRC = $(LIBSRC)/XIE SOXIEREV = 6.0 DEPXIELIB = XIELIB = -lXIE LINTXIE = $(LINTLIBDIR)/llib-lXIE.ln PHIGSLIBSRC = $(LIBSRC)/PHIGS DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a PHIGSLIB = -lphigs LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a XBSDLIB = -lXbsd LINTXBSD = $(LINTLIBDIR)/llib-lXbsd.ln ICESRC = $(LIBSRC)/ICE SOICEREV = 6.3 DEPICELIB = ICELIB = -lICE LINTICE = $(LINTLIBDIR)/llib-lICE.ln SMSRC = $(LIBSRC)/SM SOSMREV = 6.0 DEPSMLIB = SMLIB = -lSM LINTSM = $(LINTLIBDIR)/llib-lSM.ln XKEYSRC = $(LIBSRC)/Xkey SOXKEYREV = 6.0 DEPXKEYLIB = XKEYLIB = -lXkey LINTXKEY = $(LINTLIBDIR)/llib-lXkey.ln FSLIBSRC = $(LIBSRC)/FS DEPFSLIB = $(USRLIBDIR)/libFS.a FSLIB = -lFS LINTFS = $(LINTLIBDIR)/llib-lFS.ln FONTLIBSRC = $(LIBSRC)/font DEPFONTLIB = $(USRLIBDIR)/libfont.a FONTLIB = -lfont LINTFONT = $(LINTLIBDIR)/llib-lfont.ln XKBFILELIBSRC = $(LIBSRC)/xkbfile DEPXKBFILELIB = $(USRLIBDIR)/libxkbfile.a XKBFILELIB = -lxkbfile LINTXKBFILE = $(LINTLIBDIR)/llib-lxkbfile.ln XKBCOMPCMD = xkbcomp DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB) DEPLIBS1 = $(DEPLIBS) DEPLIBS2 = $(DEPLIBS) DEPLIBS3 = $(DEPLIBS) DEPLIBS4 = $(DEPLIBS) DEPLIBS5 = $(DEPLIBS) DEPLIBS6 = $(DEPLIBS) DEPLIBS7 = $(DEPLIBS) DEPLIBS8 = $(DEPLIBS) DEPLIBS9 = $(DEPLIBS) DEPLIBS10 = $(DEPLIBS) CONFIGDIR = $(LIBDIR)/config USRLIBDIRPATH = $(USRLIBDIR) LDPRELIBS = -L$(USRLIBDIR) LDPOSTLIBS = TOP_INCLUDES = -I$(INCROOT) $(TOP_X_INCLUDES) PROJECT_DEFINES = # ---------------------------------------------------------------------- # start of Imakefile DEPLIBS = OBJS = msub.o SRCS = msub.c PROGRAM = msub all:: msub msub: $(OBJS) $(DEPLIBS) $(RM) $@ $(CCLINK) -o $@ $(LDOPTIONS) $(OBJS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) install:: msub @if [ -d $(DESTDIR)$(BINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DESTDIR)$(BINDIR)); fi $(INSTALL) $(INSTALLFLAGS) $(INSTPGMFLAGS) msub $(DESTDIR)$(BINDIR)/msub install.man:: msub.man @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi $(INSTALL) $(INSTALLFLAGS) $(INSTMANFLAGS) msub.man $(DESTDIR)$(MANDIR)/msub.$(MANSUFFIX) depend:: $(DEPEND) $(DEPENDFLAGS) -- $(ALLDEFINES) $(DEPEND_DEFINES) -- $(SRCS) lint: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) lint1: $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS) clean:: $(RM) msub # "make test" to run a test # "make regression" to run the test, compare output with reference result test:: ./msub ./msub -f test.makefile testfile regression:: ./msub ./msub -f test.makefile testfile | diff test.out - # ---------------------------------------------------------------------- # common rules for all Makefiles - do not edit .c.i: $(RM) $@ $(CC) -E $(CFLAGS) $(_NOOP_) $*.c > $@ emptyrule:: clean:: $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut "#"* Makefile:: -@if [ -f Makefile ]; then set -x; \ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ else exit 0; fi $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR) tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS man_keywords:: catman -M $(DESTDIR)$(MANPATH) -w # ---------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS - do not edit install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" install.linkkit:: @echo "install.linkkit in $(CURRENT_DIR) done" Makefiles:: includes:: depend:: # ---------------------------------------------------------------------- # dependencies generated by makedepend = -G -z tmsub-1.13/Log010064400017710000151000000023750632402602000145730ustar00junkyarddatamgmt00000400000027msub change log V1.0 read the Makefile line by line into buffer, merging continuation lines with no overflow checking. V1.1 reads the entire Makefile into memory and does continuation merging in place. V1.0 only deferenced variables in the script which were known to have been defined or referenced in the Makefile. V1.1 dereferences all variables in the script; if a variable wasn't given a value in the Makefile, it's assumed to have an empty value. V1.0 allowed no way to define alternate reference indicators in the template. V1.1 allows that using +R/-R. This allows better disambiguation of variable references in shell scripts. V1.11 Added support for -e and variable=value options on the command line. V1.12 Adds some type coercion to avoid coredumps on NetBSD systems. V1.13 WinNT systems apparently do \r\n -> \n mapping for read(). This causes the number of bytes read not to equal the number of bytes requested when you try to read in the entire Makefile at once (where the file size is obtained from the stat() information). So for WinNT, just check that the read() returns non-zero if the file size is non-zero. Not great, but better than having msub simply quit. 12 Apr 97 - "make test" for testing msub now works in config/extras under Windows NT. msub-1.13/msub.html010066400017710000151000000160410632400164700157700ustar00junkyarddatamgmt00000400000027 MSUB manual page

MSUB manual page

Table of Contents


NAME

msub - substitute make variables into template to produce script

SYNOPSIS

msub [ -e ] [ -f file ] [ +Rstr ] [ -Rstr ] [ variable=value ] [ file ... ]

DESCRIPTION

Makefiles often contain project configuration information specified as make variables, and it is often desirable to make use of that information in other files. msub allows targets to be produced easily from templates that contain references to those variables. msub is particularly useful in software projects that use imake because virtually all configuration parameters are written into Makefiles and are thus available for propagation into other files.

First msub reads the Makefile and finds all variable definition lines of the form "var = value". Then msub reads any files named on the command line (or the standard input if none), looks for references to those variables, and replaces the references with the corresponding variable values. References to undefined variables are replaced by the empty string. The result is written to the standard output.

msub takes the following options:

-e
Environment variable values override assignments within Makefiles. Normally assignments within Makefiles override environment variables.
-f file
By default, variable values are extracted from Makefile (or makefile if Makefile is missing) in the current directory. If the -f file option is given, variable values are extracted from file instead. Multiple -f options may be specified. (Note: make recognizes -f - to mean the Makefile should be read from stdin. msub doesn't, because template input may come from stdin.)
+Rstr

-Rstr
The default variable reference indicators within templates are the same as in Makefiles, i.e., "$(" and ")", and "${" and "}". These can be changed with the +R and -R options, which must be specified in pairs. +R specifies the string that initiates a variable reference and -R specifies the string that terminates it. Multiple pairs of reference indicators may be given.
variable=value
Variable definition. This definition overrides any regular definition for the specified variable within the makefile itself or in the environment.

EXAMPLES

Suppose you want to produce for a program a help file that indicates the local e-mail address to which questions may be directed. If this address is specified as the variable EMAILHELPADDR in the Makefile, you can write a template helpfile.msub like this:
    ...stuff...
    Please direct questions to ${EMAILHELPADDR}.
    ...more stuff...
Process the template to produce the help file like this:
    msub helpfile.msub > helpfile
If the Makefile contains the following lines:
    EMAILHELPADDR = postmaster@$(DOMAIN)
    DOMAIN = primate.wisc.edu
then helpfile will look like this:
    ...stuff...
    Please direct questions to postmaster@primate.wisc.edu.
    ...more stuff...
msub can produce executable scripts, too. If the processor for which you're producing the script allows variable references, make sure you refer to make variables in the template in a different way than the processor refers to variables. For instance, "${var}" is ambiguous in a shell script template - is it a reference to a shell variable that you want msub to leave alone, or to a make variable for which you want msub to substitute the variable's value? To resolve the ambiguity, you can refer to shell variables as "$var" (which the shell recognizes, but msub doesn't), or you can use different indicators than the defaults to refer to make variables in the template. For example, you could use "@<" and ">@" and refer to variables as "@<var>@". Suppose you have a simple shell script to print your home directory pathname. You might write it like this:
    #!@<SHELL>@
    echo ${HOME}
Then you can process the template like this (note that you must quote the arguments because "<" and ">" are special to the shell):
    msub +R"@<" -R">@" template > script
The +R/-R arguments cause msub to recognize "@<SHELL>@" but not "${HOME}". The result looks like this:
    #!/bin/sh
    echo ${HOME}

WHO-TO-BLAME

Paul DuBois, dubois@primate.wisc.edu

BUGS AND RESTRICTIONS

CC, YACC, etc., have implicit values in make even if they're not defined in the Makefile, which isn't true for msub. However, when msub is used with imake, this isn't normally a problem since imake-generated Makefiles tend to contain explicit definitions for every parameter in the known universe.

msub is more restrictive in the variable names it recognizes and performs substitutions on than make. make allows single character names to be referenced as "$c", where c is a letter; msub doesn't. msub also ignores make variables like "$*" and "$@".

Recursive references in Makefile variables aren't expanded. If a Makefile contains the definition "X = ${X}", X won't be expanded. Indirectly recursive references aren't expanded, either. If a Makefile contains the definitions "X = ${Y}" and "Y = ${X}", neither X nor Y will be expanded. (These actually aren't bugs in msub, they're problems in the Makefile.)

A comment at the end of a variable assignment line become part of the variable's value. If Makefile contains the following line:

    SHELL = /bin/shell # default shell
then msub takes the value of SHELL to be "/bin/shell # default shell".
-Rstr
The default variable reference indicators within templates are the same as in Makefiles, i.e., "$(" and ")", and "${" and "}". These can be changed with the +R and -R options, which must be specified in pairs. +R specifies the string that initiates a variable reference and -R specifies the string that terminates it. Multiple pairs of reference indicators may be gmsub-1.13/README010064400017710000151000000024330632374005500150140ustar00junkyarddatamgmt00000400000027README for msub Paul DuBois 12 April 1997 msub is a program that reads a template file for variable references, then substitutes those references with variable values. It gets the values by looking through the Makefile. This means you can refer to any variables that are defined in your Makefile. msub is most useful with imake, since then you tend to have Makefiles with lots of make variables defined that you can refer to. See the file "imake.support" for some information on using msub with imake. If you have imake and the X11 configuration files, you can build and install like this: % xmkmf Generate the Makefile % make clean Remove anything extraneous % make Build msub % make install Install msub % make install.man Install msub manual page "make test" can be used to run a simple test. The file "test.out" contains the expected output. msub works on UNIX or Windows NT, though to use the command sequence above under NT, you'll have to have the Perl version of xmkmf installed and you should use nmake rather than make. Under NT the executable will be called msub.exe. You can also compile msub by hand, perhaps with a command as simple as this: % cc -o msub msub.c Under Windows NT, make sure to pass -DWIN32 to the compile command, and to name the executable msub.exe. msub-1.13/.depend010066400017710000151000000005100632055745300153750ustar00junkyarddatamgmt00000400000027# DO NOT DELETE msub.o: /usr/include/stdio.h /usr/include/sys/types.h msub.o: /usr/include/sys/cdefs.h /usr/include/machine/endian.h msub.o: /usr/include/machine/ansi.h /usr/include/machine/types.h msub.o: /usr/include/ctype.h /usr/include/runetype.h /usr/include/sys/stat.h msub.o: /usr/include/sys/time.h /usr/include/time.h msub-1.13/X11/004077500017710000151000000000000632400160600145015ustar00junkyarddatamgmt00000400000027msub-1.13/X11/Xfuncproto.h010064400017710000151000000055010632055751600170310ustar00junkyarddatamgmt00000400000027/* $XConsortium: Xfuncproto.h,v 1.9 95/06/08 23:20:39 gildea Exp $ */ /* * Copyright (c) 1989, 1991 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. * */ /* Definitions to make function prototypes manageable */ #ifndef _XFUNCPROTO_H_ #define _XFUNCPROTO_H_ #ifndef NeedFunctionPrototypes #if defined(FUNCPROTO) || defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) #define NeedFunctionPrototypes 1 #else #define NeedFunctionPrototypes 0 #endif #endif /* NeedFunctionPrototypes */ #ifndef NeedVarargsPrototypes #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&2) #define NeedVarargsPrototypes 1 #else #define NeedVarargsPrototypes 0 #endif #endif /* NeedVarargsPrototypes */ #if NeedFunctionPrototypes #ifndef NeedNestedPrototypes #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&8) #define NeedNestedPrototypes 1 #else #define NeedNestedPrototypes 0 #endif #endif /* NeedNestedPrototypes */ #ifndef _Xconst #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&4) #define _Xconst const #else #define _Xconst #endif #endif /* _Xconst */ #ifndef NeedWidePrototypes #ifdef NARROWPROTO #define NeedWidePrototypes 0 #else #define NeedWidePrototypes 1 /* default to make interropt. easier */ #endif #endif /* NeedWidePrototypes */ #endif /* NeedFunctionPrototypes */ #ifndef _XFUNCPROTOBEGIN #ifdef __cplusplus /* for C++ V2.0 */ #define _XFUNCPROTOBEGIN extern "C" { /* do not leave open across includes */ #define _XFUNCPROTOEND } #else #define _XFUNCPROTOBEGIN #define _XFUNCPROTOEND #endif #endif /* _XFUNCPROTOBEGIN */ #endif /* _XFUNCPROTO_H_ */ msub-1.13/X11/Xos.h010064400017710000151000000131030632055751600154300ustar00junkyarddatamgmt00000400000027/* * $XConsortium: Xos.h /main/70 1996/11/15 16:00:41 kaleb $ * * Copyright (c) 1987 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. * * The X Window System is a Trademark of X Consortium. * */ /* This is a collection of things to try and minimize system dependencies * in a "signficant" number of source files. */ #ifndef _XOS_H_ #define _XOS_H_ #include /* * Get major data types (esp. caddr_t) */ #ifdef USG #ifndef __TYPES__ #ifdef CRAY #define word word_t #endif /* CRAY */ #include /* forgot to protect it... */ #define __TYPES__ #endif /* __TYPES__ */ #else /* USG */ #if defined(_POSIX_SOURCE) && (defined(MOTOROLA) || defined(AMOEBA)) #undef _POSIX_SOURCE #include #define _POSIX_SOURCE #else #include #endif #endif /* USG */ /* * Just about everyone needs the strings routines. We provide both forms here, * index/rindex and strchr/strrchr, so any systems that don't provide them all * need to have #defines here. * * These macros are defined this way, rather than, e.g.: * #defined index(s,c) strchr(s,c) * because someone might be using them as function pointers, and such * a change would break compatibility for anyone who's relying on them * being the way they currently are. So we're stuck with them this way, * which can be really inconvenient. :-( */ #ifndef X_NOT_STDC_ENV #include #ifndef index #define index strchr #endif #ifndef rindex #define rindex strrchr #endif #else #ifdef SYSV #include #define index strchr #define rindex strrchr #else #include #define strchr index #define strrchr rindex #endif #endif /* X_NOT_STDC_ENV */ /* * strerror() */ #if defined(X_NOT_STDC_ENV) || (defined(sun) && !defined(SVR4)) || defined(macII) #ifndef strerror extern char *sys_errlist[]; extern int sys_nerr; #define strerror(n) \ (((n) >= 0 && (n) < sys_nerr) ? sys_errlist[n] : "unknown error") #endif #endif /* * Get open(2) constants */ #ifdef X_NOT_POSIX #include #if defined(USL) || defined(CRAY) || defined(MOTOROLA) || (defined(i386) && (defined(SYSV) || defined(SVR4))) || defined(__sxg__) #include #endif #ifdef WIN32 #include #else #include #endif #else /* X_NOT_POSIX */ #if !defined(_POSIX_SOURCE) && defined(macII) #define _POSIX_SOURCE #include #include #undef _POSIX_SOURCE #else #include #include #endif #endif /* X_NOT_POSIX else */ /* * Get struct timeval */ #ifdef SYSV #ifndef USL #include #endif #include #ifdef CRAY #undef word #endif /* CRAY */ #if defined(USG) && !defined(CRAY) && !defined(MOTOROLA) && !defined(uniosu) && !defined(__sxg__) struct timeval { long tv_sec; long tv_usec; }; #ifndef USL_SHARELIB struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif /* USL_SHARELIB */ #endif /* USG */ #ifdef _SEQUENT_ struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif /* _SEQUENT_ */ #else /* not SYSV */ #if defined(_POSIX_SOURCE) && defined(SVR4) /* need to omit _POSIX_SOURCE in order to get what we want in SVR4 */ #undef _POSIX_SOURCE #include #define _POSIX_SOURCE #else /* defined(_POSIX_SOURCE) && defined(SVR4) */ #ifdef WIN32 #include #if !defined(_WINSOCKAPI_) && !defined(_WILLWINSOCK_) struct timeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ }; #endif #include #define gettimeofday(t) \ { \ struct _timeb _gtodtmp; \ _ftime (&_gtodtmp); \ (t)->tv_sec = _gtodtmp.time; \ (t)->tv_usec = _gtodtmp.millitm * 1000; \ } #else /* WIN32 */ #ifdef _SEQUENT_ #include #else /* _SEQUENT_ */ #include #endif /* _SEQUENT_ */ #endif /* WIN32 else */ #endif /* defined(_POSIX_SOURCE) && defined(SVR4) */ #endif /* SYSV */ /* define X_GETTIMEOFDAY macro, a portable gettimeofday() */ #if defined(_XOPEN_XPG4) || defined(_XOPEN_UNIX) /* _XOPEN_UNIX is XPG4.2 */ #define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0) #else #if defined(SVR4) || defined(VMS) || defined(WIN32) #define X_GETTIMEOFDAY(t) gettimeofday(t) #else #define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0) #endif #endif /* XPG4 else */ /* use POSIX name for signal */ #if defined(X_NOT_POSIX) && defined(SYSV) && !defined(SIGCHLD) #define SIGCHLD SIGCLD #endif #ifdef ISC #include #endif #endif /* _XOS_H_ */ msub-1.13/X11/Xosdefs.h010064400017710000151000000054570632055751600163070ustar00junkyarddatamgmt00000400000027/* * O/S-dependent (mis)feature macro definitions * * $XConsortium: Xosdefs.h /main/16 1996/09/28 16:17:29 rws $ * Copyright (c) 1991 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. */ #ifndef _XOSDEFS_H_ #define _XOSDEFS_H_ /* * X_NOT_STDC_ENV means does not have ANSI C header files. Lack of this * symbol does NOT mean that the system has stdarg.h. * * X_NOT_POSIX means does not have POSIX header files. Lack of this * symbol does NOT mean that the POSIX environment is the default. * You may still have to define _POSIX_SOURCE to get it. */ #ifdef NOSTDHDRS #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #ifdef sony #if !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV) #define X_NOT_POSIX #endif #endif #ifdef UTEK #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #ifdef vax #ifndef ultrix /* assume vanilla BSD */ #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #endif #ifdef luna #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #ifdef Mips #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #ifdef USL #ifdef SYSV /* (release 3.2) */ #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #endif #ifdef i386 #ifdef SYSV #ifndef _SCO_DS /* SCO 5.0 has SVR4 header files */ #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #endif #endif #ifdef MOTOROLA #ifdef SYSV #define X_NOT_STDC_ENV #endif #endif #ifdef sun #ifdef SVR4 /* define this to whatever it needs to be */ #define X_POSIX_C_SOURCE 199300L #endif #endif #ifdef WIN32 #ifndef _POSIX_ #define X_NOT_POSIX #endif #endif #if defined(nec_ews_svr2) || defined(SX) || defined(PC_UX) #define X_NOT_POSIX #define X_NOT_STDC_ENV #endif #endif /* _XOSDEFS_H_ */ msub-1.13/X11/Xw32defs.h010064400017710000151000000032140632400160600162520ustar00junkyarddatamgmt00000400000027/* $XConsortium: Xw32defs.h /main/5 1996/11/13 14:43:44 lehors $ */ #ifndef _XW32DEFS_H #define _XW32DEFS_H typedef char *caddr_t; #define access _access #define alloca _alloca #define chdir _chdir #define chmod _chmod #define close _close #define creat _creat #define dup _dup #define dup2 _dup2 #define environ _environ #define execl _execl #define execle _execle #define execlp _execlp #define execlpe _execlpe #define execv _execv #define execve _execve #define execvp _execvp #define execvpe _execvpe #define fdopen _fdopen #define fileno _fileno #define fstat _fstat #define getcwd _getcwd #define getpid _getpid #define hypot _hypot #define isascii __isascii #define isatty _isatty #define lseek _lseek #define mkdir _mkdir #define mktemp _mktemp #define open _open #define putenv _putenv #define read _read #define rmdir _rmdir #define sleep(x) _sleep((x) * 1000) #define stat _stat #define sys_errlist _sys_errlist #define sys_nerr _sys_nerr #define umask _umask #define unlink _unlink #define write _write #define random rand #define srandom srand #define O_RDONLY _O_RDONLY #define O_WRONLY _O_WRONLY #define O_RDWR _O_RDWR #define O_APPEND _O_APPEND #define O_CREAT _O_CREAT #define O_TRUNC _O_TRUNC #define O_EXCL _O_EXCL #define O_TEXT _O_TEXT #define O_BINARY _O_BINARY #define O_RAW _O_BINARY #define S_IFMT _S_IFMT #define S_IFDIR _S_IFDIR #define S_IFCHR _S_IFCHR #define S_IFREG _S_IFREG #define S_IREAD _S_IREAD #define S_IWRITE _S_IWRITE #define S_IEXEC _S_IEXEC #define F_OK 0 #define X_OK 1 #define W_OK 2 #define R_OK 4 #endif troffcvt-1.04.orig/tarballs/portlib-1.01.tar100644 1750 1750 176000 6431756100 16501 0ustar blpblpportlib-1.01/004077500017710000151000000000000634120634400146375ustar00junkyarddatamgmt00000400000027portlib-1.01/config/004077500017710000151000000000000631711100100160705ustar00junkyarddatamgmt00000400000027portlib-1.01/config/Imake.p-params010064400017710000151000000025470634014006400205720ustar00junkyarddatamgmt00000400000027#ifndef ProjectName #define ProjectName Portability Library #endif #ifndef ProjectMajorRelease #define ProjectMajorRelease 1 #endif #ifndef ProjectMinorRelease #define ProjectMinorRelease 01 #endif /* * Override default values of PortLib/DepPortLib, since they refer * to the already-installed library. */ #ifndef PortLib #define PortLib $(LOADERLIBPREFIX)$(TOP)/libport.a #endif #ifndef DepPortLib #define DepPortLib $(TOP)/libport.a #endif #ifndef ProjectIncludes #define ProjectIncludes -I. #endif #ifndef HasFlock /* flock() system call present? */ #if SystemV || SystemV4 #define HasFlock NO #else /* BSD */ #define HasFlock YES #endif #endif #ifndef HasFcntl /* fcntl() system call present? */ #if SystemV || SystemV4 #define HasFcntl YES #else /* BSD */ #define HasFcntl NO #endif #endif #ifndef HasSysDirH /* sys/dir.h include file present? */ #if SystemV || SystemV4 #define HasSysDirH NO #else /* BSD */ #define HasSysDirH YES #endif #endif #ifndef HasDirentH /* dirent.h include file present? */ #if SystemV || SystemV4 #define HasDirentH YES #else /* BSD */ #define HasDirentH NO #endif #endif #ifndef HasSysconf /* is sysconf(_SC_OPEN_MAX) available? */ #define HasSysconf NO #endif #ifndef HasBCopy #if SystemV || SystemV4 #define HasBCopy NO #else /* BSD */ #define HasBCopy YES #endif #endif #ifndef HasStrcasecmp #define HasStrcasecmp YES #endif portlib-1.01/config/Mips.p-cf010064400017710000151000000001330626753346500175710ustar00junkyarddatamgmt00000400000027#ifndef HasFcntl #define HasFcntl YES #endif #ifndef HasFlock #define HasFlock YES #endif portlib-1.01/config/sun.p-cf010064400017710000151000000002120626753346500174640ustar00junkyarddatamgmt00000400000027#ifndef HasFcntl #define HasFcntl YES #endif #ifndef HasSysconf /* is sysconf(_SC_OPEN_MAX) available? */ #define HasSysconf YES #endif portlib-1.01/config/hp.p-cf010064400017710000151000000001340626753346500172710ustar00junkyarddatamgmt00000400000027#ifndef HasSysconf /* is sysconf(_SC_OPEN_MAX) available? */ #define HasSysconf YES #endif portlib-1.01/config/ultrix.p-cf010064400017710000151000000001350626753346500202120ustar00junkyarddatamgmt00000400000027 #ifndef HasSysconf /* is sysconf(_SC_OPEN_MAX) available? */ #define HasSysconf YES #endif portlib-1.01/config/linux-pmac.p-cf010064400017710000151000000012270631711105400207210ustar00junkyarddatamgmt00000400000027#ifndef HasFcntl /* fcntl() system call present? */ #define HasFcntl YES #endif #ifndef HasDirentH /* dirent.h include file present? */ #define HasDirentH YES #endif #ifndef HasSysconf /* is sysconf(_SC_OPEN_MAX) available? */ #define HasSysconf YES #endif /* * sys/dir.h is present, but scandir() doesn't work with pre-2.x servers. * Since we can't tell in this file what server version we're using (that * isn't set until linux-pmac.cf is processed), and since the * opendir()/readdir() stuff always works, just set this to NO to disable * use of scandir(). */ #ifndef HasSysDirH /* sys/dir.h include file present? */ #define HasSysDirH NO #endif portlib-1.01/Imakefile010064400017710000151000000050170627457110700164550ustar00junkyarddatamgmt00000400000027/* Portability library Imakefile */ XCOMM Portability library Makefile #if !HasStrcasecmp XCOMM system doesn't have strcasecmp(), provide it in portlib. STRSRCS = strcasecmp.c STROBJS = strcasecmp.o #endif DEFINES = \ -DHAS_SYSCONF=HasSysconf \ -DHAS_FLOCK=HasFlock \ -DHAS_FCNTL=HasFcntl \ -DHAS_SYS_DIR_H=HasSysDirH \ -DHAS_DIRENT_H=HasDirentH \ -DHAS_BCOPY=HasBCopy LIBSRCS = ato.c dir.c fd.c lock.c mem.c $(STRSRCS) LIBOBJS = ato.o dir.o fd.o lock.o mem.o $(STROBJS) ATOSRCS = atotest.c ATOOBJS = atotest.o ATOLIBS = $(PORTLIB) DEPATOLIBS = $(DEPPORTLIB) DIRSRCS = dirtest.c DIROBJS = dirtest.o DIRLIBS = $(PORTLIB) DEPDIRLIBS = $(DEPPORTLIB) FDSRCS = fdtest.c FDOBJS = fdtest.o FDLIBS = $(PORTLIB) DEPFDLIBS = $(DEPPORTLIB) LOCKSRCS = locktest.c LOCKOBJS = locktest.o LOCKLIBS = $(PORTLIB) DEPLOCKLIBS = $(DEPPORTLIB) MEMSRCS = memtest.c MEMOBJS = memtest.o MEMLIBS = $(PORTLIB) DEPMEMLIBS = $(DEPPORTLIB) SRCS = $(LIBSRCS) $(ATOSRCS) $(DIRSRCS) $(FDSRCS) $(LOCKSRCS) $(MEMSRCS) all:: NormalLibraryObjectRule() BuildNormalLibrary(port,$(LIBSRCS),$(LIBOBJS)) InstallLibrary(port,$(LOCALUSRLIBDIR)) InstallIncludeFile(portlib.h,$(LOCALINCLUDEROOT)) BuildProgram(atotest,$(ATOSRCS),$(ATOOBJS),$(ATOLIBS),$(DEPATOLIBS)) FakeInstallFile(atotest) BuildProgram(dirtest,$(DIRSRCS),$(DIROBJS),$(DIRLIBS),$(DEPDIRLIBS)) FakeInstallFile(dirtest) BuildProgram(fdtest,$(FDSRCS),$(FDOBJS),$(FDLIBS),$(DEPFDLIBS)) FakeInstallFile(fdtest) BuildProgram(locktest,$(LOCKSRCS),$(LOCKOBJS),$(LOCKLIBS),$(DEPLOCKLIBS)) FakeInstallFile(locktest) BuildProgram(memtest,$(MEMSRCS),$(MEMOBJS),$(MEMLIBS),$(DEPMEMLIBS)) FakeInstallFile(memtest) ShScriptFromMsubTemplate(porttest,porttest.sh,NullArg) FakeInstallFile(porttest) DependTarget() SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) HelpAuxTarget(test-all,test all portlib operations) test-all:: porttest atotest dirtest fdtest locktest memtest ./porttest HelpAuxTarget(test-ato,test string-conversion operations) test-ato:: porttest atotest ./porttest ato HelpAuxTarget(test-dir,test directory-reading operations) test-dir:: porttest dirtest ./porttest dir HelpAuxTarget(test-fd,test file-descriptor operations) test-fd:: porttest fdtest ./porttest fd HelpAuxTarget(test-lock,test file-locking operations) test-lock:: porttest locktest ./porttest lock XCOMM remove test lock file used by locktest StuffToClean(lock.test) HelpAuxTarget(test-mem,test memory operations) test-mem:: porttest memtest ./porttest mem portlib-1.01/portlib.h010064400017710000151000000007010634013775000164570ustar00junkyarddatamgmt00000400000027/* * portlib.h * * Portability Library stuff */ #ifndef _PORTLIB_H #define _PORTLIB_H extern int AcquireLock (); extern void ReleaseLock (); extern int OpenDir (); extern char *ReadDir (); extern void CloseDir (); extern int MaxFileDesc (); extern short StrToShort (); extern int StrToInt (); extern long StrToLong (); extern double StrToDouble (); extern void BCopy (); extern void BZero (); extern int BCmp (); #endif /* _PORTLIB_H */ portlib-1.01/Makefile010066400017710000151000000411250634014007700162760ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 10 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = Portability Library PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 01 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = $(LOADERLIBPREFIX)$(TOP)/libport.a DEPPORTLIB = $(TOP)/libport.a # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # Portability library Makefile DEFINES = \ -DHAS_SYSCONF=1 \ -DHAS_FLOCK=0 \ -DHAS_FCNTL=1 \ -DHAS_SYS_DIR_H=0 \ -DHAS_DIRENT_H=1 \ -DHAS_BCOPY=0 LIBSRCS = ato.c dir.c fd.c lock.c mem.c $(STRSRCS) LIBOBJS = ato.o dir.o fd.o lock.o mem.o $(STROBJS) ATOSRCS = atotest.c ATOOBJS = atotest.o ATOLIBS = $(PORTLIB) DEPATOLIBS = $(DEPPORTLIB) DIRSRCS = dirtest.c DIROBJS = dirtest.o DIRLIBS = $(PORTLIB) DEPDIRLIBS = $(DEPPORTLIB) FDSRCS = fdtest.c FDOBJS = fdtest.o FDLIBS = $(PORTLIB) DEPFDLIBS = $(DEPPORTLIB) LOCKSRCS = locktest.c LOCKOBJS = locktest.o LOCKLIBS = $(PORTLIB) DEPLOCKLIBS = $(DEPPORTLIB) MEMSRCS = memtest.c MEMOBJS = memtest.o MEMLIBS = $(PORTLIB) DEPMEMLIBS = $(DEPPORTLIB) SRCS = $(LIBSRCS) $(ATOSRCS) $(DIRSRCS) $(FDSRCS) $(LOCKSRCS) $(MEMSRCS) all:: .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libport.a libport.a: $(LIBOBJS) $(RM) $@ $(AR) $@ $(LIBOBJS) clean:: $(RM) libport.a lint:: lint.libport.a lint.libport.a: $(LINT) $(LINTFLAGS) $(LIBSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.libport.a"' to "lint sources for libport.a help_aux:: @echo "'make "libport.a"' to "build the libport.a library install:: i.libport.a help_aux:: @echo "'make "i.libport.a"' to "install libport.a i.libport.a:: libport.a @if [ -d $(LOCALUSRLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALUSRLIBDIR)); fi $(INSTALL) $(INSTLIBFLAGS) libport.a $(LOCALUSRLIBDIR)/libport.a install:: i.portlib.h help_aux:: @echo "'make "i.portlib.h"' to "install portlib.h i.portlib.h:: portlib.h @if [ -d $(LOCALINCLUDEROOT) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALINCLUDEROOT)); fi $(INSTALL) $(INSTINCFLAGS) portlib.h $(LOCALINCLUDEROOT)/portlib.h all:: atotest help_aux:: @echo "'make "atotest"' to "build atotest atotest: $(ATOOBJS) $(DEPATOLIBS) $(RM) $@ $(CC) -o $@ $(ATOOBJS) $(LDOPTS) $(ATOLIBS) $(EXTRA_LDLIBS) clean:: $(RM) atotest lint:: lint.atotest lint.atotest: $(LINT) $(LINTFLAGS) $(ATOSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.atotest"' to "lint sources for atotest install:: i.atotest i.atotest:: @echo atotest is not installed anywhere. all:: dirtest help_aux:: @echo "'make "dirtest"' to "build dirtest dirtest: $(DIROBJS) $(DEPDIRLIBS) $(RM) $@ $(CC) -o $@ $(DIROBJS) $(LDOPTS) $(DIRLIBS) $(EXTRA_LDLIBS) clean:: $(RM) dirtest lint:: lint.dirtest lint.dirtest: $(LINT) $(LINTFLAGS) $(DIRSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.dirtest"' to "lint sources for dirtest install:: i.dirtest i.dirtest:: @echo dirtest is not installed anywhere. all:: fdtest help_aux:: @echo "'make "fdtest"' to "build fdtest fdtest: $(FDOBJS) $(DEPFDLIBS) $(RM) $@ $(CC) -o $@ $(FDOBJS) $(LDOPTS) $(FDLIBS) $(EXTRA_LDLIBS) clean:: $(RM) fdtest lint:: lint.fdtest lint.fdtest: $(LINT) $(LINTFLAGS) $(FDSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.fdtest"' to "lint sources for fdtest install:: i.fdtest i.fdtest:: @echo fdtest is not installed anywhere. all:: locktest help_aux:: @echo "'make "locktest"' to "build locktest locktest: $(LOCKOBJS) $(DEPLOCKLIBS) $(RM) $@ $(CC) -o $@ $(LOCKOBJS) $(LDOPTS) $(LOCKLIBS) $(EXTRA_LDLIBS) clean:: $(RM) locktest lint:: lint.locktest lint.locktest: $(LINT) $(LINTFLAGS) $(LOCKSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.locktest"' to "lint sources for locktest install:: i.locktest i.locktest:: @echo locktest is not installed anywhere. all:: memtest help_aux:: @echo "'make "memtest"' to "build memtest memtest: $(MEMOBJS) $(DEPMEMLIBS) $(RM) $@ $(CC) -o $@ $(MEMOBJS) $(LDOPTS) $(MEMLIBS) $(EXTRA_LDLIBS) clean:: $(RM) memtest lint:: lint.memtest lint.memtest: $(LINT) $(LINTFLAGS) $(MEMSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.memtest"' to "lint sources for memtest install:: i.memtest i.memtest:: @echo memtest is not installed anywhere. all:: porttest porttest:: porttest.sh $(RM) $@ echo "#!"$(SHELL) > $@ $(MSUB) porttest.sh >> $@ $(CHMOD) a+x $@ clean:: $(RM) porttest help_aux:: @echo "'make "porttest"' to "build the porttest script install:: i.porttest i.porttest:: @echo porttest is not installed anywhere. depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) all:: World:: @echo "Building "$(PROJECTNAME)", Release "$(PROJECTRELEASE) @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean $(MAKE) $(MFLAGS) depend $(MAKE) $(MFLAGS) all @echo "" @date @echo "" @echo "Done building "$(PROJECTNAME) help_aux:: @echo "'make "World"' to "build the entire $(PROJECTNAME) distribution help_aux:: @echo "'make "test-all"' to "test all portlib operations test-all:: porttest atotest dirtest fdtest locktest memtest ./porttest help_aux:: @echo "'make "test-ato"' to "test string-conversion operations test-ato:: porttest atotest ./porttest ato help_aux:: @echo "'make "test-dir"' to "test directory-reading operations test-dir:: porttest dirtest ./porttest dir help_aux:: @echo "'make "test-fd"' to "test file-descriptor operations test-fd:: porttest fdtest ./porttest fd help_aux:: @echo "'make "test-lock"' to "test file-locking operations test-lock:: porttest locktest ./porttest lock # remove test lock file used by locktest clean:: $(RM) lock.test help_aux:: @echo "'make "test-mem"' to "test memory operations test-mem:: porttest memtest ./porttest mem # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE ato.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h ato.o: /usr/include/math.h /usr/include/floatingpoint.h ato.o: /usr/include/sys/ieeefp.h dir.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h dir.o: /usr/include/sys/types.h /usr/include/sys/isa_defs.h dir.o: /usr/include/sys/machtypes.h /usr/include/sys/select.h dir.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/dirent.h dir.o: /usr/include/sys/dirent.h portlib.h fd.o: portlib.h /usr/include/unistd.h /usr/include/sys/feature_tests.h fd.o: /usr/include/sys/types.h /usr/include/sys/isa_defs.h fd.o: /usr/include/sys/machtypes.h /usr/include/sys/select.h fd.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/sys/unistd.h lock.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h lock.o: /usr/include/fcntl.h /usr/include/sys/types.h lock.o: /usr/include/sys/isa_defs.h /usr/include/sys/machtypes.h lock.o: /usr/include/sys/select.h /usr/include/sys/time.h /usr/include/time.h lock.o: /usr/include/sys/fcntl.h portlib.h mem.o: portlib.h /usr/include/string.h /usr/include/sys/feature_tests.h atotest.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h portlib.h dirtest.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h portlib.h fdtest.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h portlib.h locktest.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h portlib.h memtest.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h portlib.h IBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -portlib-1.01/lock.c010064400017710000151000000030560626753346600157510ustar00junkyarddatamgmt00000400000027/* * File-locking calls * * AcquireLock() - acquire an exclusive lock on an open file * ReleaseLock() - release a lock on an open file * * The argument to both calls is a FILE * */ #if !HAS_FCNTL && !HAS_FLOCK *** error -- neither fcntl() nor flock() are present? #endif #include #if HAS_FCNTL #include #endif #if HAS_FLOCK #include #endif #include "portlib.h" /* * Some braindamaged systems don't define this in fcntl.h. */ #ifndef SEEK_SET #define SEEK_SET 0 #endif #if HAS_FCNTL /* fcntl() version of locking functions */ int AcquireLock (f) FILE *f; { struct flock lock; int fd; #ifdef DEBUG printf ("using fcntl() on fileno %d\n", fileno (f)); #endif lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; fd = fileno (f); if (fcntl (fd, F_SETLK, &lock) == 0) return (1); #ifdef DEBUG perror ("AcquireLock"); #endif return (0); } void ReleaseLock (f) FILE *f; { struct flock lock; int fd; lock.l_type = F_UNLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; fd = fileno (f); (void) fcntl (fd, F_SETLK, &lock); } #else #if HAS_FLOCK /* flock() version of locking functions */ int AcquireLock (f) FILE *f; { int fd; #ifdef DEBUG printf ("using flock() on fileno %d\n", fileno (f)); #endif fd = fileno (f); if (flock (fd, LOCK_EX | LOCK_NB) == 0) return (1); #ifdef DEBUG perror ("AcquireLock"); #endif return (0); } void ReleaseLock (f) FILE *f; { int fd; fd = fileno (f); (void) flock (fd, LOCK_UN); } #endif /* HAS_FLOCK */ #endif /* HAS_FCNTL */ portlib-1.01/dir.c010064400017710000151000000043060626753346600155760ustar00junkyarddatamgmt00000400000027/* * Directory-reading calls * * int OpenDir(pathname) - open a directory for reading * char *ReadDir() - return next name from directory or NULL * void CloseDir() - close directory */ #if !HAS_DIRENT_H && !HAS_SYS_DIR_H *** error -- neither opendir()/readdir() nor scandir() are present? #endif #include #include #if HAS_DIRENT_H # include #else # if HAS_SYS_DIR_H # include # endif #endif #include "portlib.h" #if HAS_DIRENT_H /* opendir() version of directory functions */ static DIR *dir = (DIR *) NULL; int OpenDir (pathname) char *pathname; { #ifdef DEBUG printf ("using opendir() to read %s\n", pathname); #endif CloseDir (); /* close previous directory if one is open */ dir = opendir (pathname); if (dir != (DIR *) NULL) return (1); #ifdef DEBUG perror ("OpenDir"); #endif return (0); } char * ReadDir () { struct dirent *dp; if (dir != (DIR *) NULL) /* directory is open */ { dp = readdir (dir); if (dp != (struct dirent *) NULL) return (dp->d_name); CloseDir (); } return ((char *) NULL); } void CloseDir () { if (dir != (DIR *) NULL) (void) closedir (dir); dir = (DIR *) NULL; } #else #if HAS_SYS_DIR_H /* scandir() version of directory functions */ /* * Use scandir() to simulate an opendir()/readdir()/closedir() interface. */ static struct direct **dp = (struct direct **) NULL; static int count = 0; static int index = 0; int OpenDir (pathname) char *pathname; { #ifdef DEBUG printf ("using scandir() to read %s\n", pathname); #endif CloseDir (); /* close previous directory if one is open */ count = scandir (pathname, &dp, NULL, NULL); if (count >= 0) { return (1); } #ifdef DEBUG perror ("OpenDir"); #endif count = 0; return (0); } char * ReadDir () { if (index < count) return (dp[index++]->d_name); CloseDir (); return ((char *) NULL); } /* * It seems to me that the memory pointed to by dp should be freed, * but adding free(dp) to the function below makes no difference. * Perhaps it's necessary to walk through the entries and free them * individually. */ void CloseDir () { dp = (struct direct **) NULL; count = 0; index = 0; } #endif /* HAS_SYS_DIR_H */ #endif /* HAS_DIRENT_H */ portlib-1.01/dirtest.c010064400017710000151000000013100626753346600164660ustar00junkyarddatamgmt00000400000027/* * dirtest - test portlib directory-reading functions * * This program takes one argument, a directory name, and displays * the names of the files in that directory. * * 29 November 1996 * Paul DuBois * dubois@primate.wisc.edu * http://www.primate.wisc.edu/people/dubois/ */ #include #include "portlib.h" int main (argc, argv) int argc; char *argv[]; { FILE *f; char *p; --argc; /* skip program name */ ++argv; if (argc != 1) { fprintf (stderr, "Usage: dirtest dirname\n"); exit (1); } if (OpenDir (argv[0]) == 0) { fprintf (stderr, "could not open directory\n"); exit (1); } while ((p = ReadDir ()) != (char *) NULL) printf ("%s\n", p); CloseDir (); exit (0); } portlib-1.01/README010064400017710000151000000035030631207560700155170ustar00junkyarddatamgmt00000400000027Portability Library Paul DuBois dubois@primate.wisc.edu http://www.primate.wisc.edu/people/dubois/ 16 January 1997 This library provides a consistent interface across systems to operations that tend to vary in ugly ways for different UNIX systems, such as file locking and directory reading. By using the library, programs can use a set of function names that don't vary across systems. I figured, why write the code to make these decisions in different programs? Why not figure it out once and package it up in a library so any program can use the functions? AcquireLock() may not work very well over an NFS link, but I figure that if you're trying to do NFS locking, you deserve what you get. ReadDir() - the character string returned should be copied by the calling program if it is to be modified or accessed beyond the next ReadDir() call. CloseDir() is, strictly speaking, normally not necessary. ReadDir() closes the directory automatically when it reaches the end of the directory you're reading. If you call OpenDir() without closing the previous directory, OpenDir() will close it for you. It's preferable to use the opendir() method rather than the scandir() method if possible: - it maps more closely to the interface provided. - it uses less memory (scandir allocates memory to hold all of the names). If the scandir() method is used and a program does a lot of directory scans, I suspect the program could run out of memory eventually. There is nothing about needing to free the memory pointed to by the directory structure, but I find that executing many scandir()'s increase the running image size. On the other hand passing the structure to free() doesn't keep the size from increasing, so I'm not sure what has to be freed. I suppose you have to walk through the structure and free individual entries, but I've never tried it. portlib-1.01/locktest.c010064400017710000151000000043720626753346600166530ustar00junkyarddatamgmt00000400000027/* * locktest - test portlib file-locking functions * * This program tries to acquire a lock. If the lock is obtained * successfully, the program sleeps for 10 seconds, then releases * the lock. To use the program, start one instance, then start * another before the first releases the lock. The first instance * should get the lock, the second instance should fail. When the * first instance exits, start a third instance. The first instance * should successfully acquire a lock. * * Options: * -s n sleep for n seconds instead of default 10 * -f name create file with given name instead of default "lock.test" * * 29 November 1996 * Paul DuBois * dubois@primate.wisc.edu * http://www.primate.wisc.edu/people/dubois/ */ #include #include "portlib.h" #ifndef bufSiz #define bufSiz 1024 #endif static char lockFile[bufSiz] = "lock.test"; static int sleepTime = 10; static char *usage = "Usage: locktest [ -s sleeptime ] [ -f lockfile ]"; int main (argc, argv) int argc; char *argv[]; { FILE *f; --argc; /* skip program name */ ++argv; while (argc > 0 && argv[0][0] == '-') { if (strcmp (argv[0], "-s") == 0) { if (argc < 2) { fprintf (stderr, "%s\n", usage); exit (1); } sleepTime = StrToInt (argv[1]); argc -= 2; argv += 2; } else if (strcmp (argv[0], "-f") == 0) { if (argc < 2) { fprintf (stderr, "%s\n", usage); exit (1); } (void) strcpy (lockFile, argv[1]); argc -= 2; argv += 2; } else { fprintf (stderr, "unknown option: %s\n", argv[0]); fprintf (stderr, "%s\n", usage); exit (1); } } if (argc != 0) { fprintf (stderr, "%s\n", usage); exit (1); } printf ("opening \"%s\" file\n", lockFile); /* * Create file if it doesn't exist, but if it does exist, * don't overwrite the contents. We just want to lock it, * not destroy it. */ if ((f = fopen (lockFile, "a+")) == (FILE *) NULL) { printf ("could not open \"%s\", exiting\n", lockFile); exit (1); } printf ("trying to acquire lock\n"); if (AcquireLock (f) == 0) { printf ("lock not acquired, exiting\n"); (void) fclose (f); exit (1); } printf ("lock acquired successfully\n"); sleep (sleepTime); printf ("releasing lock\n"); ReleaseLock (f); (void) fclose (f); exit (0); } portlib-1.01/Notes010064400017710000151000000007150626753346600156670ustar00junkyarddatamgmt00000400000027For a function that seems to be provided using different calls under different versions of UNIX (e.g., memcpy vs. bcopy), I made up a different name and used that. The portlib code implementing the function then maps onto whichever call is appropriate for the host system. For a function that has the same name on all systems on which it is present, but is simply missing on some systems (e.g., strcasecmp), I use that name and provide code to implement it. portlib-1.01/fd.c010064400017710000151000000004430626753346600154070ustar00junkyarddatamgmt00000400000027/* * MaxFileDesc () * * Returns the maximum number of file descriptors allowed. */ #include "portlib.h" #if HAS_SYSCONF #include int MaxFileDesc () { return (sysconf (_SC_OPEN_MAX)); } # else int MaxFileDesc () { return (getdtablesize ()); } #endif /* HAS_SYSCONF */ portlib-1.01/fdtest.c010064400017710000151000000006510626753346600163100ustar00junkyarddatamgmt00000400000027/* * fdtest - test portlib file-descriptor functions * * This program display the maximum number of file descriptors a system * should have. * * 29 November 1996 * Paul DuBois * dubois@primate.wisc.edu * http://www.primate.wisc.edu/people/dubois/ */ #include #include "portlib.h" int main (argc, argv) int argc; char *argv[]; { printf ("maximum file descriptors = %d\n", MaxFileDesc ()); exit (0); } portlib-1.01/ato.c010064400017710000151000000013760634013772000155700ustar00junkyarddatamgmt00000400000027/* * ato.c - string-to-number conversions. * * The primary reason for these routines is to hide the need to know which * header file to include to get the proper declaration of the underlying * atox() routines. Some systems declare them in math.h, others in stdlib.h. * When using portlib, include portlib.h, call the routines defined below, * and you'll get the correct results. * * This should use strtol() if that is available, probably. */ #include #ifdef __STDC__ #include #else #include #endif short StrToShort (s) char *s; { return ((short) atoi (s)); } int StrToInt (s) char *s; { return (atoi (s)); } long StrToLong (s) char *s; { return (atol (s)); } double StrToDouble (s) char *s; { return (atof (s)); } portlib-1.01/atotest.c010064400017710000151000000022270634013776200164720ustar00junkyarddatamgmt00000400000027/* * atotest - test portlib string-to-number functions * * Syntax: atotest conversion-type string * * conversion-type should be i (int), l (long), or f (floating point). * string is the string to be converted to a number. * The output is the numeric value after conversion. * * 2 December 1996 * Paul DuBois * dubois@primate.wisc.edu * http://www.primate.wisc.edu/people/dubois/ */ #include #include "portlib.h" static char *usage = "Usage: atotest conversion-type string\n\ conversion type should be one of:\n\ i\tinteger\nl\tlong integer\nf\tfloating-point\n"; int main (argc, argv) int argc; char *argv[]; { char *str; int i; long l; double f; --argc; /* skip program name */ ++argv; if (argc != 2) { fprintf (stderr, "%s", usage); exit (1); } str = argv[1]; if (argv[0][0] == 'i' && argv[0][1] == '\0') { i = StrToInt (str); printf ("%d\n", i); exit (0); } if (argv[0][0] == 'l' && argv[0][1] == '\0') { l = StrToLong (str); printf ("%ld\n", l); exit (0); } if (argv[0][0] == 'f' && argv[0][1] == '\0') { f = StrToDouble (str); printf ("%g\n", f); exit (0); } fprintf (stderr, "%s", usage); exit (1); } portlib-1.01/porttest.sh010064400017710000151000000046600626753425000170670ustar00junkyarddatamgmt00000400000027 # Script type: Bourne shell ato=n dir=n fd=n lock=n mem=n if [ $# -eq 0 ]; then # test all functions ato=y dir=y fd=y lock=y mem=y else for a in $*; do case $a in ato) ato=y ;; dir) dir=y ;; fd) fd=y ;; lock) lock=y ;; mem) mem=y ;; *) echo "Usage: $0 [ato] [dir] [fd] [lock] [mem]" 1>&2 ;; esac done fi if [ $ato = y ]; then # test string conversion echo test string conversion err=0 n="12345" res=`./atotest i $n` if [ "$res" != "$n" ]; then echo "$n converted INCORRECTLY as $res" err=`expr $err + 1` fi n="-12345" res=`./atotest i $n` if [ "$res" != "$n" ]; then echo "$n converted INCORRECTLY as $res" err=`expr $err + 1` fi n="123456" res=`./atotest l $n` if [ "$res" != "$n" ]; then echo "$n converted INCORRECTLY as $res" err=`expr $err + 1` fi n="-123456" res=`./atotest l $n` if [ "$res" != "$n" ]; then echo "$n converted INCORRECTLY as $res" err=`expr $err + 1` fi n="1.5" res=`./atotest f $n` if [ "$res" != "$n" ]; then echo "$n converted INCORRECTLY as $res" err=`expr $err + 1` fi n="-1.5" res=`./atotest f $n` if [ "$res" != "$n" ]; then echo "$n converted INCORRECTLY as $res" err=`expr $err + 1` fi if [ $err -eq 0 ]; then echo "*** tests successful" fi fi if [ $dir = y ]; then # test directory reading echo test directory reading err=0 ls=`ls -a . | sort` ls2=`./dirtest . | sort` if [ "$ls" != "$ls2" ]; then echo "test FAILED" err=`expr $err + 1` fi if [ $err -eq 0 ]; then echo "*** tests successful" fi fi if [ $fd = y ]; then # test file descriptor count echo test file descriptor count ./fdtest echo "*** you will have to verify if this is correct yourself" fi if [ $lock = y ]; then # test file locking echo "test file locking (takes a few seconds)" err=0 ./locktest > /dev/null 2>&1& sleep 2 # give locktest time to set lock ./locktest > /dev/null 2>&1 if [ $? -eq 0 ]; then # preceding command should fail! echo "test 1 FAILED" err=`expr $err + 1` fi wait # wait for first locktest to exit ./locktest > /dev/null 2>&1 if [ $? -ne 0 ]; then # preceding command should succeed! echo "test 2 FAILED" err=`expr $err + 1` fi if [ $err -eq 0 ]; then echo "*** tests successful" fi fi if [ $mem = y ]; then # test memory operations echo "test memory operations" err=0 ./memtest > /dev/null 2>&1& if [ $err -eq 0 ]; then echo "*** tests successful" else echo "memory tests FAILED" fi fi exit 0 portlib-1.01/memtest.c010064400017710000151000000022440626753704600164730ustar00junkyarddatamgmt00000400000027/* * memtest - test portlib memory functions * * Does very rudimentary tests. * * 16 Janyary 1997 * Paul DuBois * dubois@primate.wisc.edu * http://www.primate.wisc.edu/people/dubois/ */ #include #include "portlib.h" #define bufSiz 10 int main (argc, argv) int argc; char *argv[]; { char buf1[bufSiz], buf2[bufSiz]; int result; int i; printf ("test BZero..."); for (i = 0; i < bufSiz; i++) buf1[i] = 1; BZero (buf1, 10); result = 1; for (i = 0; i < bufSiz; i++) { if (buf1[i] != 0) result = 0; } printf ("%s\n", result ? "okay" : "NOT okay"); printf ("test BCopy..."); for (i = 0; i < bufSiz; i++) { buf1[i] = 1; buf2[i] = 2; } BCopy (buf1, buf2, 10); result = 1; for (i = 0; i < bufSiz; i++) { if (buf1[i] != buf2[i]) result = 0; } printf ("%s\n", result ? "okay" : "NOT okay"); printf ("test BCmp(1)..."); for (i = 0; i < bufSiz; i++) { buf1[i] = 1; buf2[i] = 1; } printf ("%s\n", BCmp (buf1, buf2, bufSiz) == 0 ? "okay" : "NOT okay"); printf ("test BCmp(1)..."); for (i = 0; i < bufSiz; i++) { buf1[i] = 1; buf2[i] = 2; } printf ("%s\n", BCmp (buf1, buf2, bufSiz) != 0 ? "okay" : "NOT okay"); exit (0); } portlib-1.01/mem.c010064400017710000151000000012500626753557100155700ustar00junkyarddatamgmt00000400000027/* * mem.c - memory operations */ #include "portlib.h" #if HAS_BCOPY /* * Use bcopy(), bzero(), bcmp() */ #include void BCopy (src, dst, n) char *src; char *dst; int n; { bcopy (src, dst, n); } void BZero (s, n) char *s; int n; { bzero (s, n); } int BCmp (s1, s2, n) char *s1; char *s2; int n; { return (bcmp (s1, s2, n)); } # else /* * Use memcpy(), memset(), memcmp() */ #include void BCopy (src, dst, n) char *src; char *dst; int n; { memcpy (dst, src, n); } void BZero (s, n) char *s; int n; { memset (s, '\0', n); } int BCmp (s1, s2, n) char *s1; char *s2; int n; { return (memcmp (s1, s2, n)); } #endif /* HAS_BCOPY */ portlib-1.01/strcasecmp.c010064400017710000151000000066640627457057700171770ustar00junkyarddatamgmt00000400000027/* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific written prior permission. This software * is provided ``as is'' without express or implied warranty. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)strcasecmp.c 5.5 (Berkeley) 11/24/87"; #endif /* LIBC_SCCS and not lint */ #include #ifndef u_char #define u_char unsigned char #endif /* * This array is designed for mapping upper and lower case letter * together for a case independent comparison. The mappings are * based upon ascii character sequences. */ static u_char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; strcasecmp(s1, s2) char *s1, *s2; { register u_char *cm = charmap, *us1 = (u_char *)s1, *us2 = (u_char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return(0); return(cm[*us1] - cm[*--us2]); } strncasecmp(s1, s2, n) char *s1, *s2; register int n; { register u_char *cm = charmap, *us1 = (u_char *)s1, *us2 = (u_char *)s2; while (--n >= 0 && cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return(0); return(n < 0 ? 0 : cm[*us1] - cm[*--us2]); } portlib-1.01/Log010066400017710000151000000002510634013777700153120ustar00junkyarddatamgmt0000040000002728 Mar 97 - Renamed config/mklinuxppc.p-cf to config/linux-pmac.p-cf per similar naming change in WRPRC 2.10 config file distribution. 18 May 97 - Added StrToShort(). portlib-1.01/Changes-1.01010066400017710000151000000000260634014005500164750ustar00junkyarddatamgmt00000400000027- Added StrToShort(). troffcvt-1.04.orig/tarballs/troffcvt-1.04.tar100600 1750 1750 4636000 6431756100 16703 0ustar blpblptroffcvt-1.04/004077500017710000151000000000000634147251600150325ustar00junkyarddatamgmt00000400000027troffcvt-1.04/README010066400017710000151000000053060633344224400157070ustar00junkyarddatamgmt00000400000027The troffcvt distribution contains tools for processing troff files and turning them into other formats. The sample converters included in the distribution are: troff2html troff to HTML troff2rtf troff to RTF unroff troff to text (like deroff, but often better) troff2null troff to nothing (null converter) The distribution also includes tblcvt, a preprocessor for files containing tbl-format table specifications. It turns files into a form that's friendlier to troffcvt than raw tbl output. The pic, eqn, and grap preprocessors are NOT supported (and likely never will be). troffcvt tools are used much like tbl and troff. Suppose you'd normally format a document like this: % troff -ms mydoc.ms > mydoc.out To turn your document into HTML instead, you'd use this command: % troff2html -ms mydoc.ms > mydoc.html Substitute troff2rtf or unroff for troff2html to turn the document into RTF or plain text: % troff2rtf -ms mydoc.ms > mydoc.rtf % unroff -ms mydoc.ms > mydoc.txt If your document contains tables, you might normally format it like this: % tbl mydoc.ms | troff -ms > mydoc.out To produce HTML instead, do this: % tblcvt mydoc.ms | troff2html -ms > mydoc.html troffcvt supports the -ms and -man macro packages best. It supports -me, -mdoc, and -mm less well. The quality of troffcvt conversions is often acceptable, but not always. If you want to find out whether or not troffcvt produces output that is good enough for your purposes, you can use the troffcvt-server mail server to convert some sample documents by mail. Check the following location for instructions: http://www.primate.wisc.edu/software/troffcvt/ In any case, troffcvt should process your documents without crashing. If your documents cause a crash, I'd be interested in finding out why. (Note however that I'll want a copy of your input files. If you are formatting proprietary information and won't let me see it, I can't help you.) ----------------------------------------------------------------------------- What to read: README - this file Prereq.* - installation prerequisites INSTALL - installation instructions Changes-* - summary of release-specific major changes Log - more detailed log of changes Manual pages available (in the man directory): troffcvt.man tblcvt.man troff2html.man troff2rtf.man tc2html.man tc2html-toc.man unroff.man Documents available (in the doc directory): troffcvt.ms overview tblcvt.ms tblcvt notes bugs.ms bug list actions.ms action reference output.ms output format, postprocessor writing tc2html.ms tc2html notes tc2rtf.ms tc2rtf notes groff.ms groff support notes frontend.ms front end writing Questions and comments to: dubois@primate.wisc.edu If you find bugs, please report them. troffcvt-1.04/Prereq.html010066400017710000151000000070440634147251100171530ustar00junkyarddatamgmt00000400000027

This document describes the prerequisite software you'll need to build the troffcvt distribution.

An ANSI C compiler to compile the C code.

Perl. If you want to use tblcvt rather than tbl for preprocessing tbl input (hint: you do, you'll get better results), you'll need Perl 5. The other Perl scripts can use either Perl 4 or Perl 5.

You need imake and related build tools (e.g., makedepend, mkdirhier)

The version of imake you use should be a version at least as recent as the one distributed with the X Window System, Release 6 (X11R6).

If you don't have imake, you can get it by obtaining the itools distribution. This is available at:

   http://http.primate.wisc.edu/software/imake-book/
   ftp://ftp.primate.wisc.edu/software/imake-book/
Build and installation instructions for itools are available at the same location. Look for the "Appendix B" files. These contain the text of Appendix B of the O'Reilly imake book (the "boa book").

You need imboot for bootstrapping Makefiles. imboot is included in the itools distribution, and is also available in standalone form at:

   http://http.primate.wisc.edu/software/imake-stuff/
   ftp://ftp.primate.wisc.edu/software/imake-stuff/
imboot 1.03 was used to build this distribution.

You need msub for building one or more files in this distribution. msub is included in the itools distribution, and is also available in standalone form at:

   http://http.primate.wisc.edu/software/imake-stuff/
   ftp://ftp.primate.wisc.edu/software/imake-stuff/
msub 1.13 was used to build this distribution.

You need the WRPRC imake configuration files

The WRPRC configuration files are available at:

   http://http.primate.wisc.edu/software/imake-stuff/
   ftp://ftp.primate.wisc.edu/software/imake-stuff/
WRPRC release 2.11 was used to build this distribution.

The X11 configuration files are *not* used to build this distribution.

You need some other libraries

This distribution depends on some other libraries, which you should build and install before attempting to build the troffcvt distribution. Each library is built using imake and the WRPRC configuration files. Each is available at:

   http://http.primate.wisc.edu/software/
   ftp://ftp.primate.wisc.edu/software/

The specific libraries you'll need are:

The portlib portability library, available at:

   http://http.primate.wisc.edu/software/portlib/
   ftp://ftp.primate.wisc.edu/software/portlib/
portlib release 1.01 was used to build this distribution.

The ETM (Exception and Termination Manager) library, available at:

   http://http.primate.wisc.edu/software/ETM/
   ftp://ftp.primate.wisc.edu/software/ETM/
ETM release 1.09 was used to build this distribution.

The tokenscan token scanning library, available at:

   http://http.primate.wisc.edu/software/TS/
   ftp://ftp.primate.wisc.edu/software/TS/
tokenscan release 1.08 was used to build this distribution.

The MemMgr memory manager library, available at:

   http://http.primate.wisc.edu/software/MemMgr/
   ftp://ftp.primate.wisc.edu/software/MemMgr/
MemMgr release 1.04 was used to build this distribution.
troffcvt-1.04/Prereq.ms010066400017710000151000000063250634147251000166260ustar00junkyarddatamgmt00000400000027.LP This document describes the prerequisite software you'll need to build the .I troffcvt distribution. .LP An ANSI C compiler to compile the C code. .LP Perl. If you want to use .I tblcvt rather than .I tbl for preprocessing .I tbl input (hint: you do, you'll get better results), you'll need Perl 5. The other Perl scripts can use either Perl 4 or Perl 5. .LP .LP You need \fIimake\fP and related build tools (e.g., \fImakedepend\fP, \fImkdirhier\fP) .LP The version of \fIimake\fP you use should be a version at least as recent as the one distributed with the X Window System, Release 6 (X11R6). .LP If you don't have \fIimake\fP, you can get it by obtaining the \fIitools\fP distribution. This is available at: .Ps http://http.primate.wisc.edu/software/imake-book/ ftp://ftp.primate.wisc.edu/software/imake-book/ .Pe Build and installation instructions for \fIitools\fP are available at the same location. Look for the "Appendix B" files. These contain the text of Appendix B of the O'Reilly imake book (the "boa book"). .LP You need \fIimboot\fP for bootstrapping Makefiles. \fIimboot\fP is included in the \fIitools\fP distribution, and is also available in standalone form at: .Ps http://http.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ .Pe \fIimboot\fP 1.03 was used to build this distribution. .LP You need \fImsub\fP for building one or more files in this distribution. \fImsub\fP is included in the \fIitools\fP distribution, and is also available in standalone form at: .Ps http://http.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ .Pe \fImsub\fP 1.13 was used to build this distribution. .LP You need the WRPRC imake configuration files .LP The WRPRC configuration files are available at: .Ps http://http.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ .Pe WRPRC release 2.11 was used to build this distribution. .LP The X11 configuration files are *not* used to build this distribution. .LP You need some other libraries .LP This distribution depends on some other libraries, which you should build and install before attempting to build the \fItroffcvt\fP distribution. Each library is built using \fIimake\fP and the WRPRC configuration files. Each is available at: .Ps http://http.primate.wisc.edu/software/ ftp://ftp.primate.wisc.edu/software/ .Pe .LP The specific libraries you'll need are: .LP The portlib portability library, available at: .Ps http://http.primate.wisc.edu/software/portlib/ ftp://ftp.primate.wisc.edu/software/portlib/ .Pe portlib release 1.01 was used to build this distribution. .LP The ETM (Exception and Termination Manager) library, available at: .Ps http://http.primate.wisc.edu/software/ETM/ ftp://ftp.primate.wisc.edu/software/ETM/ .Pe ETM release 1.09 was used to build this distribution. .LP The tokenscan token scanning library, available at: .Ps http://http.primate.wisc.edu/software/TS/ ftp://ftp.primate.wisc.edu/software/TS/ .Pe tokenscan release 1.08 was used to build this distribution. .LP The MemMgr memory manager library, available at: .Ps http://http.primate.wisc.edu/software/MemMgr/ ftp://ftp.primate.wisc.edu/software/MemMgr/ .Pe MemMgr release 1.04 was used to build this distribution. troffcvt-1.04/Prereq.ps010066400017710000151000000246160634147251000166340ustar00junkyarddatamgmt00000400000027%!PS-Adobe-3.0 %%Creator: groff version 1.10 %%CreationDate: Fri May 23 23:57:44 1997 %%DocumentNeededResources: font Times-Roman %%+ font Times-Italic %%+ font Courier %%DocumentSuppliedResources: procset grops 1.10 0 %%Pages: 2 %%PageOrder: Ascend %%Orientation: Portrait %%EndComments %%BeginProlog %%BeginResource: procset grops 1.10 0 /setpacking where{ pop currentpacking true setpacking }if /grops 120 dict dup begin /SC 32 def /A/show load def /B{0 SC 3 -1 roll widthshow}bind def /C{0 exch ashow}bind def /D{0 exch 0 SC 5 2 roll awidthshow}bind def /E{0 rmoveto show}bind def /F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def /G{0 rmoveto 0 exch ashow}bind def /H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /I{0 exch rmoveto show}bind def /J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def /K{0 exch rmoveto 0 exch ashow}bind def /L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /M{rmoveto show}bind def /N{rmoveto 0 SC 3 -1 roll widthshow}bind def /O{rmoveto 0 exch ashow}bind def /P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /Q{moveto show}bind def /R{moveto 0 SC 3 -1 roll widthshow}bind def /S{moveto 0 exch ashow}bind def /T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def /SF{ findfont exch [exch dup 0 exch 0 exch neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /MF{ findfont [5 2 roll 0 3 1 roll neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /level0 0 def /RES 0 def /PL 0 def /LS 0 def /MANUAL{ statusdict begin/manualfeed true store end }bind def /PLG{ gsave newpath clippath pathbbox grestore exch pop add exch pop }bind def /BP{ /level0 save def 1 setlinecap 1 setlinejoin 72 RES div dup scale LS{ 90 rotate }{ 0 PL translate }ifelse 1 -1 scale }bind def /EP{ level0 restore showpage }bind def /DA{ newpath arcn stroke }bind def /SN{ transform .25 sub exch .25 sub exch round .25 add exch round .25 add exch itransform }bind def /DL{ SN moveto SN lineto stroke }bind def /DC{ newpath 0 360 arc closepath }bind def /TM matrix def /DE{ TM currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath TM setmatrix }bind def /RC/rcurveto load def /RL/rlineto load def /ST/stroke load def /MT/moveto load def /CL/closepath load def /FL{ currentgray exch setgray fill setgray }bind def /BL/fill load def /LW/setlinewidth load def /RE{ findfont dup maxlength 1 index/FontName known not{1 add}if dict begin { 1 index/FID ne{def}{pop pop}ifelse }forall /Encoding exch def dup/FontName exch def currentdict end definefont pop }bind def /DEFS 0 def /EBEGIN{ moveto DEFS begin }bind def /EEND/end load def /CNT 0 def /level1 0 def /PBEGIN{ /level1 save def translate div 3 1 roll div exch scale neg exch neg exch translate 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit []0 setdash /setstrokeadjust where{ pop false setstrokeadjust }if /setoverprint where{ pop false setoverprint }if newpath /CNT countdictstack def userdict begin /showpage{}def }bind def /PEND{ clear countdictstack CNT sub{end}repeat level1 restore }bind def end def /setpacking where{ pop setpacking }if %%EndResource %%IncludeResource: font Times-Roman %%IncludeResource: font Times-Italic %%IncludeResource: font Courier grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron /scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent /ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen /period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon /semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O /P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex /underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y /z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft /guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl /endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut /dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash /quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen /brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft /logicalnot/minus/registered/macron/degree/plusminus/twosuperior /threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior /ordmasculine/guilsinglright/onequarter/onehalf/threequarters /questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE /Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn /germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash /ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def /Courier@0 ENC0/Courier RE/Times-Italic@0 ENC0/Times-Italic RE /Times-Roman@0 ENC0/Times-Roman RE %%EndProlog %%Page: 1 1 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(This document describes the prerequisite softw) 72 84 Q(are you')-.1 E(ll need to b)-.1 E(uild the)-.2 E/F1 10 /Times-Italic@0 SF(tr)2.5 E(of)-.45 E(fcvt)-.18 E F0(distrib)2.5 E (ution.)-.2 E(An ANSI C compiler to compile the C code.)72 104.4 Q 3.642 (Perl. If)72 124.8 R 1.142(you w)3.642 F 1.142(ant to use)-.1 F F1 (tblcvt)3.642 E F0 1.142(rather than)3.642 F F1(tbl)3.642 E F0 1.142 (for preprocessing)3.642 F F1(tbl)3.641 E F0 1.141 (input \(hint: you do, you')3.641 F 1.141(ll get better)-.1 F (results\), you')72 136.8 Q(ll need Perl 5.)-.1 E (The other Perl scripts can use either Perl 4 or Perl 5.)5 E -1.1(Yo)72 165.6 S 2.5(un)1.1 G(eed)-2.5 E F1(imak)2.5 E(e)-.1 E F0(and related b) 2.5 E(uild tools \(e.g.,)-.2 E F1(mak)2.5 E(edepend)-.1 E F0(,)A F1 (mkdirhier)2.5 E F0(\))A .53(The v)72 186 R .53(ersion of)-.15 F F1 (imak)3.03 E(e)-.1 E F0 .53(you use should be a v)3.03 F .53 (ersion at least as recent as the one distrib)-.15 F .53 (uted with the X W)-.2 F(in-)-.4 E(do)72 198 Q 2.5(wS)-.25 G (ystem, Release 6 \(X11R6\).)-2.5 E(If you don')72 218.4 Q 2.5(th)-.18 G -2.25 -.2(av e)-2.5 H F1(imak)2.7 E(e)-.1 E F0 2.5(,y)C (ou can get it by obtaining the)-2.5 E F1(itools)2.5 E F0(distrib)2.5 E 2.5(ution. This)-.2 F(is a)2.5 E -.25(va)-.2 G(ilable at:).25 E/F2 8 /Courier@0 SF(http://http.primate.wisc.edu/software/imake-book/)92 236.8 Q(ftp://ftp.primate.wisc.edu/software/imake-book/)92 246.8 Q F0 .375 (Build and installation instructions for)72 267.2 R F1(itools)2.875 E F0 .374(are a)2.875 F -.25(va)-.2 G .374(ilable at the same location.).25 F .374(Look for the "Appendix B")5.374 F 2.5(\214les. These)72 279.2 R (contain the te)2.5 E(xt of Appendix B of the O'Reilly imak)-.15 E 2.5 (eb)-.1 G(ook \(the "boa book"\).)-2.5 E -1.1(Yo)72 311.6 S 4.097(un)1.1 G(eed)-4.097 E F1(imboot)4.097 E F0 1.597(for bootstrapping Mak)4.097 F (e\214les.)-.1 E F1(imboot)6.597 E F0 1.597(is included in the)4.097 F F1(itools)4.098 E F0(distrib)4.098 E 1.598(ution, and is also)-.2 F -.2 (av)72 323.6 S(ailable in standalone form at:)-.05 E F2 (http://http.primate.wisc.edu/software/imake-stuff/)92 342 Q (ftp://ftp.primate.wisc.edu/software/imake-stuff/)92 352 Q F1(imboot)72 372.4 Q F0(1.03 w)2.5 E(as used to b)-.1 E(uild this distrib)-.2 E (ution.)-.2 E -1.1(Yo)72 404.8 S 2.505(un)1.1 G(eed)-2.505 E F1(msub) 2.505 E F0 .005(for b)2.505 F .005 (uilding one or more \214les in this distrib)-.2 F(ution.)-.2 E F1(msub) 5.004 E F0 .004(is included in the)2.504 F F1(itools)2.504 E F0(distrib) 2.504 E(ution,)-.2 E(and is also a)72 416.8 Q -.25(va)-.2 G (ilable in standalone form at:).25 E F2 (http://http.primate.wisc.edu/software/imake-stuff/)92 435.2 Q (ftp://ftp.primate.wisc.edu/software/imake-stuff/)92 445.2 Q F1(msub)72 465.6 Q F0(1.13 w)2.5 E(as used to b)-.1 E(uild this distrib)-.2 E (ution.)-.2 E -1.1(Yo)72 498 S 2.5(un)1.1 G(eed the WRPRC imak)-2.5 E 2.5(ec)-.1 G(on\214guration \214les)-2.5 E (The WRPRC con\214guration \214les are a)72 518.4 Q -.25(va)-.2 G (ilable at:).25 E F2(http://http.primate.wisc.edu/software/imake-stuff/) 92 536.8 Q(ftp://ftp.primate.wisc.edu/software/imake-stuff/)92 546.8 Q F0(WRPRC release 2.11 w)72 567.2 Q(as used to b)-.1 E(uild this distrib) -.2 E(ution.)-.2 E(The X11 con\214guration \214les are *not* used to b) 72 587.6 Q(uild this distrib)-.2 E(ution.)-.2 E -1.1(Yo)72 620 S 2.5(un) 1.1 G(eed some other libraries)-2.5 E .642(This distrib)72 640.4 R .643 (ution depends on some other libraries, which you should b)-.2 F .643 (uild and install before attempting to)-.2 F -.2(bu)72 652.4 S(ild the) .2 E F1(tr)2.5 E(of)-.45 E(fcvt)-.18 E F0(distrib)2.5 E 2.5(ution. Each) -.2 F(library is b)2.5 E(uilt using)-.2 E F1(imak)2.5 E(e)-.1 E F0 (and the WRPRC con\214guration \214les.)2.5 E(Each is)5 E -.2(av)72 664.4 S(ailable at:)-.05 E F2(http://http.primate.wisc.edu/software/)92 682.8 Q(ftp://ftp.primate.wisc.edu/software/)92 692.8 Q EP %%Page: 2 2 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(-2-)282.17 48 Q(The speci\214c libraries you')72 84 Q(ll need are:)-.1 E(The portlib portability library)72 104.4 Q 2.5 (,a)-.65 G -.25(va)-2.7 G(ilable at:).25 E/F1 8/Courier@0 SF (http://http.primate.wisc.edu/software/portlib/)92 122.8 Q (ftp://ftp.primate.wisc.edu/software/portlib/)92 132.8 Q F0 (portlib release 1.01 w)72 153.2 Q(as used to b)-.1 E(uild this distrib) -.2 E(ution.)-.2 E(The ETM \(Exception and T)72 185.6 Q (ermination Manager\) library)-.7 E 2.5(,a)-.65 G -.25(va)-2.7 G (ilable at:).25 E F1(http://http.primate.wisc.edu/software/ETM/)92 204 Q (ftp://ftp.primate.wisc.edu/software/ETM/)92 214 Q F0 (ETM release 1.09 w)72 234.4 Q(as used to b)-.1 E(uild this distrib)-.2 E(ution.)-.2 E(The tok)72 266.8 Q(enscan tok)-.1 E(en scanning library) -.1 E 2.5(,a)-.65 G -.25(va)-2.7 G(ilable at:).25 E F1 (http://http.primate.wisc.edu/software/TS/)92 285.2 Q (ftp://ftp.primate.wisc.edu/software/TS/)92 295.2 Q F0(tok)72 315.6 Q (enscan release 1.08 w)-.1 E(as used to b)-.1 E(uild this distrib)-.2 E (ution.)-.2 E(The MemMgr memory manager library)72 348 Q 2.5(,a)-.65 G -.25(va)-2.7 G(ilable at:).25 E F1 (http://http.primate.wisc.edu/software/MemMgr/)92 366.4 Q (ftp://ftp.primate.wisc.edu/software/MemMgr/)92 376.4 Q F0 (MemMgr release 1.04 w)72 396.8 Q(as used to b)-.1 E(uild this distrib) -.2 E(ution.)-.2 E EP %%Trailer end %%EOF .notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/space/extroffcvt-1.04/Prereq.tmpl010066400017710000151000000016050634122724100171560ustar00junkyarddatamgmt00000400000027.LP This document describes the prerequisite software you'll need to build the .I troffcvt distribution. .LP An ANSI C compiler to compile the C code. .LP Perl. If you want to use .I tblcvt rather than .I tbl for preprocessing .I tbl input (hint: you do, you'll get better results), you'll need Perl 5. The other Perl scripts can use either Perl 4 or Perl 5. .LP #itools-info# #imboot-info# #msub-info# .LP You need the WRPRC imake configuration files #wrprc-config-info# .LP You need some other libraries .LP This distribution depends on some other libraries, which you should build and install before attempting to build the \fItroffcvt\fP distribution. Each library is built using \fIimake\fP and the WRPRC configuration files. Each is available at: .Ps %software-http-url% %software-ftp-url% .Pe .LP The specific libraries you'll need are: #portlib-info# #etm-info# #tokenscan-info# #memmgr-info# troffcvt-1.04/Prereq.txt010066400017710000151000000060520634147251100170240ustar00junkyarddatamgmt00000400000027 This document describes the prerequisite software you'll need to build the troffcvt distribution. An ANSI C compiler to compile the C code. Perl. If you want to use tblcvt rather than tbl for preprocessing tbl input (hint: you do, you'll get better results), you'll need Perl 5. The other Perl scripts can use either Perl 4 or Perl 5. You need imake and related build tools (e.g., makedepend, mkdirhier) The version of imake you use should be a version at least as recent as the one distributed with the X Window System, Release 6 (X11R6). If you don't have imake, you can get it by obtaining the itools distribution. This is available at: http://http.primate.wisc.edu/software/imake-book/ ftp://ftp.primate.wisc.edu/software/imake-book/ Build and installation instructions for itools are available at the same location. Look for the "Appendix B" files. These contain the text of Appendix B of the O'Reilly imake book (the "boa book"). You need imboot for bootstrapping Makefiles. imboot is included in the itools distribution, and is also available in standalone form at: http://http.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ imboot 1.03 was used to build this distribution. You need msub for building one or more files in this distribution. msub is included in the itools distribution, and is also available in standalone form at: http://http.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ msub 1.13 was used to build this distribution. You need the WRPRC imake configuration files The WRPRC configuration files are available at: http://http.primate.wisc.edu/software/imake-stuff/ ftp://ftp.primate.wisc.edu/software/imake-stuff/ WRPRC release 2.11 was used to build this distribution. The X11 configuration files are *not* used to build this distribution. You need some other libraries This distribution depends on some other libraries, which you should build and install before attempting to build the troffcvt distribution. Each library is built using imake and the WRPRC configuration files. Each is available at: http://http.primate.wisc.edu/software/ ftp://ftp.primate.wisc.edu/software/ The specific libraries you'll need are: The portlib portability library, available at: http://http.primate.wisc.edu/software/portlib/ ftp://ftp.primate.wisc.edu/software/portlib/ portlib release 1.01 was used to build this distribution. The ETM (Exception and Termination Manager) library, available at: http://http.primate.wisc.edu/software/ETM/ ftp://ftp.primate.wisc.edu/software/ETM/ ETM release 1.09 was used to build this distribution. The tokenscan token scanning library, available at: http://http.primate.wisc.edu/software/TS/ ftp://ftp.primate.wisc.edu/software/TS/ tokenscan release 1.08 was used to build this distribution. The MemMgr memory manager library, available at: http://http.primate.wisc.edu/software/MemMgr/ ftp://ftp.primate.wisc.edu/software/MemMgr/ MemMgr release 1.04 was used to build this distribution. troffcvt-1.04/INSTALL010064400017710000151000000063270633344217600160660ustar00junkyarddatamgmt00000400000027Installation guide for troffcvt distribution -------------------------------------------------------------------------- 1) Consider whether or not you really want to try to build the troffcvt distribution. The process is non-trivial unless you already have all the other prerequisite pieces. If you want to find out whether or not troffcvt produces output that is good enough for your purposes, you can use the troffcvt-server mail server to convert some sample documents by mail. Check the following location for instructions: http://www.primate.wisc.edu/software/troffcvt/ Should you decide to go ahead, the troffcvt distribution is available from the same location as a gzip'ed tar file. Unzip and extract the distribution: % gunzip < troffcvt-X.YY.tar.gz | tar xf - where X.YY is the current release number. 2) You'll need some prerequisite software to build the distribution. See one of the Prereq.{html,ps,txt} files for information about the prerequisites upon which the troffcvt distribution depends. 3) Familiarize yourself with the distribution layout. The primary directories are: config Project-specific imake configuration files doc General documentation h Header files lib General library files libmac Macintosh-specific library files (unusable) libunix UNIX-specific library files man manual pages misc Odds and ends post Postprocessor source tblcvt tblcvt source troffcvt troffcvt source 4) Build the troffcvt distribution. First take a look in the config directory and see if there's anything in the configuration files that you want to modify. Then in the distribution top-level directory, build the software with this command: % make World If that doesn't work, try these commands: % imboot -C WRPRC2 % make Makefiles % make clean % make depend % make all When the build process is done, you should have these programs: troffcvt tblcvt tc2html tc2html-toc tc2rtf tc2text tc2null troff2html troff2rtf unroff troff2null 5) Test troffcvt: % cd troffcvt/tests % runtest This should run a bunch of test files through troffcvt and compare the output with the expected output, printing "OK" or "*** NOT OK ***" for each. You want to see "OK" for each. If a test doesn't produce that result, try: % runtest -d testname which will run the test and show you a "diff" output for the expected and actual result. If the difference is simply that the pathname of a macro or action file being processed is different on my machine and yours, the test result is okay. Otherwise there may be a real problem. 6) In the post (postprocessor) directory, you may want to modify tcr-fonts, html-fonts, and rtf-fonts to reflect typefaces locally available at your site. You may want to modify html-specials, text-specials, and rtf-spec-* to reflect special characters available in versions of troff at your site. You can edit these files to modify the output that you get from the postprocessors for particular fonts and special characters, without making any changes to the postprocessors themselves. 7) Install the distribution: % make install -------------------------------------------------------------------------- Questions and comments to: dubois@primate.wisc.edu If you find bugs, please report them. troffcvt-1.04/Changes-1.01010064400017710000151000000043530626662670700167130ustar00junkyarddatamgmt00000400000027Changes to troffcvt distribution for release 1.01. (1.00 was the original unnumbered beta) troffcvt is known to still have severe problems with -mm, but at least it doesn't go into infinite recursion anymore. Fixed macro body scanner to look for the proper control character on the terminating line. (Was looking for curCtrlChar, not ctrlChar.) Added debug-flag and dump-macro actions. Fake requests can be defined in the actions file to make these available from within troff files. Documentation is somewhat more complete. .rm and .rn allow up to 40 arguments now. Some additional registers are supported: .b, .c, c., $$, .R Fixed bug whereby .nr for existing register didn't carry forward increment value if increment param was missing on new .nr request. Fixed \w bug - was picking up any unit character after closing delimiter; shouldn't have been. Same bug occurred with \h, \v and \x, too. The line-drawing sequences \l and \L are supported (but incompletely) now. troffcvt control output lines \motion c N and \line c N are now \motion N c and \line N c [rep] (rep is the repetition character if specified). Better handling of escaped \x and special \(xx characters when given in odd places (like ".cc \(*a") ParseNameRef doesn't allow whitespace, fixing problems which occur when "\f " is given. tc2rtf special character file rtf-specials now split up into one file per character set. The four-file thing is more unwieldy but gets around a couple of ugly problems. tc2rtf and troff2rtf support options to allow desired character set to be specified (Macintosh set still default and is most complete.) Further imake-ized configuration information. Changed meaning of "\space-size N" in troffcvt output. N was formerly expressed as the space size in basic units. That's incorrect as the space size depends on the current value of 1 em (and thus point size). Now N is number of 1/36th ems. This means postprocessors should recompute space size whenever point size changes. Motion support from Dave Davey added. Changed troffcvt action names {control,special,text}-output to to output-{control,special,text} (so they'd group together in actions.ms :-)). tc2rtf.c significantly reorganized to handle paragraph formatting properties better (putatively). troffcvt-1.04/Changes-1.02010064400017710000151000000027020626662671000167020ustar00junkyarddatamgmt00000400000027Changes to troffcvt distribution for release 1.02. setget.c: Prior to this version, indent, page offset, line length, title length and line spacing were clipped for purposes of writing an output value, but the actual parameter value was stored internally. Now the internal value is clipped, too. This means, for instance, that the internal indent is never negative. The -mac option to troff2rtf/tc2rtf was ambiguous (was intended to select Macintosh character set, could be taken as "read macro package "ac"). Changed troff2rtf/tc2rtf to take -cs charset option, where charset is ansi, mac, pc, pca. Uglier but unambiguous. rtf-fonts (for tc2rtf) has a few more entries in it, for the \pc character set, courtesy Dave Davey. The value of the split/join option for tc2text is now split, not join. This makes it easier to use for viewing on terminals and sending mail. The -split option also now takes a following number to specify the split length. (Either -split30 or -split 30 are allowable.) tc2text tries to draw horizontal lines by putting out '-' characters now. General: some lint fluff taken out. Handling of -me's .(x and .)x macros was botched, which turned out to be... Macro body scanning was broken: the check for the end-of-body sequence terminated when the sequence was matched, but did not check that it was at the end of the input line. So "..." would match "..", for instance, when it shouldn't have. More special chars added to rtf-spec-mac. troffcvt-1.04/Changes-1.03010064400017710000151000000016210626662671000167020ustar00junkyarddatamgmt00000400000027Changes to troffcvt distribution for release 1.03. Distribution is now configured with the WRPRC2 (Release 2) imake configuration files, not the WRPRC (Release 1) files. troffcvt: Doesn't announce when it's reading from stdin anymore. This reduces stderr noise for other programs that invoke troffcvt and check error output to see if it's empty or not. AWriteText() had an infinite-loop bug. Added several special-char's from Dave Davey. tc2rtf.c: Two of the variable initializations (lineLen, pageWid) were changed to cope with dumb compiler that doesn't allow integral variables to be initialized from non-integral expressions. cs-argument parsing didn't pick up first character of charset name (off-by-one error). troff2rtf: Passes -troff to troffcvt now. Fixed bug in passing rargs to tc2rtf. Added several special characters from Dave Davey to rtf-spec-mac. unroff: Passes -nroff to troffcvt now. troffcvt-1.04/Changes-1.04010064400017710000151000000076360634111546600167120ustar00junkyarddatamgmt00000400000027Changes to troffcvt distribution for release 1.04. The most important changes are the addition of troff2html (a new translator for converting troff to HTML), tblcvt (a preprocessor for tbl input so that postprocessors can provide better tbl support) and the implementation of a number of groff features. See doc/groff.ms for a list of groff features now supported by troffcvt. Other changes are listed below: - The distribution has been reorganized. The major directories are: h header files lib general-purpose library and reader library stuff libunix UNIX-specific library stuff libmac Macintosh-specific library stuff troffcvt source for troffcvt post source for postprocessors doc general documentation man manual pages config troffcvt-specific imake configuration files misc other stuff - 8-bit input characters (in the range 128-255) are allowed now. - There is no longer a limitation of 255 special characters. - Added -A option to troffcvt to suppress reading of default action file. - Added -C option to troffcvt to enable compatibility mode (like -C in groff) Incompatibilities: Some options have changed: - The troffcvt -nroff and -troff options are now specified using the -t (formatter type) option as -t nroff and -t troff. - The options for tc2text (and thus unroff), and tc2rtf (and thus troff2rtf) have changed. - Some internal names for special characters were changed. For the most part, the new names match the PostScript names: Old: New: @A-acute @Aacute @A-dieresis @Adieresis @A-grave @Agrave @E-acute @Eacute @E-dieresis @Edieresis @E-grave @Egrave @I-acute @Iacute @I-dieresis @Idieresis @I-grave @Igrave @O-acute @Oacute @O-dieresis @Odieresis @O-grave @Ograve @U-acute @Uacute @U-dieresis @Udieresis @U-grave @Ugrave @Y-acute @Yacute @Y-dieresis @Ydieresis @a-acute @aacute @a-dieresis @adieresis @a-grave @agrave @acute-accent @acute @approximately-equal @approxequal @approximates @similar @bell-system-logo @bell @bold-vertical @bv @box-vertical-rule @br @cap @intersection @cup @union @daggerdbl @daggerdbl @digit-space @digitspace @down-arrow @arrowdown @e-acute @eacute @e-dieresis @edieresis @e-grave @egrave @em-dash @emdash @empty-set @emptyset @footmark @minute @grave-accent @grave @greater-equal @greaterequal @hard-space @hardspace @i-acute @iacute @i-dieresis @idieresis @i-grave @igrave @identically-equal @equivalence @improper-subset @reflexsubset @improper-superset @reflexsuperset @ldblquote @quotedblleft @left-arrow @arrowleft @left-bottom-bracket @braceleftbt @left-ceiling-bracket @bracketlefttp @left-center-bracket @braceleftmid @left-floor-bracket @bracketleftbt @left-hand @handleft @left-top-bracket @bracelefttp @less-equal @lessequal @ligature-ff @ff @ligature-ffi @ffi @ligature-ffl @ffl @ligature-fi @fi @ligature-fl @fl @lsglquote @quoteleft @math-equals @equalmath @math-plus @plusmath @math-star @asteriskmath @member-of @element @n-tilde @ntilde @not @logicalnot @not-equal @notequal @o-acute @oacute @o-dieresis @odieresis @o-grave @ograve @o-slash @oslash @one-half @onehalf @one-quarter @onequarter @opt-hyphen @opthyphen @or @bar @partial-derivative @partialdiff @plus-minus @plusminus @rdblquote @quotedblright @right-arrow @arrowright @right-bottom-bracket @bracerightbt @right-ceiling-bracket @bracketrighttp @right-center-bracket @bracerightmid @right-floor-bracket @bracketrightbt @right-hand @handright @right-top-bracket @bracerighttp @root-extender @radicalex @rsglquote @quoteright @rule @ru @sixth-space @sixthspace @square-root @radical @subset @propersubset @superset @propersuperset @terminal-sigma @sigma1 @three-fourths @threequarters @twelfth-space @twelfthspace @u-acute @uacute @u-dieresis @udieresis @u-grave @ugrave @underrule @ul @up-arrow @arrowup @y-acute @yacute @y-dieresis @ydieresis @zero-space @zerospace @field-begin @fieldbegin @field-end @fieldend @field-pad @fieldpad troffcvt-1.04/Log010064400017710000151000000644710634137037600155060ustar00junkyarddatamgmt0000040000002714 Apr 94 - Created directories h, lib, libunix, and libmac. h holds header files, lib holds the general and reader libraries libtcgen.a and libtcread.a, libunix holds UNIX-specific stuff in libtcunix.a. libmac holds source used only by Macintosh versions of the translators (which don't exist yet). Some stuff is shared by both troffcvt and the postprocessors, so that goes in libtcgen.a. - Abolished TCRStrToNum(). Instead use one of the functions in lib/math.c. 15 Apr 94 - Renamed tcr.h -> tcread.h - New global variable (long tcrLineNum) for the reader stuff, to indicate input line number. *** NOTE that it's not incremented properly yet *** - TCRInit() should now be called by postprocessors once per input file, to reset tcrLineNum properly. - HAVEGETPID configuration parameter is gone now. The GetPid() function now exists in different forms in the libunix and libmac libraries. [[ ... long gap in active development ... ]] 15 Dec 96 - Use portlib string-to-number routines instead of the ones in lib/math.c. 16 Dec 96 - Enable recognition of long request names, and long string and register references like \*[xxx] and \n[xxx]. This helps with translation of input intended for groff. - Add -C option to troffcvt to turn on compatibility mode (disables recognition of long names). It's like groff's -C option. - Add .C register, which is 1 if compatibility mode is on, off otherwise. 20 Dec 96 - Instantiated new type XChar (extended type), which is typedef'ed as an unsigned long. It's an unsigned type wide enough to encode information about any input character (plain, escaped, or special char) in a single scalar value. This way I can avoid encoding non-standard characters in a sequence of bytes. - Low-level input functions now return type XChar rather than int. - Renamed Bug() macro to Debug(). 21 Dec 96 - There is no longer a limit of 255 special characters. 23 Dec 96 - Making full conversion from using UChar (unsigned char) to XChar (unsigned long) for internal character type. This is such a pervasive change, and has so many implications, that I'm also switching to using prototyped functions. This means troffcvt won't compile under non-ANSI compilers anymore. That may break it on some systems, I guess, but I really need to have the compiler tell me when I'm passing the wrong argument type or the conversion will drive me nuts. 26 Dec 96 - Renamed TCSetOpenLibFileProc() and TCOpenLibFile() to TCRSetOpenLibFileProc() and TCROpenLibFile(). - ToEsc() has always had a panic triggered to go off it it's called with a special character code as an argument. I've now put a similar panic into FromEsc(); I don't see anywhere that it should be called with a special character code, but I want to be sure. - Added FileInfo() function that returns a string consisting of the current input filename and line number. Useful for making error messages more informative. 28 Dec 96 - Added support for building troffcvt distribution on FreeBSD and MkLinux. - Parameterized how troffcvt constructs system macro filenames for handling command-line arguments like -me and -ms. Usually these files have names like tmac.e and tmac.s, but under Solaris they seem to be named just e and s. - Modified the way troffcvt interprets command line arguments. Formerly, it read setup files (action or macro files) named by -a or -m options as soon as the option was pulled from the command line. Also, the -r option, if one was given, had to be given before any -a or -m options. This is no longer necessary, because instead of reading setup files as they're found, troffcvt keeps a list of pointers to them. After all the option arguments have been examined, it reads the setup files. After the setup files have been read it proceeds to read any other input files named on the command line. - Eliminated troffcvt -troff and -nroff options. Now they should be specified as -t troff or -t nroff (t = formatter type). Also, the option -t groff is now recognized (see next item below). I changed the option structure to avoid using up more initial option letters each time a new formatter type is added. This way only -t is used. - Added -t groff option to troffcvt. This defines the .g read-only register, which keeps troffcvt from aborting on gtbl output or when using groff macro packages. (gtbl output and the groff macro packages test for the .g register and abort if it's not set.) -t groff is also intended to make troffcvt act like groff in other ways, but I haven't implemented other ways yet...check the list below for future groff-related entries. - Added ASetCompatibility() function and "req cp" line in actions file to implement the groff .cp request for setting compatibility mode on the fly. This is needed to keep troffcvt from dying while reading the groff tmac.e file. But the "req cp" line in the actions file should probably really be interpreted only if the -t groff flag was specified...??? - Add -A option to troffcvt to suppress reading default action file. 30 Dec 96 - Changed tl action to have "title $1 $2 $3" in the post-parsing part. - The troffcvt output format for three-part titles is different, too. It's now incompatible with earlier format. However, this should present little problem to postprocessors; three-part title output was never implemented before, so postprocessors are unlikely to have tried to do anything with them. 02 Jan 97 - Allow special character references of the form \[xxx]. That is, allow special characters with long names. These are disallowed in compatibility mode. 03 Jan 97 - Modified handling of the .bd request; previously ".bd S F N" was parsed correctly, but ".bd S N" was not. The "parse-s" action has been replaced by the "parse-embolden" action, and the AParseS() function has been replaced by AParseEmbolden(), which parses all of the .bd request arguments, not just the "S". This change is probably of minimal impact; very little is done with this request by postprocessors. - Began work on tc2html, a postprocessor for producing HTML. 06 Jan 97 - Added \pass (pass-through) control to troffcvt reader. Action files can use this as: output-control "pass anything" to cause: \pass anything to appear in troffcvt output. Postprocessors can do what they like with "anything" (which is parsed into rargv[] as a single argument, but normally it should be dumped unchanged to the output. - Added \other control to troffcvt reader. Action files can use this as output-control "other arg1 arg2 ..." to cause \other arg1 arg2 ... to appear in troffcvt output. Postprocessors can do what they like with the arguments, but typically \other indicates the presence of unrecognized requests. - Added ADumpBadRequests() action function, which can be used to turn dumping of unrecognized requests on or off with "dump-bad-requests 1" or "dump-bad-requests 0". An input line beginning with an unrecognized request will then appear in the output as: \comment bad-req: original-line-here 08 Jan 97 - Added ADumpInputStack() action function, which writes information about the input stack to stderr. It can be accessed using "dump-input-stack" in an action file, which can be useful for debugging. For example, if you use the following line in an action file, you can dump the input stack with .dump_stack requests: req dump_stack eol dump-input-stack - Changed how the push-string action works. Formerly this just pushed a string onto the input stack. The problem with this is that the string didn't actually get processed until after the action list was finished. Suppose you had an action list like this: break push-string "this is a line\n" break The break would be executed, then "abc" should be shoved on the input stack, another break would be executed, and the action would be over. Then the string on the input stack would finally be processed. Furthermore, if you had an action list like this: push-string "line 1\n" push-string "line 2\n" the output that would result would be "line 2 line 1" because the strings would be processed in first-in last-out order. Now any string put on the stack is processed immediately. This means you can put it anywhere in an action list and expect it to be processed where it occurs. 09 Jan 97 - Began changing "non-parsing" terminology to "post-parsing" in doc/actions.ms (and will change anywhere else it occurs). "post" is more descriptive of the fact that these actions are executed after request arguments are parsed. 14 Jan 97 - Fixed bug of erroneously pushing back newline after processing conditional if newline was not the last char read (could be endOfInput, e.g., if the conditional was provided by a push-string of a string that didn't end in newline). Now push back newline or endOfInput, whichever was the last char read. - tc2html produces "okay" output now. That is, it can HTML-ize all the documents in the doc directory pretty well. Not sure how well it does in the general case yet. The biggest difficulty is that to use tc2html with input intended for a given macro package, you need to write a troffcvt action file that redefines the structure-related macros to produce produce \html output lines that tc2html can recognize. Once this is done, though, it should be able to do pretty well for most documents formatted using that macro package. - Added "flush" action to troffcvt. It's like "break" but doesn't write any \break, i.e., it just flushes any pending output if there is any. This allows you to guarantee that the next stuff written will be on a new line (e.g., if you write a \pass xxx action to write xxx to the output literally). 16 Jan 97 - Fixed crashing bug if macro argument \$0 occurred. Arguments are supposed to be \$1 .. \$9, but I had an off-by-one error on the bounds check, which was triggered by some groff macros which use \$0 to mean the macro name. Boom. Probably should at some point just implement \$0 to do with groff does. - troff input files can refer to \$* and \$* in a macro to refer to all the macro arguments concatenated and space-separated. \$@ additionally puts double quotes around each argument. - Actions can now refer to $* and $@, which produce a string consisting of all request arguments concatenated and space-separated. $@ additionally puts double quotes around each argument. - Fixed following bug: When a request is processed, the arguments are parsed and put in an array. If the request's post-parsing action list includes a push-string action and the string pushed contains a request, processing the request replaces the argument array with the new arguments. Any further argument references in actions for the original request then refer to the most recently seen arguments! The fix is to save the current argument information before processing a request, and restore it afterward. See parse.c/ProcessRequest(). 18 Jan 97 - Allow \$0 inside macros to refer to the macro name, a la groff. - Implement the groff .mso request. This is done using the new troffcvt action push-macro-file, which is like push-file, except that troffcvt looks for the filename in the same places it looks for a macro file. Note that this will not be *quite* the same as in groff, because if a file of the desired name is found in the troffcvt library directory before it's found elsewhere, it will be used. - doc/actions.ms says that the argument array passed to action procedures has a NULL pointer at the end. In fact, no NULL pointer has ever been added. Fixed now. - troffcvt/parse.c no longer keeps a separate buffer for the request name. Instead it just parses the name into the rargv[] array like all the other arguments. - troffcvt now allows 99 macro arguments rather than just 9. Along with this, you can refer to macro arguments using \$(nn or \$[nnn], not just \$n. 20 Jan 97 - I just discovered that both troff and groff do the following. If you define a macro xx, and then refer to it like a string using \*(xx, the macro gets executed. I guess this is because macros and strings share the same namespace. Still, it seems weird to me. Nevertheless, both troff and groff seem to do this. So troffcvt does it now, too. This makes troffcvt handle the groff -man package a lot better because groff's tmac.an deliberately uses this trick. [see also 16 Mar 97 entry] - Implement groff ".shift" request for troffcvt. New action shift-args is used for this. - Implement groff ".do" request for troffcvt. New action process-do is used for this. - Fixed bug where a macro's arguments weren't accessible unless the macro was the current input source. For instance, if a file was .so'ed from within the macro and the file referenced \$1, the macro's first argument wasn't being seen. 23 Jan 97 - Started working on implementing aliases such as groff has (for the .aln and .als requests). This will involve some changes to the data structures used for requests, macros, strings, and registers. In particular, the underlying structure for macros and registers has a pointer back to the structure holding the name. This won't work because with aliases, multiple names will be able to point to the same underlying structure. (And that structure can't point back to them all.) The reason for these backpointers is so that the name associated with a structure can be obtained, so the code has to be reworked to allow the name to be gotten differently. - Fixed memory leak related to deferred removal of macros that got redefined while they were executing. (Had the code in there to handle this case, but it didn't work!) 24 Jan 97 - Eliminated the -tgroff command line option; the groff extensions are now the default. - Fixed memory leak with .rn xx yy -- if yy already existed, it wasn't being removed before renaming xx to yy. This also had the problem that if you then removed the new yy, the old yy was still in the namelist and could reappear! - Finished implementing the .aln and .als requests, using the alias-register and alias-macro actions (the latter also applies to request and string names). 28 Jan 97 - Turns out I hadn't implemented aliases correctly. In groff, if you redefine a macro (string, etc.), any aliases are *also* redefined. Fixed this. - Wrote a script "runtest" (built in the troffcvt directory, run in the troffcvt/tests directory) that'll run troffcvt with a given input file and compare it to the expected result. The input and results file must both be in the tests directory, named xxx and xxx.result, for some xxx. This is useful for regression testing when I change code that affects something I know used to work and makes it easier to find bugs. 30 Jan 97 - Added table-of-contents stuff to tc2html, so that you can have a clickable TOC at the top of the document which links to all the sections in the document. 04 Feb 97 - Fixed crashing bug which could occur if a request was removed by its own action list. To prevent this from occurring, I now increment the use count on the request object while the action lists are being executed, and release the use afterward. (Similar to the mechanism that prevents crashes of a macro that happens to remove or redefine itself as it executes.) 05 Feb 97 - Started working on tblcvt, a tbl preprocessor that has much the same goal as troffcvt: to convert one form of input to output that's easier to parse. - Simplified the implementation of strings and macros by not maintaining a separate "String" type. Now a string is just a macro without arguments. (Internally, both strings and macros were simply a source of input. Furthermore, troff allows .am to a string name and .as to a macro name, which implies it's treating them similarly internally.) Anyway, not having a separate string type eliminates a certain amount of code. 07 Feb 97 - Junked the parse-removelist parsing action (used for .rm and .rr). I never liked that this not only parsed the actions, but did something with them (doing something with them should be handled by the post-parsing actions. Replaced parse-removelist with a new action parse-names (like parse-name, but gets multiple names), and call a new action remove-names in the port-parsing actions. (I use parse-names rather than parse-macro-args because parse-macro-args strips quotes.) 09 Feb 97 - The noescape action was defined in troffcvt/action.c as taking one argument when it really takes none. Fixed. 12 Feb 97 - Implement named environments (a la groff) by considering *all* environments to be named rather than numbers. Compatibility with number-only environments is achieved by creating an initial default set of environments named "0", "1", and "2". 13 Feb 97 - Implement another quoting mode such that a quote in a macro argument doesn't get subjected to further quote stripping if the macro passes the argument to another macro. This is done by turning these quotes into a special quote character not used anywhere else. The regular quote-stripping mechanism is still used in compatibility mode. [see also 14 Mar 97 entry] - Transliterations have been limited to transliterating an ASCII character to another ASCII character. Eased this limitation slightly so that the destination character can be anything. Probably should allow the source character to be anything as well, but then it's harder to use a simple array lookup to do the transliteration. 17 Feb 97 - Added -l command line option to troffcvt. This causes it to print controls to the output that look like: \line file number to give an indication of the current input file and number. This helps for debugging, to figure out what output is resulting from which input line. 01 Mar 97 - tblcvt works reasonably well now. Now need to add table-specific controls to troffcvt and get the postprocessors to do something with them. - Changed symbols like begin-setup, end-setup, BeginSetup, EndSetup to setup-begin, setup-end, SetupBegin, SetupEnd. This change has no functional significance, it just makes names group better in lists that are organized alphabetically. 06 Mar 97 - Fixed subtle bug in parse.c where skipping a failed multi-line condition wouldn't properly detect the closing \} if the line was the last in the input but didn't end with a newline. Sheesh. 07 Mar 97 - Modified troffcvt's name lookup mechanism. Instead of a single list with all the names on it, have an array of lists, and index into the array using the name's hash value to select one of the lists. 11 Mar 97 - Corrected failure of troffcvt reader code to recognize \noconstant-width. 13 Mar 97 - Started working on support for the -mdoc macro package. The first test (formatting the mdoc manual page itself, using the macros themselves with no redefinitions) turned out pretty awful -- lots of \A tests were being written literally to the output. That's because I never implemented \A. After adding code to handle \A, the man page turned out fairly well. It could still use some work, much of which I hope can be done with a tc.mdoc redefinition file. 14 Mar 97 - Oops! Now I tried formatting the mdoc.samples manual page and it breaks big time. Lots of the \A'xx' tests occur in macros and test an argument using \A'\\$n', where \$n has a quote in it (like "that's"). This causes the delimiter scan to terminated early, spilling text to the output that should be part of the test. Okay, to fix this, the parsing routines need to pay attention to the input level, such that routines that looks for closing delimiters don't quit parsing until encounting a delimiter at the same input level as the opening delimiter. This is similar to what groff does. To preserve compatibility with standard troff, the input level is ignored in compatibility mode. This change affects such stuff as \A'xx', \w'xx', .if 'x'y', and .tl 'left'center'right. Turns out the same mechanism can also be used with opening and closing quotes in macro argument parsing, so the ugly special quote character hack (see 13 Feb 97) can be junked. - Modify input character pushback mechanism to record the input level of pushed back characters, to prevent them from being returned into the wrong input level should a level change occur after a character is pushed back but before the next character is read. 16 Mar 97 - Implemented groff's property that when a macro interpolates another macro as a string (\*x, \*(xx, \*[xxx]), the outer macro's arguments are not hidden from the inner macro. This required splitting out argument information from the MacSrc structure into a separate structure and maintaining a use count on the argument structure. - Wrote manual page for unroff. 17 Mar 97 - Changed options for tc2null, tc2text, tc2rtf. This helps make most options for troffcvt lowercase and options for postprocessors uppercase, which helps when writing front ends that execute both troffcvt and a postprocessor, by reducing option space overlap. tc2null changes: echo input tokens: old -e new -E tc2rtf changes: debugging output: old -d new -D echo input tokens: old -e new -E character set: old -cs charset new -S charset tc2text changes: echo input tokens: old -e new -E join output lines: old -join new -J split output lines: old -split nnn new -S nnn 28 Mar 97 - Renamed config/mklinuxppc.p-cf to config/linux-pmac.p-cf per similar naming change in WRPRC 2.10 config file distribution. 09 Apr 97 - Added support for groff's ".if d", ".if r", and ".if c" constructs. The ".if c" construct is a little tricky: the input routines create at a very low level any special char they see that doesn't exist. This makes any special character always appear to exist if you test whether it has a code. But the value given to such characters is empty, so the test is made based on an empty or non-empty value. - tc2html now does the following with the construct: instead of writing it to the output immediately, it hangs onto it and "floats" it forward in the document until it encounters a non-whitespace character. Then it writes the anchor followed by the character. This avoids the problem where an anchor is started on one line, but the text surrounded by the anchor beginning and end is on the next line and is part of a display. Since the text is typically indented in a display, the leading space was part of the link and was being underlined as well, which is ugly. Now the anchor beginning floats past the spaces. 18 Apr 97 - Moved the troffcvt-specific macros, variables, and rules for formatting documents with troff2html, troff2rtf, and unroff into the WRPRC2 configuration files. This means the distribution *requires* at least WRPRC-2.10 of that distribution. 06 May 97 - tc2text actually pays a little attention to the indent and temp indent now. 09 May 97 - Fixed ugly (subtle) bug in troffcvt with writing /indent and /temp-indent. Normally, troffcvt tries to avoid writing out param settings if the value hasn't really changed. The indent was one of these params. But it really has to be written out each time. Consider the following: .in .5i .ti 1i a .ti 1i .in .5i b This was generating the following output: \indent 216 \temp-indent 432 a \break \temp-indent 432 b \break No \indent was written after the second \temp-indent, because the .in value didn't change. But this is wrong, because .in overrides a preceding .ti and the \indent should be written, like this: \indent 216 \temp-indent 432 a \break \temp-indent 432 \indent 216 b \break This was fixed by forcing out an \indent on every indent change. The output gets a bit more verbose, but it's correct. - Fixed a temp indent bug where the \temp-indent argument was being allowed to go negative rather than being clipped to zero. - Began making tc2text a bit smarter: - Pays attention to line length - Uses a buffer to assemble the output line. (Before it was just writing characters as soon as it saw them.) This allows better line wrapping (breaking a line before the word that crosses the output line length rather than after). It also allows centering to be done (since the entire line is assembled before writing it out, it's known how long it is and therefore how much indenting is needed. - Tabs are expanded. (Treats all tabs as left-justified, though.) - Handles tables a little bit, though badly (especially for cells with multiple-line contents). 11 May 97 - Removed -S option from tc2text (and unroff) since tc2text now pays attention to line length. 13 May 97 - Improved tc2rtf's handling of tables. The table output isn't great but at least it no longer instantly crashes Word. :-) 16 May 97 - Changed internal names of some special characters (names written by troffcvt using @name). I decided to use PostScript names whenever possible (PostScript is a preexisting standard that includes most names I need, so by using it I don't need to make up as many names myself). This means names like @em-dash become @emdash, etc. Changes-1.04 lists the changes. - Changed oslash sequence from o/ to /o, which matches groff. - Added special-character sequences to the troffcvt actions file for those characters recognized by groff that weren't already in the file. This will help provide the basis for ISO Latin-1 (ISO 8859-1) support, since lots of Latin-1 characters are specified using special-character sequences of the form \(xx. 18 May 97 - Removed the restriction on 8-bit input characters. This was done by starting special-character codes at 512 rather than 256, and by using an escape-code range of 256-511 rather than 128-255, which frees up the range from 128-255 for another purpose - that purpose being to allow 8-bit characters. This shouldn't yet be considered as real "support" for 8-bit input, since all it means is that troffcvt doesn't filter them out. Postprocessors don't do anything special with such characters. 21 May 97 - Removed the UC (university-crest) special character. That's the kind of thing that should be locally added on a per-site basis. - Improved handling of tables by tc2text a little. - Added -8 option to tc2text and unroff for specifying that 8-bit characters should be allowed in the output. -8 turns on reading of text-8-specials after reading text-specials. The text-8-specials file lists the translations for 8-bit Latin-1 character names. - Wrote list-specials and chk-specials scripts (in misc directory) for generating a troffable list of all special characters and for checking which special characters are listed and unlisted in postprocessor special-character translations tables. 22 May 97 - Removed the @leader-pad special character. There is no such thing. - I had @emdash listed as a builtin special character in some places. It's not. 23 May 97 - The distribution builds under NetBSD 1.2.1 (mac68k) now. nvironments named "0", "1", and "2". 13 Feb 97 - Implement another quoting mode such that a quote in a macro argument doesn't get subjected to further quote stripping if the macro passes the argumetroffcvt-1.04/ReleaseDates010064400017710000151000000000550634123541000172770ustar00junkyarddatamgmt000004000000271.02 28 Sep 92 1.03 17 Sep 93 1.04 23 May 97 troffcvt-1.04/ThinkCNotes010064400017710000151000000033340626662670700171550ustar00junkyarddatamgmt00000400000027This source compiles under THINK C 6.0.1 General notes for all projects in this folder You MUST include memmgr.h in any source file that uses MemMgr calls, or invokes the New() macro. You will get allocation errors otherwise (of the sort that don't crash the program immediately, but make it fail in hard to find ways). For troffcvt and postprocessors to run correctly, any runtime files they read (e.g., actions, rtf-fonts, tcr-fonts) must be in the same folder as the application or in the "troffcvt" folder inside the Preferences folder. If you use the latter, you can keep all runrtime files in the same place. troffcvt project: Under Options/Language Settings, Select ANSI Settings and THINK C extensions. Under Options/Prefix, you should indicate the following: # define HAVEGETPID 0 # define SYSV The -mxx option is intended to allow inclusion of /usr/lib/tmac/tmac.xx under UNIX. It will only work on a Macintosh if you have the tmac.xx files in your current folder. Note that some macro packages consist of multiple files; if so, you may need more than a single file per package. If the main file defines a string which indicates the directory in which to find the other files, you'll probably need to comment it out. tc2rtf project Under Options/Language Settings, Select ANSI Settings and THINK C extensions. Under Options/Prefix, you should indicate the following: # define SYSV tc2text project Under Options/Language Settings, Select ANSI Settings and THINK C extensions. Under Options/Prefix, you should indicate the following: # define SYSV tc2null project Under Options/Language Settings, Select ANSI Settings and THINK C extensions. Under Options/Prefix, you should indicate the following: # define SYSV troffcvt-1.04/Imakefile010064400017710000151000000025000634146662600166400ustar00junkyarddatamgmt00000400000027XCOMM troffcvt project Makefile XCOMM Use "make World" to build the distribution. But before you do that, XCOMM look at the files in the config subdirectory to see if you want XCOMM to change anything. XCOMM Requires the WRPRC2 imake configuration files #define IHaveSubdirs #define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' SUBDIRS = lib libunix troffcvt tblcvt post doc man misc SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) Prereq:: Prereq.ps Prereq.txt Prereq.html Prereq.ms: Prereq.tmpl prereq Prereq.tmpl > Prereq.ms StuffToClean(Prereq.ms) TroffMsToPostScript(Prereq.ps,doc/tmac.wrprc Prereq.ms,NullArg,NullArg) TroffMsToText(Prereq.txt,Prereq.ms,doc/tmac.wrprc,NullArg,NullArg) TroffMsToHTML(Prereq.html,Prereq.ms,doc/tmac.wrprc -a doc/tc.wrprc-html,NullArg,NullArg) DISTFILES = \ README Prereq* INSTALL Changes-* Log ReleaseDates ThinkCNotes \ Imakefile Makefile \ doc man \ config h lib libmac libunix troffcvt tblcvt post misc DISTDIR = troffcvt-$(PROJECTRELEASE) HelpAuxTarget(Distribution,build a release $(PROJECTRELEASE) distribution) Distribution:: $(MAKE) $(MFLAGS) clean $(MAKE) Prereq -$(RM) -r $(DISTDIR) MakeDir($(DISTDIR)) tar cf - $(DISTFILES) | (cd $(DISTDIR) ; tar xf -) tar cf $(DISTDIR).tar $(DISTDIR) gzip $(DISTDIR).tar StuffToClean($(DISTDIR).tar.gz) clean:: $(RM) -r $(DISTDIR) troffcvt-1.04/Makefile010066400017710000151000000342560634146663100165020ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # troffcvt project Makefile # Use "make World" to build the distribution. But before you do that, # look at the files in the config subdirectory to see if you want # to change anything. # Requires the WRPRC2 imake configuration files SUBDIRS = lib libunix troffcvt tblcvt post doc man misc all:: World:: @echo "Building "$(PROJECTNAME)", Release "$(PROJECTRELEASE) @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean $(MAKE) $(MFLAGS) depend $(MAKE) $(MFLAGS) all @echo "" @date @echo "" @echo "Done building "$(PROJECTNAME) help_aux:: @echo "'make "World"' to "build the entire $(PROJECTNAME) distribution Prereq:: Prereq.ps Prereq.txt Prereq.html Prereq.ms: Prereq.tmpl prereq Prereq.tmpl > Prereq.ms clean:: $(RM) Prereq.ms Prereq.ps:: doc/tmac.wrprc Prereq.ms $(SOELIM) doc/tmac.wrprc Prereq.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > Prereq.ps clean:: $(RM) Prereq.ps help_aux:: @echo "'make "Prereq.ps"' to "format Prereq.ps in PostScript Prereq.txt:: $(SOELIM) Prereq.ms | $(UNROFF) -ms doc/tmac.wrprc $(TROFFOPTS) - > Prereq.txt clean:: $(RM) Prereq.txt help_aux:: @echo "'make "Prereq.txt"' to "format Prereq.txt in plain text Prereq.html:: $(SOELIM) Prereq.ms | $(TROFF2HTML) -ms doc/tmac.wrprc -a doc/tc.wrprc-html $(TROFFOPTS) - >Prereq.html clean:: $(RM) Prereq.html help_aux:: @echo "'make "Prereq.html"' to "format Prereq.html in HTML DISTFILES = \ README Prereq* INSTALL Changes-* Log ReleaseDates ThinkCNotes \ Imakefile Makefile \ doc man \ config h lib libmac libunix troffcvt tblcvt post misc DISTDIR = troffcvt-$(PROJECTRELEASE) help_aux:: @echo "'make "Distribution"' to "build a release $(PROJECTRELEASE) distribution Distribution:: $(MAKE) $(MFLAGS) clean $(MAKE) Prereq -$(RM) -r $(DISTDIR) @if [ -d $(DISTDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(DISTDIR)); fi tar cf - $(DISTFILES) | (cd $(DISTDIR) ; tar xf -) tar cf $(DISTDIR).tar $(DISTDIR) gzip $(DISTDIR).tar clean:: $(RM) $(DISTDIR).tar.gz clean:: $(RM) -r $(DISTDIR) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # rules for building in SUBDIRS all:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "making" all "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) 'CDEBUGFLAGS=$(CDEBUGFLAGS)' all); \ done depend:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "depending" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) depend); \ done install:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "installing" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) install); \ done install.man:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "installing man pages" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) install.man); \ done clean:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "cleaning" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) RM_CMD='$(RM_CMD)' clean); \ done tags:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ ($(CHDIR) $$i ; echo "tagging" "in $(CURRENT_DIR)/$$i..."; \ $(MAKE) $(MFLAGS) TAGS='$(TAGS)' tags); \ done Makefiles:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \ case "$$i" in \ ./?*/?*/?*/?*) parent=../../../../;; \ ./?*/?*/?*) parent=../../../;; \ ./?*/?*) parent=../../;; \ ./?*) parent=../;; \ */?*/?*/?*) parent=../../../../;; \ */?*/?*) parent=../../../;; \ */?*) parent=../../;; \ *) parent=../;; \ esac; \ case "$(TOP)" in \ /?*) topadj= ;; \ *) topadj=$$parent ;; \ esac; \ ($(CHDIR) $$i ; \ $(IMBOOT_CMD) $$topadj$(TOP) $(CURRENT_DIR)/$$i ; \ $(MAKE) $(MFLAGS) Makefiles ) ; \ done # ------------------------------------------------------------------------- # dependencies generated by makedepend MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFItroffcvt-1.04/doc/004077500017710000151000000000000634147233300155745ustar00junkyarddatamgmt00000400000027troffcvt-1.04/doc/actions.ms010064400017710000151000000745560632352003200175770ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 11 April 1997 .\" .EH 'troffcvt Action Reference'- % -'' .OH ''- % -'troffcvt Action Reference' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .de Ac \" action .LP .nf .ta \n(LLuR \\$1 (\fB\\$2\fR) .br .fi .. .TL .ps +2 troffcvt Action Reference .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .H*toc*title "Table of Contents" .\" .H*aname introduction .H*aend .\" .Ah Introduction .\" .LP When .I troffcvt executes, it reads one or more action files which instruct it how to interpret .I troff requests. The default action file is named .I actions ; this file is read before any other action files or any macro packages named on the command line. You should understand the format of action files if you want to modify the default action file or if you want to write your own action files. .LP This document describes the syntax of action files, and discusses how actions work. This includes argument parsing and transmission of argument values. It also includes a list of the available actions. .\" .H*aname general-syntax .H*aend .Ah "General Syntax" .\" .LP Action files are plain text files. Blank lines are ignored, as are lines beginning with ``#'' in column 1, which are taken as comments. Other lines should begin with .B imm or .B req and have the following syntax: .Ps imm \f(CIimmediate-actions\fP req \f(CIrequest-name parsing-actions\fP eol \f(CIpost-parsing-actions\fP .Pe .B imm and .B req lines may be continued onto the next line with a ``\e'' as the last character. .LP An .B imm line specifies actions to be executed as soon as they are read from an action file. (No output can be generated from .B imm lines because .I troffcvt turns off output while action files are being read.) .LP A .B req line describes what .I troffcvt should do when a given request occurs in the input. .I request-name is the name of the request (without the leading period). .I parsing-actions is either empty or a list of actions to perform to parse the request arguments. .B eol is mandatory and causes .I troffcvt to skip to the end of the request line. .I post-parsing-actions is either empty of a list of actions to perform after the request arguments have been parsed; typically these actions process the arguments parsed by the parsing arguments. .LP To include whitespace in an argument that is passed to an action, you can surround it with either single or double quote characters. For example: .Ps push-string ".tm this is an argument with whitespace\en" push-string '.tm this is an argument with whitespace\en' .Pe To include a quote within such an argument, you must quote it with the other quote character. For example: .Ps push-string ".tm this is a single-quote: '\en" push-string '.tm this is a double-quote: "\en' .Pe .\" .Ah "Argument Processing" .\" .Bh "Argument Collection" .\" .LP Several actions are available to parse various kinds of request line arguments, e.g., numbers, macro arguments, single characters. Most parsing routines read arguments from the request line, store them in the request argument vector .Cw rargv[] , and bump the request argument count .Cw rargc . Arguments stored this way are available to other actions, which refer to them as .B $1 , .B $2 , etc. .LP A few parsing routines do not store the arguments in .Cw rargv[] but instead act on them directly. For example, .B parse-tab-stops reads the tab values and sets the current stops directly. .B parse-condition reads and tests the condition, then executes or skips the rest of the conditional request line. .Bh "Argument Transmission \*- General" .LP Before an argument is passed to an action, it is examined to see whether it contains references to request arguments or to escape sequences. The legal references and sequences are shown below along with their meanings: .Ps .ta .75i $\f(CIn\fP \fRBecomes the \f(CIn\fR-th request argument, empty if unavailable\f(CW $$ \fRBecomes the number of arguments parsed from request line\f(CW $* \fRBecomes a string consisting of all arguments, space-separated\f(CW $@ \fRLike \f(CW$*\fR, but arguments are double-quoted as well\f(CW \e\e \fRBecomes \f(CW\e \en \fRBecomes a linefeed\f(CW \et \fRBecomes a tab\f(CW \e\f(CIX\fP \fRBecomes \f(CIX\fR, for any character not listed above\f(CW .Pe An empty string is substituted for a request argument if .I n is not a digit, if there is no such argument, if the argument was empty, or if the action occurs in an immediate action list. Note that .B $* and .B $@ produce a .I single string, and thus count as a single argument when passed to an action. .LP Quotes may be used around an action argument to include whitespace in the argument. However, as noted in the .H*ahref general-syntax "General Syntax" .H*aend section, to include a single quote within an argument, you must quote the argument with double quotes, and vice-versa. .LP .B Example: The following has defines a string as the second argument if the first argument isn't empty: .LP .Ps push-string '.if !"$1"" .ds $1 "$2\en' .Pe .\" .Bh "Argument Transmission \*- Numeric Arguments" .\" .LP .LP The .B parse-num action is used to parse a number from the request line. It takes one argument, a scaling indicator used to scale numbers in request argument expressions that don't have explicit scaling indicators. For example, the .Rq sp request can be specified like this: .LP .Ps req sp parse-num v eol break space $1 .Pe .LP In this case .B parse-num uses .B v 's as the default scaling. Then the arguments to the requests .LP .Ps \&.sp 1 \&.sp 1i \&.sp 1i+1 .Pe .LP will be interpreted as ``1v'', ``1i'' and ``1i+1v'', respectively. (The ``i'', where present, overrides the default of .B v ). .LP In each case, after .B parse-num finishes evaluating the expression, the result is converted into basic units, and that is what is stored in the request argument vector. If the resolution is 432 units/inch and a .B v is 72 units, the arguments for the three requests above would be stored as the strings ``72'', ``432'' and ``504''. In other words, the value stored may not look much like the value on the request line. .LP Allowable scaling indicators are .B i (inches), .B c (centimeters), .B P (picas), .B m (ems), .B n (ens), .B p (points), .B v (vertical spacing units), .B u (basic units) and .B x (ignore scaling). .LP The .B x specifier is special; it means there is no default, numbers are interpreted without scaling, and the result stored in the request argument vector is .I not converted to basic units. This is appropriate for requests such as .Rq ce or .Rq ls , which may be specified like so: .LP .Ps req ce parse-num x eol center $1 req ls parse-num x eol line-spacing $1 .Pe .LP If a request parsing action attempts to parse an argument that is not present on the request line or that does not conform to what the action is looking for, the request-parsing action stores an empty string in the .Cw rargv[] array. Functions for actions that allow arguments to be missing (empty) must be written to test for that case. .LP Actions that take numeric parameters usually expect that the number be given in basic units, unless an explicit scaling indicator is appended. The reason for this is that numeric arguments to actions are generally obtained from parsing actions earlier in the action list, and those will usually have been converted to basic units. This means that even for actions used in .B imm lines, the same convention must be followed. Thus, the two lines following have very different results: .LP .Ps .ta 2i imm space 12 \fRSet spacing to 12 units\fP imm space 12p \fRSet spacing to 12 points\fP .Pe .Bh "Argument Transmission \*- Relative-Change Requests" .LP Some requests allow parameter values to be changed either to an absolute value, or relatively by a specified amount. Examples: .Ps .ta 1i \&.ps 3 \fRSet point size to 3 points\fP \&.ps +3 \fR... to 3 points greater than current value\fP \&.nr x 4 \fRDefine number register with initial value 4\fP \&.nr x +4 \fR...with initial value 4 greater than current value\fP .Pe This kind of request is handled with the .B parse-absrel-num action. .B parse-absrel-num is like .B parse-num in that it takes a default scaling indicator, but it also takes a second argument which specifies the current value of the relevant parameter. Since you can't specify the current value literally in an action file (the current value is a volatile value), you can refer to the parameter symbolically. The parameters which may be referred to this way are .B point-size , .B spacing , .B line-spacing , .B indent , .B line-length , .B page-length , .B title-length and .B offset . .LP .B Example: the current indent may be set absolutely or relative to the current value, so it may be specified like this: .LP .Ps req in parse-absrel-num m indent eol break indent $1 .Pe .LP If the argument on an .Rq in request begins with a plus or minus sign, the sign is stripped, the rest of the argument is evaluated to produce a number, and the result is the current indent modified up or down by that number. (The result does .I not modify the current indent; it is simply stored in .Cw rargv[] .) If there is no initial sign, the request argument is an absolute number and the parse result is simply the value of the argument (the current indent value is ignored). In the example above, the result goes into .B $1 . The second reference to .B indent is as an action, which is what actually sets the indentation (to the value of .B $1 ). .LP As a special-case hack, if the current-value argument to .B parse-absrel-num begins with a backslash, the rest of the argument is taken as the name of a number register, and the value of the register is used. This is used in relation to the .Rq nr request, which allows a register to be redefined relative to its current value. .Rq nr can be specified in an action file as: .LP .Ps req nr parse-name parse-absrel-num u \e\e$1 parse-num x eol define-register $1 $2 $3 .Pe .LP It is necessary that .B parse-num and .B parse-absrel-num both exist, because an expression such as ``\-10+10'' means ``0'' as an absolute number, but ``decrease by 20'' as a relative number. .\" .Ah "Action Descriptions" .\" .LP Each action is discussed below. Action descriptions are accompanied by one or more of the following indicators to specify the allowable contexts in which the action can be used: .Ps .ta 1i imm \fRAllowable in \fPimm\fP lines\fP p \fRAllowable in argument parsing section of \fPreq\fP lines\fP pp \fRAllowable in post-parsing section of \fPreq\fP lines\fP .Pe Whenever you specify an action in an action list, you must specify all the arguments that it expects. However, an argument often can be the empty string. Thus .B escape-char .B @ sets the escape character to ``@'' while .B escape-char \fB""\fP restores the default escape character. .\" .Ac "\fBabort\fR \fIstring\fR" "pp, imm" .IP Aborts .I troffcvt after printing .I string on .I stderr . If .I string is empty, ``User abort'' is printed instead. .\" .Ac "\fBadjust\fR \fIc\fR" "pp, imm" .IP Turns on output line adjusting, with mode .I c , which can be .B l (left), .B c (center), .B r (right), .B b or .B n (both), or a number previously obtained from the .B \.j register. An adjustment indicator is written to the output if the request changes the current adjustment and centering is off and filling is on. If .I c is empty, adjustment is turned on with whatever the current mode is. .\" .Ac "\fBalias-macro\fR \fIxx yy\fR" "pp, imm" .IP Create the name .B xx as an alias for macro, string, or request .B yy . This implements the .I groff .Rq als request. The two names become equivalent. .Rq xx continues to exist even if .Rq yy is removed. If .Rq yy is redefined, .Rq xx becomes redefined as well. .IP Actually, there is one difference between aliased names, which is that .B \e$0 in the macro refers to the actual name under which the macro was invoked, not the name under which it was first created. .\" .Ac "\fBalias-register\fR \fIxx yy\fR" "pp, imm" .IP Like .B alias-macro but for number registers. This implements the .I groff .Rq aln request. .\" .Ac "\fBappend-macro\fR \fIxx yy\fR" pp .IP Like .B define-macro but appends to an existing macro definition. .\" .Ac "\fBappend-string\fR \fIxx value\fR" "pp, imm" .IP Like .B define-string but appends to an existing string. .\" .Ac "\fBbegin-page\fR \fIN\fR" "pp, imm" .IP If .I N is empty, writes .Cl begin-page . Otherwise, writes .Cl begin-page .I N and sets the current page number and register .B % to .I N . .\" .Ac "\fBbreak\fR" "pp, imm" .IP Causes a break (writes a .Cl break line) unless the no-break control character was given on the request or unless the current output line doesn't have anything on it. None of the action functions do a break except that for .B break itself, so it should be specified in the action list for any request that normally causes a break. The reason for this is to make sure complete control over when a break occurs is in the action file, not inside .I troffcvt . This is more work for the action file writer, but provides more flexibility. .IP For instance, .Rq sp can be specified as ``req sp parse-num v eol break space $1''. The function associated with .B space doesn't do any break itself, so the .B break is necessary. .\" .Ac "\fBcenter\fR \fIN\fR" "pp, imm" .IP Turns on centering and writes .Cl center to the output. .I troffcvt will generate additional control output to turn off centering after .I N lines of text input have been read (1 line if .I N is empty). .\" .Ac "\fBconstant-width\fR \fIF N M\fR" "pp, imm" .IP Treat font .I F as a constant-width font. See the .I troff manual for the interpretation of .I N and .I M . .\" .Ac "\fBcontinuous-underline\fR \fIN\fR" "pp, imm" .IP Turns on continuous underlining and writes .Cl cunderline to the output. Continuous underlining is turned off after .I N lines of text input (1 line if .I N is empty). .\" .Ac "\fBdebug-flag\fR \fIN\fR" "p, pp, imm" .IP Turns on debugging flag bit .I N . The allowable values are listed in .I troffcvt.h and are not of general interest. If .I N is empty, all flags are turned on. If .I N is negative, all flags are turned off. .\" .Ac "\fBdefine-macro\fR \fIxx yy\fR" pp .IP Defines a macro named .I xx . Reads input in copy mode until a line of the form \fB\.\fIyy\fR is found, at which point \fB\.\fIyy\fR is invoked. If .I yy is empty, a line of the form .B \.\. terminates the definition. .\" .Ac "\fBdefine-register\fR \fIxx init incr\fR" "pp, imm" .IP Defines number register .I xx with initial value .I init and increment value .I incr . .\" .Ac "\fBdefine-string\fR \fIxx value\fR" "pp, imm" .IP Defines string .I xx with value .I value . .\" .Ac "\fBdiversion-append\fR \fIxx\fR" pp .IP Like .B diversion-begin but writes .Cl diversion-append .I xx to the output instead. .\" .Ac "\fBdiversion-begin\fR \fIxx\fR" pp .IP Writes .Cl diversion-begin .I xx to the output. When a matching .Rq di or .Rq da is seen, .Cl diversion-end .I xx is written. .\" .Ac "\fBdump-bad-requests\fR \fIN\fR" "pp, imm" .IP If .I N is non-zero, any unrecognized requests are written to the output in the form: .Ps \eother bad-req: \f(CIoriginal input line\fP .Pe If .I N is zero, this kind of output is suppressed. .\" .Ac "\fBdump-input-stack\fR" "pp, imm" .IP Dump information about the input stack to .I stderr . This is for debugging. .\" .Ac "\fBdump-macro\fR \fIxx\fR" "p, pp, imm" .IP Dumps the body of macro .I xx to .I stderr . This is for debugging. .\" .Ac "\fBecho\fR \fIstring\fR" "p, pp, imm" .IP Writes .I string to .I stderr . .\" .Ac "\fBembolden S \fIF N\fR" "pp, imm" .IP This request takes three arguments, but the arguments can actually be .I F and .I N rather than .B S , .I F , and .I N . It's necessary to examine the first argument to tell. .IP Emboldens font .I F by smearing it .I N units. If .I S is present, embolden the special font by .I N units when the current font is .I F . .\" .Ac "\fBend-input\fR" pp .IP Forces input routines to return end-of-input to cause .I troffcvt to finish processing immediately. .\" .Ac "\fBend-macro\fR \fIxx\fR" "pp, imm" .IP Causes macro .I xx to be invoked after all other input has been processed. .I xx must be a macro, not a request. .\" .Ac "\fBenvironment\fR \fIname\fR" "pp, imm" .IP Enters environment .I name or resume previous environment if the argument is empty. .\" .Ac "\fBeol\fR" "p" .IP Skips to the end of the current input line. This action must terminate the parsing action section of all .B req lines. .\" .Ac "\fBfill\fR" "pp, imm" .IP Turns on fill mode. .\" .Ac "\fBfont\fR \fIF\fR" "pp, imm" .IP Switches to font .I F , writing .Cl font .I F to the output if this causes a font change. .\" .Ac "\fBfont-position\fR \fIN F\fR" "pp, imm" .IP Associates font .I F with position .I N . .\" .Ac "\fBflush\fP" "pp, imm" .IP Flush any pending output. Similar to .B break , but doesn't write .Cl break . .\" .Ac "\fBhyphenate\fR \fImode\fR" "pp, imm" .IP Sets the hyphenation mode, which should be zero to turn off hyphenation, or a positive value as described in the .I troff manual. .\" .Ac "\fBhyphen-char\fR \fIc\fR" "pp, imm" .IP Sets the hyphenation character to .I c . .\" .Ac "\fBignore\fR \fIyy\fR" "pp, imm" .IP Input is read in copy mode but otherwise ignored until a line of the form \fB\&\.\fIyy\fR is found, at which time .Rq \fIyy\fR is invoked. If .I yy is empty, a line of the form .B \.\. terminates the .B ignore action. .\" .Ac "\fBindent\fR \fIN\fR" "pp, imm" .IP Sets indent to .I N . .\" .Ac "\fBinput-trap\fR \fIN xx\fR" "pp" .IP Sets the input-line trap to .I xx , to spring after .I N input lines. .I xx must be a macro, not a request. .\" .Ac "\fBline-length\fR \fIN\fR" "pp, imm" .IP Sets line length to .I N . .\" .Ac "\fBline-spacing\fR \fIN\fR" "pp, imm" .IP Sets line spacing to .I N . .\" .Ac "\fBneed\fR \fIN\fR" "pp, imm" .IP Indicate that .I N lines are needed on the current output page. If not that many lines are available, postprocessors that pay attention to this information typically will perform a page break. .\" .Ac "\fBno-space\fR \fIc\fR" "pp, imm" .IP Turns on no-space mode if the argument is .B y , off if it's .B n . .\" .Ac "\fBnoadjust\fR" "pp, imm" .IP Turns off output line adjusting. .\" .Ac "\fBnoescape\fR" "pp, imm" .IP Turns off escape processing. .\" .Ac "\fBnofill\fR" "pp, imm" .IP Turns on no-fill mode. .\" .Ac "\fBoffset\fR \fIN\fR" "pp, imm" .IP Sets offset to .I N . .\" .Ac "\fBoutput-control\fR \fIstring\fR" "pp, imm" .IP Writes .I string directly to the output, preceded by a .B \e character and followed by a newline. .\" .Ac "\fBoutput-special\fR \fIstring\fR" "pp, imm" .IP Writes .I string directly to the output, preceded by a .B @ character and followed by a newline. .\" .Ac "\fBoutput-text\fR \fIstring\fR" "pp, imm" .IP Writes .I string directly to the output. .\" .Ac "\fBpage-length\fR \fIN\fR" "pp, imm" .IP Sets page length to .I N . .\" .Ac "\fBpage-num-char\fR \fIc\fR" "pp, imm" .IP Sets the page number character (used in titles) to .I c . .\" .Ac "\fBpage-number\fR \fIN\fR" "pp, imm" .IP Sets the current page number and the .B % register to .I N . Writes no output. .\" .Ac "\fBparse-absrel-num\fR \fIc N\fR" p .IP Parses a number or numeric expression from the request line, which may be absolute, or relative to .I N . .I c is the default scaling unit to be used in evaluating expressions. .\" .Ac "\fBparse-char\fR" p .IP Parses a single-character argument from the request line. .\" .Ac "\fBparse-condition\fR \fIc\fR" p .IP Parses a condition from the request line, tests it, and executes or skips the rest of the line depending on the result of the test. .I c should be .B y if a following else-clause should be expected later (as for .Rq ie ) or .B n if it should not be (as for .Rq if ). .\" .Ac "\fBparse-embolden\fR" p .IP An ugly hack used for the .Rq bd request. Parses both forms of the request, which are: .Ps \&.bd \f(CIF N\fP \&.bd S \f(CIF N\fP .Pe The resulting argument vector will have either two or three elements. .\" .Ac "\fBparse-filename\fR" p .IP Parses a filename from the request line. .\" .Ac "\fBparse-macro-args\fR" p .IP Parses all remaining arguments (in copy mode) to the end of the request line. Arguments on request lines are separated by spaces, or may be double-quoted to include whitespace in an argument. Note that a numeric argument is not evaluated in the same manner as for the number-parsing actions. To get around this, you can later interpolate the argument into a string that's processed with .B push-string: .Ps # assume first argument, if present, is numeric expression to set indent. req XX parse-macro-args eol push-string ".if $$>0 .in $1\en" .Pe .\" .Ac "\fBparse-name\fR" p .IP Parses a name of the form from the request line. This action is used to pick up single string, macro, register, etc. names. If compatibility mode is on, the name can be no more than two characters long. .\" .Ac "\fBparse-names\fR" p .IP Like .B parse-name , but parses multiple names to the end of the input line. .\" .Ac "\fBparse-num\fR \fIc\fR" p .IP Parses a number or numeric expression from the request line. .I c is the default scaling unit to be used in evaluating expressions. .\" .Ac "\fBparse-string-value\fR \fIc\fR" p .IP Parses a string in copy mode to the end of the input line. .I c should be .B y if a leading double quote should be stripped off (as for .Rq ds ) or .B n if it should not be (as for .Rq ab and .Rq tm ). .\" .Ac "\fBparse-tab-stops\fR" p .IP Parses the rest of the request line for tab stop settings. If there are none, .Cl reset-tabs is written, which should be taken as meaning reset tab stops to ``every half inch''. (The .I troff manual doesn't specify how many stops are allowed; presumably postprocessors should allow for ``several''.) .IP If explicit stops are given, the first one is written out as .Cl first-tab .I N .I c , and any following are written as .Cl next-tab .I N .I c . When .Cl first-tab is seen, the postprocessor should clear any stops and begin collecting new ones. Each .Cl next-tab setting should be added to the current list. .I N is specified in basic units. .I c is .B l (left), .B c (center) or .B r (right). .\" .Ac "\fBparse-title\fR" p .IP Parses a title of the form \fB\'\fIleft\fB\'\fIcenter\fB\'\fIright\fB\'\fR from the request line into three elements of .Cw rargv[] . Missing title elements become empty arguments in .Cw rargv[] . .\" .Ac "\fBparse-transliteration\fR" p .IP Parses a transliteration list from the request line. .\" .Ac "\fBpoint-size\fR \fIN\fR" "pp, imm" .IP Sets the point size to .I N . .I N is number of points (unscaled), not basic units. .\" .Ac "\fBprocess-condition\fR" p .IP Executes or skips conditional input. This is used for the .Rq el request, and tests whether the preceding matching .Rq ie succeeded or failed. .\" .Ac "\fBprocess-do\fR" p .IP This action implements the .I groff .Rq do request. Parses the rest of the input line with compatibility mode disabled, then executes the line. The rest of the line must contain a request, but not begin with a control character. The control character that begins the .B do line (\fB.\fR or \fB\'\fP) is used to begin the request. .\" .Ac "\fBpush-file\fR \fIfilename\fR" pp .IP Pushes the given file onto the input stack. .\" .Ac "\fBpush-macro-file\fR \fIfilename\fR" pp .IP Like .B push-file , but looks for the file in the same directories used to find macro files. This implements the .I groff .Rq mso request. .\" .Ac "\fBpush-string\fR \fIstring\fR" "pp, imm" .IP Pushes the given string onto the input stack and processes it. To push a named string onto the stack, use one of the following forms: .Ps \epush-string "\e*\f(CIx\fP" \epush-string "\e*(\f(CIxx\fP" \epush-string "\e*[\f(CIxxx\fP]" .Pe To push a request or macro onto the stack, use: .Ps \epush-string ".\f(CIxx\fP\en" .Pe It can be dangerous to use .B push-string in immediate mode, since your execution environment may not yet be fully set up. That is, although you can process a string immediately using an .B imm line, you should make sure that any requests or macros named in the string have been defined, or they'll be ignored. .IP .\" .Ac "\fBregister-format\fR \fIxx format\fR" "pp, imm" .IP Assigns the given format to number register .I xx . .\" .Ac "\fBremove-name\fR \fIc name\fR" "pp, imm" .IP Removes a name. .I c is .B y if the name refers to a number register, .B n if the name refers to a request, string, or macro. .\" .Ac "\fBremove-names\fR \fIc name1 name2 name3 name4 name5 name6 name7 name8 name9\fR" "pp, imm" .IP Multiple-name form of .B remove-name . There must be nine name arguments specified, but arguments may be given as empty strings if you're not removing nine names. .\" .Ac "\fBrename\fR \fIxx yy\fR" "pp, imm" .IP Renames request, macro, or string .I xx to .I yy . .\" .Ac "\fBset-compatibility\fR \fIN\fR" "pp, imm" .IP Sets compatibility mode to .I N , which turns the mode on if .I N is non-zero. When compatibility mode is off, recognition of long request, macro, string, register, and font names is suppressed. This action also sets the .B .C read-only register. .\" .Ac "\fBset-control\fR \fIc\fR" "pp, imm" .IP Sets control character to .I c .B \. "" ( if .I c is empty). .\" .Ac "\fBset-control2\fR \fIc\fR" "pp, imm" .IP Sets no-break control character to .I c .B \' "" ( if .I c is empty). .\" .Ac "\fBset-escape\fR \fIc\fR" "pp, imm" .IP Restores escape processing, setting escape character to .I c (\fB\e\fR if .I c is empty). .I c cannot be an escaped or .Es ( \fIxx\fR special character, since then it would be recursive. .\" .Ac "\fBset-field\fR \fIdelim pad\fR" "pp, imm" .IP Sets field delimiter character to .I delim and field padding character to .I pad . If .I pad is empty, the pad character becomes space. If .I delim and .I pad are both empty, the field mechanism is turned off. .\" .Ac "\fBset-leader\fR \fIc\fR" "pp, imm" .IP Sets leader repetition character to .I c or remove it if .I c is empty. .\" .Ac "\fBset-tab\fR \fIc\fR" "pp, imm" .IP Sets tab repetition character to .I c or remove it if .I c is empty. .\" .Ac "\fBshift-args\fR \fIN\fR" "pp, imm" .IP In a macro, shifts the arguments left by .I N arguments. If .I N is empty, the arguments are shifted left by one place. If .I N is negative or zero, nothing is done. If .I N is equal to or greater than the number of arguments the macro has, all the arguments are shifted. .\" .Ac "\fBspace\fR \fIN\fR" "pp, imm" .IP Spaces vertically by .I N units (negative = upward). .\" .Ac "\fBspace-size\fR \fIN\fR" "pp, imm" .IP Sets space size to .I N /36\fBm\fR. .I N is unscaled, not in basic units. .\" .Ac "\fBspacing\fR \fIN\fR" "pp, imm" .IP Sets vertical base-line spacing to .I N units. 1 .B v then becomes .I N units. .\" .Ac "\fBspecial-char\fR \fIxx output\fR" "pp, imm" .IP Defines a special character with the given name and output sequence. The name cannot be empty and must consist of plain ASCII characters. The output sequence is the string that should be written when the character is referenced. It too cannot be empty and must consist of plain ASCII characters. .B special-char is used in .B imm lines in action files to define the set of special characters that .I troffcvt should recognize. This set should reflect the characters known by local versions of .I troff . .\" .Ac "\fBswitch-file\fR \fIname\fR" pp .IP Switches the current input file to .I name . .\" .Ac "\fBtemp-indent\fR \fIN\fR" "pp, imm" .IP Sets the temporary indent to .I N . .\" .Ac "\fBtitle\fR \fIleft\fR \fImiddle\fR \fIright\fR" "pp, imm" .IP Processes a three-part title. .\" .Ac "\fBtitle-length\fR \fIN\fR" "pp, imm" .IP Sets the title length to .I N . .\" .Ac "\fBtransliterate\fR \fIlist\fR" "pp, imm" .IP .I list should contain pairs of characters. The first element of each pair will be transliterated into the second element on output. If the list has an odd number of characters, the last is transliterated to a space. .\" .Ac "\fBunderline\fR \fIN\fR" "pp, imm" .IP Turns on underlining and writes .Cl underline to the output. Underlining is turned off after .I N lines of text input. .I troffcvt will generate additional control output to turn off underlining after .I N lines of text input have been read (1 line if .I N is empty). .\" .Ac "\fBunderline-font\fR \fIF\fR" "pp, imm" .IP Sets the underline font to .I F . .\" .Ah "Creating a New Action" .\" .LP If the set of actions is insufficient for your purposes, here's how to modify .I troffcvt to write a new one: .Ls B .Li Read the rest of this section, then study some of the existing actions in .I troffcvt source code to see how they are implemented. .Li Pick a name for the action. This will be the name used in action files to refer to it. .Li Decide whether the function used to implement the action should take any arguments, that is, whether the action should be followed by any arguments when used in an action file. You must also decide whether it should be allowed on .B imm lines and/or .B req lines (and if allowed on the latter, whether allowed in the post-parsing or parsing sections, or both). .Li List the action in the .Cw aiTab[] array in .I action.c , and add an extern for the function to .I troffcvt.h . .Li Write the action function. If the action parses arguments, the function goes in .I parse.c , otherwise it goes in .I req.c . It should be declared like this: .Ps .ta .75i int ActionFunction (int argc, XChar **argv) { } .Pe The function should perform the action and return non-zero for success, zero for failure. Possibly it should simply panic if something catastrophic (unrecoverable) happens. Note that sometimes it is useful to return non-zero for certain kinds of failures. If an action in an action list returns zero, no actions following it in an action list are executed. If you want them to execute anyway, your function should always return non-zero. .sp .5v .Cw argc is the number of action arguments and .Cw argv is an array of pointers to them. (There is a .Cw NULL pointer following the last argument, i.e., .Cw argv[argc] is .Cw NULL .) .sp .5v The function should make no direct reference to the request values .Cw rargc and .Cw rargv[] unless it is an argument parsing action. If your action can be used on .B imm lines, there won't be any request arguments available. It's also a good idea for the function to refrain from modifying the arguments passed to it. (Make copies first and modify the copies.) .Le quest lines are separated by spaces, or may be double-quoted to include whitespace in an argument. Note that a numeric argument is not evaluated itroffcvt-1.04/doc/bugs.ms010064400017710000151000000630640634111555000170740ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 7 March 1997 .\" .EH 'troffcvt Notes and Bugs'- % -'' .OH ''- % -'troffcvt Notes and Bugs' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .TL .ps +2 troffcvt .sp .3v Notes, Bugs, Deficiencies .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .H*toc*title "Table of Contents" .\" .\" .Ah "General Information" .LP This document contains miscellaneous observations about how .I troffcvt behaves, and tries to document its limitations. It should be read by anyone trying to write a postprocessor for .I troffcvt output. .LP .I troffcvt supports the full .I troff language, aside from some specific exceptions noted below. These are discussed in sections numbered in parallel with Ossanna's .I troff manual. Many are related to insignificant or obscure features of the language (e.g., .lg 0 .Rq fl , .lg .Rq pm ). Some are more significant (e.g., diversion mishandling). In some sense these exceptions form the .I troffcvt bug list. .LP .I troffcvt supports a limited subset of the .I groff extensions to standard .I troff . In general, you should assume that any particular .I groff extension is not supported by .I troffcvt , but there are some important exceptions such as aliases and long names. For more details, see the document .H*ahref groff.html .I "troffcvt Support for groff\c" .H*aend \&. .LP The most general and pervasive exception to standard .I troff processing is that .I troffcvt knows nothing about the characteristics of any output device; in particular, it uses no font metric information. This means it doesn't know how wide or tall any character is. This exception is pervasive in that it affects handling of a number of requests and other aspects of the language. Some of the implications are: .Ls B .Li .I troffcvt can't compute the size of output. This breaks constructions such as .Es w "\'\fIstring\fR\'," which makes .I troffcvt pretty well useless for files that have been passed through .I tbl , especially if the tables are complex or require close layout tolerances. (If your document contains tables, you may get more acceptable output by preprocessing the document with .I tblcvt rather than with .I tbl .) .Li .I troffcvt has no notion of current position on the page. .Li Position-related traps aren't sprung, since it can't be determined when the output position sweeps past the trap position. In particular, page transition traps aren't sprung, so .I troffcvt doesn't know the current page number. Multi-column output doesn't multi, either. .Li Registers that have values dependent on output position or size are useless. This includes the general registers .B ct , .B dl , .B dn , .B ln , .B nl , .B sb , and .B st , and the read-only registers .B \.a , .B \.d , .B \.h , .B \.n , and .B \.t . In .I troffcvt the value of these is always zero. The value of .B \.w is .I always 1 .B en . The value of the .B % is unreliable as well, affecting requests such as ``\fB\.if \en%>1\fR \fIstuff\fR'' (fairly common in macro packages). .Li Recursive macros may fail. For instance, the .B \-mm macro .Rq )r does clever spacing and testing of the current page position, recursing until it achieves the desired position. In .I troff , the recursion test eventually terminates properly, but in .I troffcvt it doesn't. .I troffcvt instead notes ``deep'' recursion and simply fails once a certain recursion depth is reached. .Le Non-use of font metric information is deliberate; it isn't a goal of .I troffcvt to lay out text on pages. If it were, .I ditroff would be more useful. The goal is to make it easier for .I other programs to lay out text, by producing input for those programs that's more easily interpretable than straight .I troff input. Along with this is the goal of producing input that's easily transformable before it's fed into the final translator. Example transformations include: mapping .Cl font lines onto fonts available in the target format; scaling character sizes up or down for easier reading or tighter packing, by mapping .Cl point-size and .Cl spacing lines; changing page layout, e.g., for production of legal or A4 size pages. Tying .I troffcvt output to font metrics would make these sorts of transformations difficult. .LP The numbering of the sections that follow correponds to the section numbering in the Ossanna .I troff manual, to make it easier to determine where .I troffcvt bugs affect requests listed in a given section of the Ossanna manual. .\" .Ah "1. General Explanation" .\" .Bh "1.2. Formatter and device resolution" .LP The default resolution used by .I troffcvt is 432 units/inch, but it may be changed with the .B \-r option. (A good value might be the least common multiple of 72 and the resolution you use in the target format.) .LP Since resolution is not fixed, postprocessors should use the value specified on the .Cl resolution line that appears as the first line of the setup section. It indicates number of basic units per inch. Numeric values on following control lines that are specified in basic units can be converted to other units as necessary using this resolution. .\" .Bh "1.3. Numerical parameter input" .LP The default scaling for unscaled numbers in .I troff requests is not hardwired into .I troffcvt . Instead, scaling is specified in the action file, although it's a good idea to use the same default there that .I troff uses: .Ps .ta 4i req sp parse-num v eol break space $1 \fRgood\fP req sp parse-num i eol break space $1 \fRbad\fP .Pe Expressions that involve calculation of ``amount of motion to reach an absolute position'' (as in, e.g., \fB|\^3.2c\fR) evaluate to zero. Since the current position is unknown, the distance to any other position cannot be determined. This affects processing of .I tbl output particularly, since .I tbl is fond of using .Es h \'|\fIN\fR\' to line up columns. .\" .Ah "2. Font and Character Size Control" .\" .Bh "2.2. Fonts" .LP Fonts R, I and B are initially mounted on positions 1, 2 and 3, respectively, and the special font is mounted on all other positions. This means fonts .B R and .B 1 , .B I and .B 2 , etc., are considered equivalent. If a different font is mounted on a given position, references to that font, either by the name or number, are considered equivalent. This is logical to me, although in fact it doesn't reflect the behavior of all .I troff versions. For instance, .I xroff does not necessarily consider .B R and .B 1 equivalent unless you mess around with its font map. .LP The .B \.f register is set to the number of the current font, or zero if the current font is not mounted (it is allowable to refer to a font simply by naming it, so the current font doesn't necessarily have any number). .Rq "ft 0" and .Es f0 are taken as referring to this font. .LP Font changes are written by name (not number) in the form .Cl font .I name , where .I name must be interpreted by the postprocessor. This is a difficult problem since font names tend to be site-specific and idiosyncratic, although the standard .I troffcvt file reader provides some simple font handling support that might be useful. .LP Output from the .Rq bd request typically appears as the .Cl embolden and .Cl embolden-special control lines. It's not clear whether it's worth it for postprocessors to support this request postprocessors, particularly the special-font variant. Although one can switch to the special font explicitly .Rq "ft S" , ( .Es fS ), characters from the special font are also logically part of the other default fonts, and thus referenced for particular characters even if .B S is not the current font. To fully support special font bolding, you'd need to keep track of all the characters in the special font and check every output character to see if it needs to come from that font. Besides, this whole business of the relationship between the special font and other fonts seems tightly linked to the particular typesetting machinery used when .I troff was originally written. .\" .Bh "2.3. Character size" .LP Any positive character size is allowed. For historical reasons, embedded absolute size changes may be one or two digits up to a size of 36, i.e., .Es s36 is the same as .Rq "ps 36" while .Es s37 is the same as .Rq "ps 3" followed by ``7''. Non-numeric input following .Es s is interpreted the same way as .Es s0 . .LP For the .Rq cs request, only the font name is written out on the .Cl constant-width line; the width in which the characters are to be written is currently ignored. .\" .Bh "3. Page Control" .LP Since the current page number cannot be reliably determined, .Rq bp and .Rq pn requests which specify a relative page number change are not reliable. .LP My .I troff .B "Summary and Index" indicates that .I V s are the default scaling unit for .Rq bp and .Rq po requests. The .I actions file supplied with the .I troffcvt distribution tells .I troffcvt to ignore scaling for .Rq bp and to use ems for .Rq po , which seems to make more sense. .LP .Rq mk and .Rq rt are not supported. .\" .Ah "4. Text Filling, Adjusting and Centering" .LP .I troff tosses extra spaces at the end of text lines. .I troffcvt tries to do the same but gets confused by sequences such as ``abc\efI\0\0\0\efP''. The trailing spaces are retained in the output, erroneously. .\" .Bh "4.1. Filling and adjusting" .LP Use of the .B \.j register as the argument to the .Rq ad request is allowed. Note: This depends on all the internal adjustment mode type values being single-digit non-negative integers so that the argument can be parsed by the .B parse-char action. The internal codes are not necessarily the same as those used by any particular version of .I troff . (The codes are known .I not to be the same as those assumed by .I tbl , but I'm not sure exactly what .I tbl assumes.) .LP No hyphenating is done; that is left for the postprocessor. The optional hyphenation character appears as .St opthyphen in the output. .LP The .B \.n , .B nl and .B \.h registers are not set. .LP .Es p appears in the output as .Cl break-spread . .\" .Bh "4.2. Text Interruption" .LP In all the CFA (center, fill, adjust) modes, text interruption in the input .Es c ) ( is processed such that the next text line appears to be logically glued to the current one. The resulting logical line counts as a single input line. (Actually, this appears to be only sometimes true, e.g., for .Rq ce , but not, evidently, for .Rq ul or .Rq it . Huh.) .LP Text interruption in the input will not appear explicitly in the output and thus is of no importance for postprocessors. .Es c is manifest in .I troffcvt output merely as an absence of a leading space on the next text output line. Example: .Ps .ta 1.5i \f(CBInput 1 Input 2\fP abc abc\ec def def .B "Output 1 Output 2" abc abc \0def def .Pe Postprocessors would write these out as ``abc def'' and ``abcdef'', respectively. .\" .Ah "5. Vertical Spacing" .\" .Bh "5.2. Extra line-space" .LP The .B \.a register is not set. .LP .Rq sv , .Rq os , .Rq ns , .Rq rs are not supported. .\" .Ah "7. Macros, Strings, Diversion, and Position Traps" .LP The .I troff manual doesn't say it, but .Rq rm allows multiple names to be specified for removal on a single request. .I troffcvt does, too. .LP The .I troff manual doesn't say that you can invoke macros as strings, either, but you can. .I troff prints ``abc'' when given the following input: .Ps \&.de xx abc \&.. \e*(xx .Pe You can also invoke a string as though it is a macro (i.e., by uttering the string name on a line by itself with a leading dot). The contents of the string are interpolated into the input in place of the line on which the invocation occurs. However, since strings have no terminating newline, the input line following this ``macro'' invocation is taken as part of the same input line on which the invocation occurs. .LP .I troffcvt treats macros and strings as essentially equivalent. The primary difference is that strings don't have arguments. .\" .Bh "7.3. Copy Mode" .LP The copy mode mechanism doesn't care how long strings are. .\" .Bh "7.4. Diversions" .LP These are ``supported'' in a poor way that probably should be changed. Diversion output isn't saved and just goes to .I stdout like everything else. Output for diversion .I xx is bracketed by .Cl diversion-begin .I xx and .Cl diversion-end .I xx for .Rq di or by .Cl diversion-append .I xx and .Cl diversion-end .I xx for .Rq da . Diversion output may be nested, which is one reason support is poor. (It puts the burden on the postprocessor to unnest them.) .LP Diversion output is not saved in a macro body, because diversions are often linked to position traps and thus might never be called. Since that would lose the output completely, I judged it better to interpolate the diversion into the output at the point at which it is created. The down side is that for diversions which .I are invoked explicitly, the diversion doesn't appear where it should. .LP Possibly diversion output should be saved in temporary files and written to the output when the diversion is done. But the question is: when is a diversion ``done''? (There may be a .Rq da later in the input.) .LP The .B \.d , .B \.h , .B \.t , .B dn and .B dl registers are not set. The .B \.z register is the .I name of the current diversion, .I not a numeric value. Its value is empty if no diversion is currently active, otherwise the current diversion name is interpolated into the output. .\" .Bh "7.5. Traps" .LP Position and diversion traps .Rq wh , ( .Rq ch , .Rq dt ) are not supported. .I troffcvt ought at least to write out some of the information for these requests so that postprocessors could try to use it if they wanted. .LP The input line trap .Rq it ) ( is supported. .\" .Ah "8. Number Registers" .LP The .I troff manual doesn't say it, but .Rq rr allows multiple registers to be specified for removal on a single request. .I troffcvt does, too. .LP The manual also doesn't say that if the increment or format arguments are missing, and the register already exists, the existing increment and format carry into the new definition. In .I troffcvt , only the increment carries through, since formats are broken (see below). .LP You cannot set, rename, remove or change the format of read-only registers. .LP The number register formats .B i , .B I , .B a and .B A are broken. These all print in the default format. Formats 01, 001, etc. are not parsed correctly either, yet. .LP The .B ct , .B dl , .B dn , .B hp , .B ln , .B nl , .B sb , and .B st registers are not supported. .LP The value of the .B % register is unreliable, since the ``current page number'' is unknown. .LP The .B \.A , .B \.T , .B \.a , .B \.d , .B \.h , .B \.n , .B \.t , .B \.x , and .B \.y registers are not supported. .LP The .B \.w register is always set to 1 .B en , since .I troffcvt calculates widths of strings by assuming that all characters are 1 .B en wide. (See \(sc11.) .LP The .B \.z register is anomalous, since it's not really a number; see notes for \(sc7.4. (This isn't a .I troffcvt bug; .I troff treats .B \.z specially, too.) .LP References to non-existent or unsupported registers are interpolated as ``0'' (zero). .\" .Ah "9. Tabs, Leaders, and Fields" .LP Tab and leader characters appear as .St tab and .St leader in the output. .LP .Rq ta with no arguments is written as .Cl reset-tabs . The postprocessor should reset tab settings to ``every half-inch''. If explicit settings are given, the first one is written as .Cl first-tab .I position .I type and all following as .Cl next-tab .I position .I type . .LP Field delimiter characters are written as .St fieldbegin or .St fieldend , depending on whether they begin or end a field. .LP Field padding characters are written as .St fieldpad when the character occurs between pairs of field delimiter characters (otherwise it is deleted, which may or may not be correct). .\" .Ah "10. Input and Output Conventions and Character Translations" .\" .Bh "10.1. Input character translations" .LP STX, ETX, ENQ, ACK, BEL, SO, SI and ESC are not treated specially. You deserve what you get if you have them in your input files. So there. .\" .Bh "10.2. Ligatures" .LP Ligature mode as set by .Rq lg is not supported. The special characters .lg 0 .Es (ff , .Es (fl , .Es (fl , .Es (Fi and .Es (Fi normally should be defined in the action file to write out .St ff , .St fi , .St fl , .St ffi and .St ffl , .lg and postprocessors should be trained to recognize these sequences. .\" .Bh "10.3. Backspacing, underlining, overstriking, etc." .LP No motion is generated for backspace characters; they appear as .St backspace in the output. .LP Underlining is indicated by .Cl underline for normal underlining and .Cl cunderline for continuous underlining. These are identical in .I troff ; postprocessors may or may not wish to consider them so, depending on the capabilities of the target format. Underlining (both kinds) is turned off with .Cl nounderline . .\" .Bh "10.5. Output translation" .LP .Rq tr doesn't work for special characters or for escaped characters. The output character can be anything, but the input character must be plain text. This is legal: .Ps \&.tr x\e(** .Pe This is not: .Ps \&.tr \e(**x .Pe .\" .Bh "10.6. Transparent throughput" .LP Transparent mode (\fB\e!\fR) is not supported very well. .LP Real-life observations of behavior of .I troff versions: It doesn't appear to be quite true that the rest of the line after .Es ! is always passed as is, at least from my observations on .I groff and SunOS 4.1.1 .I nroff . Embedded newlines are still processed. Comments are still stripped. If a transparent line within a multi-line section of conditional input contains .Es } on multi-line conditional input is recognized and terminates the input if it is within a rejected clause. If it is within an accepted clause, the .Es } appears on the transparent line. .\" .Bh "10.7. Comments and concealed newlines" .LP Comments and concealed newlines are swallowed at a very low level in the input routines, and are thus unavailable to postprocessors. .\" .Ah "11. Local Horizontal and Vertical Motions, and the Width Function" .LP .Es w "\'\fIstring\fR\'" computes widths of strings only to an approximation. Since character widths are unknown, the width is computed as though all characters in the string are 1 .B en wide. Font and size changes are recognized but ignored, which leads to particularly egregious errors for constructs such as \fB\ew\'\es+9\es+9\es+9X\es\-9\es\-9\es\-9\'\fR. The ramifications of the fact that .Es w yields only approximate results are legion, since .Es w may be used in any expression, e.g., in numeric arguments to requests, or in escape sequences such as .Es h \'\fIN\fR\'. .\" .Ah "12. Overstrike, Bracket, Line-drawing and Zero-width Functions" .LP .Es b "\'\fIstring\fR\'" and .Es o "\'\fIstring\fR\'" are supported by writing the characters in .I string to the output, sandwiched between .Cl bracket-begin .Cl overstrike-begin ) ( and .Cl bracket-end .Cl overstrike-end ). ( Certain characters, if present in .I string , are botched, such as .Es e . .LP .Es l "\'\fINc\fR\'" and .Es L "\'\fINc\fR\'" are supported but don't always work. In particular, if the repetition character is ``x'', as in .B \el'10x' , the ``x'' is eaten as part of the expression and not recognized as the repetition character. Certain other repetition characters aren't written to the output correctly (same bug as for .Es b and .Es o ). .LP .Es z \fIc\fR appears as .Cl zero-width .I c in the output. .\" .Ah "13. Hyphenation" .LP .Rq nh and .Rq hy appear as .Cl hyphenate .I N in the output. The value of .I N should be interpreted as indicated in the .I troff manual. If .I N is zero, hyphenation should be turned off. .LP The current hyphenation character is recognized and appears as .St opthyphen in the output. .LP .Rq hw is not supported. .\" .Ah "15. Output Line Numbering" .LP Not supported, because there is no way to determine how a postprocessor might lay out text on a page. This is especially true for .I tc2html : the resulting HTML document may be reformatted dynamically whenever a user viewing the document in a Web browser window resizes the window. .\" .Ah "16. Conditional Acceptance of Input" .LP Unfortunately, processing of conditionals .Rq if , ( .Rq ie/\.el ) is to a large extent meaningless and may introduce errors into the output. The tests for the conditions .B t and .B n are processed properly, but other tests may not be. For instance, many times a conditional will test the value of the current page number .Es n% ), ( which cannot be determined reliably. .LP Conditional requests are processed in a special way. Normally, to process a request, the arguments are parsed first. Then .I troffcvt scans to the end of the request line, to avoid having extraneous junk be parsed as text or another request, and then any actions remaining in the request's action list are executed to interpret the request arguments. .LP For conditional requests, that doesn't work. A different approach is taken. Here is how the conditional requests can be specified in an action file: .Ps req if parse-condition n eol req ie parse-condition y eol req el process-condition eol .Pe For .Rq if and .Rq ie , the argument is the condition to be tested, but after parsing it the rest of the line cannot be skipped over without losing some of the conditional input. What happens instead is that the .B parse-condition action gobbles up the condition and skips any following whitespace. If the conditional input is a single line (no .Es { present), the input-line processor is invoked once recursively, which causes the rest of the line to be processed as though it were a new line. The tricky part is that processing this line will involve reading the rest of the line, .I including the terminating linefeed. When the inner invocation of the line processor returns from handling the conditional input, the outer invocation of the processor that is handling the conditional request (i.e., the one performing the .B parse-condition action), is still in its argument-parsing phase, and still expects to skip to the end of the input line after parsing the condition. So a fake linefeed is shoved into the input before returning to the condition parser. .LP For conditional requests that are followed by multi-line input, a mild elaboration suffices. If the conditional input begins with .B \e{ , the current conditional level is incremented and the input processor is called repeatedly until the level returns to the original value. (The level is decremented by the input routine .I ChIn() which simply discards the .Es } and returns the next character.) .LP If a condition fails, the input is scanned character-by-character until the end of the current line (for single-line conditional input), or until a .Es } matching the beginning .Es { is found (for multi-line input). .LP The else part of the .Rq ie/\.el if-else construction is accepted or rejected by remembering the value of the previous .Rq ie . If the .Rq ie succeeded, the .Rq el part is skipped, otherwise it's processed. .LP It does not appear to be necessary that the .Rq el .I immediately follow .Rq ie , so .I troffcvt does not require that. .Rq el following .Rq if is skipped, as is .Rq el following another .Rq el . .LP Observations about .I troff versions (which don't really belong here, but I'm writing them down so I don't completely forget about them): .Ls B .Li .Es } anywhere in a line terminates accepted multiple-line conditional input. .Li .Es } immediately terminates rejected multiple-line conditional input. The rest of the line is processed as a new line. .Li .Es } in a transparent line is passed through if it occurs in accepted multiple-line conditional input. .Li .Es } in a transparent line immediately terminates rejected multiple-line conditional input. .Le 0 .\" .Ah "17. Environment Switching" .LP It's not explicit in the .I troff manual, but for revertible parameters such as indent or point size, the current .I and .I previous values are saved in the environment. .I troffcvt does this, too. .\" .Ah "18. Insertions from Standard Input" .LP .Rq rd is not supported. .\" .Ah "19. Input/Output File Switching" .LP .Rq nx doesn't properly unwind the input stack if current input source is not a file. The request is simply ignored after printing an error message. .LP .Rq pi is not supported. .\" .Ah "20. Miscellaneous" .LP .Rq mc , .Rq pm , .lg 0 .Rq fl .lg are not supported. For .Rq fl , this doesn't matter because output isn't buffered anyway. .\" .Ah Addendum .LP Most of the stuff mentioned in the .I troff addendum is unimplemented. .\" .Bh "A.1. Command-Line Options" .LP These are irrelevant to .I troffcvt . .\" .Bh "A.2. Requests" .LP The description of the .Rq ab request doesn't specify whether the string argument is to be read in copy mode or not. Assuming that it should be, .Rq ab can be defined in the action file as .Ps req ab parse-string-value n eol abort $1 .Pe The .Rq ad , .Rq ft and .Rq so requests behave as described. .LP Other requests in this section are unsupported. .\" .Bh "A.3. New Escape Sequences" .LP These are all unsupported. .\" .Bh "A.4. New Predefined Number Registers" .LP .B \.R and .B c\. are supported as general registers. .B \.R always contains a large value, since .I troffcvt always assumes it can get more memory. .LP .B $$ , .B \.L , .B \.b , and .B \.j are supported as read-only registers. .LP .B \.P , .B \.k , .B \.T are not supported. .\" .Bh "A.5. Other Important Changes" .LP Conditional input is treated as described. hould reset tab settings to ``every half-inch''. If explicit settings are given, the first one is written as .Cl first-tab .I position .I type and all following as .Cl next-tab .I position .I type . .LP Field delimiter characters are written as .St fieldbegin or .St fieldend , depending on whether they begin or end a field. .LP Field padding characters are written as .St fieldpad when the character occurs between pairs of field delimiter characters (otherwtroffcvt-1.04/doc/output.ms010064400017710000151000001123150634146717500175030ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TBL) tmac.wrprc thisfile | $(TROFF) $(MSMACROS) .\" .\" revision date - change whenever this file is edited .ds RD 21 May 1997 .\" .EH 'troffcvt Output Format'- % -'' .OH ''- % -'troffcvt Output Format' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .de Co \" control output .LP \fB\e\\$1\fR \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 .ft R .br .. .TL .ps +2 troffcvt Output Format .sp .3v and .sp .3v Postprocessor Writing .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .H*toc*title "Table of Contents" .\" .Ah Introduction .\" .LP .I troffcvt turns .I troff input files into a more easily parsed intermediate format to assist in the process of developing .I troff -to-XXX translators. To provide further assistance, the .I troffcvt distribution contains code for a library that sequences .I troffcvt output into tokens. The library is called the .I troffcvt reader (which means that it reads .I troffcvt output, not that it is used by .I troffcvt ). The combination of .I troffcvt and the .I troffcvt reader essentially turns .I troff files into a typed token stream. This simplifies the job of writing postprocessors. Generally a postprocessor sits on one side of a pipe reading the input from .I troffcvt , which sits on the other side of the pipe. The reader code is linked into the postprocessor and is called by it to get the next token from the pipe. .LP This document describes .I troffcvt output format and discusses how to write postprocessors that convert such output into some target format. If you decide not to use the reader when writing a postprocessor, you must understand how to interpret .I troffcvt files. If you do use the reader, then you don't need to know as much about .I troffcvt format since the reader tokenizes everything for you. However, it's still useful to have at least a rudimentary knowledge of the format. .\" .Ah "Output Format" .LP .I troffcvt writes three kinds of lines: .Ls B .Li Control lines used to control text processing. These begin with a backslash ``\fB\e\fR'' and a keyword, and may have arguments separated by spaces following the keyword. Control lines pertain to document structure. .Li Special text lines used to indicate special characters. These begin with an at-sign ``\fB@\fR'' followed by a special character name, e.g., .St grave .B \` ), ( .St quotedblleft .B `` ), ( or greek .St alpha .B \(*a ). ( The special character should be mapped to a character that is appropriate for the target format. .Li Plain text lines consisting of literal text to be written without further interpretation. Together with special text lines, plain text lines comprise the content of a document. .Le A .I troffcvt output file is structured as follows: .Ps \esetup-begin \eresolution \f(CIN\fP \fIother setup lines...\fP \esetup-end \fIrest of document...\fP .Pe The first portion of the file consists of a setup section bracketed by .Cl setup-begin and .Cl setup-end lines. The lines in between indicate the initial document layout. The first line of this information is .Cl resolution .I N , where .I N is the number of basic units per inch. This indicates the resolution at which .I troffcvt performed its calculations. Numbers obtained from other control lines may be converted to ems, points, etc., using this resolution. For instance, if the resolution is 1440, the control line .Cl spacing .B 240 indicates a baseline spacing of 1/6 inch. .LP The default resolution used by .I troffcvt is 432, but can be changed to whatever you want. Probably the .I lowest resolution you want to use is the least common multiple of 72 and the resolution you expect to use in the target format. Otherwise you may end up with ugly round-off errors when you convert units back to ems, points, etc. .LP If the resolution is .I r , other common .I troff units may be calculated as follows. .I S "" ( is the current point size.) .LP .TS center box; cfB | cfB | lfB c|l|l. Unit Name Number of basic units _ \fBi\fR inch \fIr\fR \fBc\fR centimeter \fIr\fR\^\(mu\^50\(sl127 \fBP\fR pica = 1\(sl6 inch \fIr\fR/6 \fBm\fR em = \fIS\fR points \fIS\fR\^\(mu\^\fIr\fR/72\^=\^\fISr\fR/72 \fBn\fR en = em\(sl2 \fIS\fR\^\(mu\^\fIr\fR/72\^\(mu\^1/2\^=\^\fISr\fR/144 \fBp\fR point = 1\(sl72 inch \fIr\fR/72 \fBu\fR basic unit 1 \fBv\fR vertical line space varies; set by \fB\espacing\fR \fIN\fR .TE .LP The rest of the lines in the setup section contain information for the page length, page width, indents, etc. .Ah "Special Text Lines" .LP .I troffcvt knows the names of special characters from two sources of information. The input sequence and output sequence for a given special character is either built in and recognized implicitly, or taken from an action file that is read at runtime. Special characters with an input sequence of the form \fB\e(\fIxx\fR or \fB\e[\fIxxx\fB]\fR are always in the latter category. .\" .Bh "Built-in Special Characters" .LP Built-in characters form a short list. Most of these are listed in the ``Escape Sequences for Characters, Indicators, and Functions'' section of the .I troff .B "Summary and Index" document. .LP .TS center box; cfB | cfB | cfB lfB | l | l. Input Sequence Output Sequence Note _ \ee @backslash affected by \fB.ec\fR \` @quoteleft \' @quoteright \`\` @quotedblleft \'\' @quotedblright \e& @zerospace \e^ @twelfthspace \e| @sixthspace \e0 @digitspace \e(space) @hardspace \e\- @minus \e\` @grave \e\' @acute \e% @opthyphen affected by \fB.hc\fR \ea\fR,\fISOH\fR @leader \et\fR,\fITAB\fR @tab \e(backspace) @backspace \fIvaries\fP @fieldbegin affected by \fB.fc\fR \fIvaries\fP @fieldend affected by \fB.fc\fR \fIvaries\fP @fieldpad affected by \fB.fc\fR .TE .LP The output sequence for .Es e actually depends on the current escape character, which may be changed with .Rq ec . The input sequence for the optional hyphenation character may be changed with .Rq hc . .LP The characters .B @ and .B \e have special meaning in .I troffcvt files, so they are indicated in .I troffcvt output by the specials .St at and .St backslash where they are to appear in the final output literally. Postprocessors should convert them back to .B @ and .B \e characters. .LP The field delimiter and field pad characters defined with .Rq fc are written out as .St fieldbegin or .St fieldend , and .St fieldpad . (Odd delimiters begin fields; even ones end fields). .\" .Bh "Non-built-in Special Characters" .LP The number of non-built-in characters is not fixed. All the special characters listed in the Ossanna .I troff manual are defined in the default action file supplied with the .I troffcvt distribution, but the list may be modified as necessary to reflect extra special characters available in your local version(s) of .I troff . The default action file as distributed with .I troffcvt includes a number of special characters known by .I groff . .\" .Ah "The troffcvt Reader" .\" .LP The .I troffcvt file reader reads .I troffcvt output and tokenizes it, setting several global variables in the process: .Ps .ta 1.1i tcrClass \fRtoken class\fP tcrMajor \fRtoken major number\fP tcrMinor \fRtoken minor number\fP tcrArgv[] \fRtoken text vector\fP tcrArgc \fRnumber of elements in \fPtcrArgv[]\fP vector\fP .Pe All tokens are assigned to a class. The other variables are set or not depending on the class. The classes are: .Ps .ta 1.1i tcrEOF \fRend of input\fP tcrControl \fRcontrol line\fP tcrText \fRplain text character\fP tcrSText \fRspecial text character\fP .Pe Elements of .Cw tcrArgv[] are null-terminated strings. There are .Cw tcrArgc elements in the vector. For plain text and special text tokens, .Cw tcrArgc is always 1. For control tokens, the rest of the line is automatically parsed to find any following arguments and these are placed into .Cw tcrArgv[1] through .Cw tcrArgv[tcrArgc-1] . .Cw tcrArgv[tcrArgc] is .Cw NULL in all cases. .LP All numbers on control lines are written as integers. Because numbers may be quite large, postprocessors generally should convert them to .Cw long rather than to .Cw short or .Cw int . .LP To use the reader, call .Cw TCRInit() , then call .Cw TCRGetToken() repeatedly. .Cw TCRGetToken() returns the token class value, which it also stores in the variable .Cw tcrClass . When .Cw TCRGetToken() returns .Cw tcrEOF , the input stream is exhausted and postprocessor can finish up. .LP Here is how the global variables are set for the various token classes. .LP \f(CWtcrClass = tcrEOF\fR: .Ps .ta 1.1i \fRnone of the other variables are set\f(CW .Pe \f(CWtcrClass = tcrControl\fR: .Ps .ta 1.1i tcrMajor \fRcontrol major number (see \fItcr.h\fR)\f(CW tcrMinor \fRmajor number subtype (not set for all control words, see \fItcr.h\fR)\f(CW tcrArgv[i] \fRfor i = 0, text of control word, including leading \e character\f(CW \fRfor i > 0, argument following control word\f(CW tcrArgc \fRnumber of arguments, including control word\f(CW .Pe \f(CWtcrClass = tcrText\fR: .Ps .ta 1.1i tcrMajor \fRASCII value of character (each character is a separate token)\f(CW tcrArgv[0] \fRone-byte string containing the character\f(CW tcrArgc \fR= 1\f(CW .Pe \f(CWtcrClass = tcrSText\fR: .Ps .ta 1.1i tcrMajor \fRusually \f(CWtcrSTUnknown\fR, but see below\f(CW tcrArgv[0] \fRtext of special character name, including leading @ character\f(CW tcrArgc \fR= 1\f(CW .Pe All the built-in special characters are recognized and assigned distinct major numbers. Other specials are assigned the major number .Cw tcrSTUnknown and the postprocessor must examine the text of the token .Cw tcrArgv[0] ) ( to determine what it is and what to do with it. There is no way for the reader to assign fixed numbers to these since the set of special characters understood by .I troffcvt isn't fixed. One way of dealing with the problem is to read at runtime a file of all the special character names you expect to see. (Usually the same set of names specified in the action file used with .I troffcvt .) .LP Note: although built-in special characters .I do have fixed major numbers assigned, there is nothing to prevent you from processing them like other specials, i.e., by examining the token text. It may be more convenient to treat all specials uniformly. .LP The reader changes the characteristics of the default token scanner. This is done in .Cw TCRInit() . If you use the token scanning library for other purposes in your application, you need to change the scanner's characteristics to what you want and then restore them, or .Cw TCRGetToken() may not work correctly. .\" .Bh "Other Global Variables" .\" .LP The .Cw tcrLineNumber holds the current input line number. This may be useful when printing error messages. Be aware that this is not the line number of the original .I troff input given to .I troffcvt ; it's the line number of the output from .I troffcvt . .\" .Ah Postprocessors .\" .LP I assume in this section that you use the .I troffcvt reader to write a postprocessor. It's not necessary that you do so, but if you don't, most of the following comments don't apply. .LP It's best that you examine the source for some of the postprocessors supplied in the .I troffcvt distribution before trying to write one of your own. You should also read the document .H*ahref bugs.html \fItroffcvt \*- Notes, Bugs, Deficiences\fR .H*aend to acquaint yourself with .I troffcvt 's many limitations. .LP A postprocessor can be set up this way: .Ls B .Li Call the reader to read tokens until .Cl setup-end is seen, processing control lines to initialize the document layout state. .Li Dump out initial layout information (if necessary) in a form appropriate to the target format. .Li Call the reader to read the rest of the document until it returns .Cw tcrEOF . Process each token as it is returned: .Ls B .Li .B "Plain text" .sp .5v Write the character to the output, except that end of line character(s) should be ignored (CR, LF or CRLF, depending on the convention used on your system). .Li .B "Special text" .sp .5v The special character should be mapped to a character appropriate for the target format and written out. If no exact equivalent is available, something reasonably close should be substituted. For instance, .St quotedblleft denotes double left curly quotes. If the output format has only straight quotes (\fB"\fR), that might be a reasonable substitute. .sp .5v In extreme cases, no reasonable substitute exists. When this happens, some translators supplied in the distribution adopt the convention of writing ``[[\fIcharacter-name\fR]]''. This is based on the assumption that it's better to write some sequence that makes it obvious the character occurred in the input than simply to drop it. .Li .B "Control tokens" .sp .5v Modify the document processing state. .Le 0 .Le The procedure described above may seem deceptively simple, and, considered in the abstract, it is. I find it easiest to begin with a copy of .I tc2null.c , which simply routes tokens through a bunch of switch statements. The switches can be filled in as you decide what to do with various tokens, which allows incremental development of a postprocessor. You'll probably find that, although this approach is simple conceptually, in practice the details quickly can become more complex than you'd like. Some of the important issues about which you need to be concerned are discussed in the following sections. .\" .Bh "Special Character Handling" .LP How will you specify what to do with special characters? Remember that the reader assigns distinct major numbers to only those special characters for which recognition is built into .I troffcvt . .LP Generally, postprocessors read in a list of special characters that parallels the list given in the action file used by .I troffcvt . If the action file list is changed, all the lists used by various postprocessors need to be changed, too. This is a headache, but at least the changes can be made by editing text files rather than by recompiling programs. .LP To get a list of all the special character names, run this command in the .I misc directory: .Ps % \f(CBchk-specials /dev/null > junk .Pe This puts into .I junk all the special character names that are not found in .I /dev/null , which, since that file is empty, will be all the names. You can use the contents of .I junk as a basis for constructing the output sequences you want the postprocessor to emit for various special characters. .LP To test the postprocessor, you can run .I list-specials , another command in the .I misc directory that generates a .I troff -format listing of all the special characters and their names. But running the output of .I list-specials through .I troffcvt and the postprocessor, you can see how each special character is actually treated. .\" .Bh "Text Centering, Filling, and Adjusting" .\" .LP Text centering, filling, and adjusting interact in .I troff . My understanding of how this works is indicated below. Since my conceptual scheme is instantiated in the code, let's hope it's correct. .LP Centering .Rq ce ) ( takes precedence over filling and adjustment. When centering is not on, no-fill mode .Rq nf ) ( suspends filling and adjustment; input lines are copied to the output, left justified. If centering is off and filling is on .Rq fi ), ( input lines are joined as necessary to fill output lines, which are then adjusted according to the current adjustment specified by .Rq ad . Adjustment may be suspended with .Rq na . .LP Turning off filling merely suspends adjustment. The adjustment setting is remembered and goes back into effect when filling is turned back on. Similarly, centering doesn't change the filling or adjustment settings; they are suspended while centering is in effect and resume when centering terminates. .LP .I troffcvt removes the need for postprocessors to handle these centering, filling and adjusting (CFA) interactions, by always explicitly writing out which CFA control code to use. This means the postprocessor only need remember the most recent one. If .I troffcvt did not do this, postprocessors would need to maintain a bunch of state variables (currently centering? currently filling? currently adjusting? which type of adjustment?). .LP The CFA control words are: .Ps \eadjust-center \eadjust-full \eadjust-left \eadjust-right \ecenter \eno-fill .Pe When .Cl center occurs, centering should be turned on. All text up to a .Cl break should be placed on a single output line and centered. Centering continues until a different CFA control occurs. .LP When .Cl nofill occurs, no-fill mode should be turned on. All text up to a .Cl break should be placed on a single output line, left-justified. No-fill mode continues until a different CFA control occurs. .LP If neither centering nor no-fill are in effect, filling is on and one of the adjustment modes .Cl adjust-left , .Cl adjust-right , .Cl adjust-full or .Cl adjust-center will be issued. All text up to the next .Cl break should be used to fill output lines. All output lines in a paragraph except the last should be adjusted in the proper way. .LP Postprocessors can likely treat .Cl center and .Cl adjust-center as equivalent. Ditto for .Cl nofill and .Cl adjust-left . .LP Note that there are no control words such as .Cl nocenter , .Cl fill or .Cl noadjust . Centering is turned off by .Cl nofill and the adjustment indicators. Filling is turned on by the adjustment indicators. The .I troff no-adjust request .Rq na seems functionally equivalent to left-adjustment and so is indicated with .Cl adjust-left . The reason for the .Rq na request seems to be so that .Rq na can be followed by .Rq ad (with no argument) to resume whatever adjustment mode was in effect prior to the .Rq na . Since .I troffcvt keeps track of adjustment modes it can write out the proper indicator explicitly. .LP It is not the case that .I troffcvt output will contain a single line of text corresponding to each input line when no-fill or centering are in effect. For example, when input contains special characters, each of these appears on a separate output line. Thus, it's important to read text until a .Cl break is seen. .\" .Bh Paragraphing .\" .LP Some document formats indicate paragraphs when they begin, others when they end. The postprocessor will need to follow whichever convention is used in the target format. This should be a simple matter since paragraph beginnings and endings both are readily located in .I troffcvt output. .B \ebreak corresponds to paragraph endings. Beginnings are easily found also: the first text line begins one, and every time a .B \ebreak occurs, the following text line begins one. (Remember that there may be other non-text lines between the .B \ebreak and the following text line, though.) .LP Paragraph text should be treated conceptually as one unbroken string of text, even though it may appear physically on several lines of .I troffcvt output. Thus, successive text lines (either plain or special) should be considered to be part of the same paragraph until a .Cl break control line occurs. The postprocessor should perform line filling and wrapping according to the most recent centering, filling or adjustment control line (one of .Cl center , .Cl nofill , .Cl adjust-left , .Cl adjust-right , .Cl adjust-full or .Cl adjust-center ). .LP All characters on plain text lines are significant except the terminating linefeed, which should be ignored. Postprocessors should not treat leading or trailing spaces as extraneous without a good reason. Postprocessors also should not insert space characters between successive text lines; where necessary, spaces will already have been placed within the text itself. One exception is that the decision as to whether to put one or two spaces between sentences is left to the postprocessor. The main difficulty is determining when a sentence ends. If the usual suggested style for creation of .I troff input files is followed (i.e., that each sentence should begin on a new line), sentence-terminating periods, question marks and exclamation points will occur at the ends of lines. This property is preserved in .I troffcvt output. Postprocessors thus can locate sentence endings and have the information they need for determining whether to insert extra spaces, should they wish to do so. .\" .Bh "Font Handling" .\" .LP Font handling can be a difficult issue. How do .I troff fonts correspond to the fonts available in your target format? One problem is that cannot predict in advance which fonts might be used in a .I troff document (although you can probably determine which ones are available at your site). .LP Another problem is that the way fonts are treated in .I troff doesn't correspond well to the way they're treated in other document formats (at least in my experience). In .I troff one switches from plain text to italic or boldface by switching fonts, e.g., from .B R to .B I , or from .B R to .B B . It is evident that .I troff collapses the two dimensions of typeface and style onto a single-dimensional font namespace. For some formats this can be handled by leaving the typeface the same but applying different style attributes to it. .LP For purposes of font support in the .I troffcvt reader it may be more fruitful to map .I troff font names onto typeface-style pairs, where the typeface is the font family a given font derives from and the style indicates those attributes that need to be applied to the plain font in that family to produce the effect of the .I troff font. For instance, the default .I troff fonts .B R , .B I and .B B can be described as follows: .LP .TS center box; lfB | lfB | lfB l | l | l . Font Typeface Style _ R Times plain I Times italic B Times bold .TE .LP Treating fonts this way allows .I troff fonts to be manipulated so that ``font'' changes that really correspond to style changes can be handled as such. .LP A simple font to typeface-style map is included in the distribution (the .I tcr-fonts file). This file should be modified as necessary to reflect fonts available locally at your site and installed into the .I troffcvt library directory. .I r-font.c contains the code to use the font map. The sample postprocessor .I tc2rtf.c shows one way to use it. .\" .Bh Tabs .LP Tab stops should be interpreted relative to the current indent, .I not the page offset. This means that if tab stops are set and then the indent is changed, the effective tab stops relative to the page offset change. Some postprocessors may need to reset tabs in the target format when that happens. .\" .Ah "Control Line Reference" .\" .LP The section documents the syntax of all control lines produced by .I troffcvt . The descriptions are grouped according to the section of the Ossanna .I troff manual to which they are most closely related. The exceptions are section 0, which contains descriptions for miscellaneous controls that don't correspond to anything in the .I troff manual, and section 15, which describes controls for table processing. .LP Unless otherwise indicated, numeric values on control lines are specified in basic units. .\" .Bh "\(sc 0. Miscellaneous" .\" .Co setup-begin .\" .IP Indicates the beginning of the setup section of .I troffcvt output. .\" .Co setup-end .\" .IP Indicates the end of the setup section of .I troffcvt output. When it occurs, the basic layout of the document will have been specified. .\" .Co resolution \fIN\fR .\" .IP This line occurs first within the setup section. It indicates the resolution at which .I troffcvt performed its calculations, in basic units per inch. .\" .Co comment \fIstring\fR .\" .IP Indicates a comment, which may be ignored. The entire .I string will be in .Cw tcrArgv[1]. .Cl comment lines may appear .I "at any time" , even before .Cl setup-begin . .\" .Co pass \fIstring\fR .\" .IP Pass .I string literally through to the output without interpretation. This is used for postprocessor-specific purposes. The entire .I string will be in .Cw tcrArgv[1]. .\" .Co line \fIfilename linenumber\fR .\" .IP This indicates the point at which line .I linenumber was read from file .I filename . .Cl line controls are generated if the .B \-l command line option was given to .I troffcvt . They provide a way of tracking the output that results from each input line. .\" .Co other \fIstring\fR .\" .IP Indicates a line that doesn't fall into any other class. The contents of .I string can be used for anything. .I string is parsed into separate arguments. .\" .\" .Bh "\(sc 2. Fonts and Character Size Control" .\" .Co font \fIF\fR .\" .IP Switch to font .I F . .\" .Co constant-width \fIF\fR .\" .IP Treat font .I F as though it is non-proportional (each character the same width). .\" .Co noconstant-width \fIF\fR .\" .IP Stop treating font .I F as though it is non-proportional. .\" .Co embolden \fIF N\fR .\" .IP Embolden font \fIF\fR by smearing it .I N units. If .I N is zero, emboldening should be turned off. .IP If you implement emboldening, you might find it more profitable to ignore the smear value and make the font bold by some means other than reprinting the characters slightly displaced from the original printing like .I troff does. .\" .Co embolden-special \fIF N\fR .\" .IP Like .Cl embolden , but embolden characters in the special font whenever the current font is .I F . In practice, this probably has no meaning for most postprocessors, because the special font in .I troff is logically part of the three default fonts, something unlikely to be true in the target output format. .\" .Co point-size \fIN\fR .\" .IP Set point size to .I N . .I N is number of points, not basic units. .\" .Co space-size \fIN\fR .\" .IP Set space size to .I N /36\fBm\fR. Note that the actual instantaneous value depends of the size of an .B em (and thus on the current point size). For this reason it may be best to maintain .I N but also recompute the actual space size in basic units whenever the point size changes. .\" .Bh "\(sc 3. Page Control" .\" .Co begin-page [\fIN\fR] .\" .IP If .I N is present, begin new page numbered .I N . Otherwise, just begin new page (presumably numbered in sequence with the current page). .\" .Co offset \fIN\fR .\" .IP Set page offset to .I N . .\" .Co page-length \fIN\fR .\" .IP Set page length to .I N . .\" .Co page-number \fIN\fR .\" .IP Set page number to .I N . (Does not begin a new page.) .\" .Co need \fIN\fR .\" .IP .I N units of vertical space are needed. If less than that remains on the current page, begin a new page. .\" .Co mark .\" .IP Remember the current vertical position on the page. This assumes you have some notion of the current position, of course. Not all target formats have such a notion; .I troffcvt itself certainly doesn't. .\" .Bh "\(sc 4. Text Filling, Adjusting, and Centering" .\" .ne 4 .Co adjust-center .\" .sp -.7v .Co adjust-full .\" .sp -.7v .Co adjust-left .\" .sp -.7v .Co adjust-right .\" .IP Fill output lines, adjusting as indicated. .\" .Co nofill .\" .IP Do not fill output lines. .\" .Co center .\" .IP Center output lines. .\" .Co break .\" .IP End of input line. Flush and terminate current output line. .\" .Co break-spread .\" .IP Break at end of current word and spread output line to current line length. .\" .Bh "\(sc 5. Vertical Spacing" .\" .Co spacing \fIN\fR .\" .IP Set vertical base-line spacing to .I N units, which becomes the meaning of 1 .B v . .\" .Co line-spacing \fIN\fR .\" .IP Set line spacing to .I N .B v 's. .\" .Co space \fIN\fR .\" .IP Space vertically .I N units (negative = upward). .\" .Co extra-space \fIN\fR .\" .IP Indicates that the current output line should have .I N \fBv\fP of extra space added to it. .\" .Bh "\(sc 6. Line Length and Indenting" .\" .Co indent \fIN\fR .\" .IP Set indent to .I N units. .\" .Co line-length \fIN\fR .\" .IP Set line length to .I N units. .\" .Co temp-indent \fIN\fR .\" .IP Temporarily set indent to .I N units. This is an absolute indent, not an value by which to adjust the current indent. In .I troff , the temporary indent value is used only for the next output line and the prevailing indent is used again after that. In other formats it likely corresponds to ``paragraph first line indent'' or something similar. .\" .Bh "\(sc 7. Macros, Strings, Diversions, and Position Traps" .\" .Co diversion-begin \fIname\fR .\" .IP Indicates that subsequent output, until .Cl diversion-end .I name occurs, was intended in the original input to be diverted to macro .I xx . .\" .Co diversion-append \fIname\fR .\" .IP Indicates that subsequent output, until .Cl diversion-end .I name occurs, was intended in the original input to be appended to diversion macro .I xx . .\" .Co diversion-end \fIname\fR .\" .IP Indicates end of preceding .Cl diversion-begin .I name or .Cl diversion-append .I name . .\" .Bh "\(sc 9. Tabs, Leaders, and Fields" .\" .Co reset-tabs .\" .IP Reset tab stops to default (every half-inch). .\" .Co first-tab \fIN c\fR .\" .IP Clear tab stops and install first one at .I N units. .I c is .B l (left), .B c (center), or .B r (right). .\" .Co next-tab \fIN c\fR .\" .IP Add tab stop to current set. .I N and .I c are as for .Cl first-tab . .\" .Co tab-char [\fIc\fR] .\" .IP Set tab repetition character to .I c . If .I c is missing, tabs should be implemented as motion. .\" .Co leader-char [\fIc\fR] .\" .IP Set leader repetition character to .I c . If .I c is missing, leaders should be implemented as motion. .\" .Bh "\(sc 10. Input and Output Conventions and Character Translations" .\" .Co underline .\" .IP Turn on underlining. .\" .Co cunderline .\" .IP Turn on continuous underlining. .\" .Co nounderline .\" .IP Turn off underlining (both kinds). .\" .Co underline-font \fIF\fR .\" .IP Set underline font to .I F . .\" .Bh "\(sc 11. Local Horizontal and Vertical Motions, and the Width Function" .\" .Co motion \fIN c\fR .\" .IP Move .I N units. .I c is .B h for horizontal motion (negative = left) or .B v vertical motion (negative = upward). .\" .Co line \fIN c\fR .\" .IP Draw line. .I N and .I c are as for .Cl motion . .\" .Bh "\(sc 12. Overstrike, Bracket, Line-drawing, and Zero-width Functions" .\" .Co bracket-begin .\" .IP Characters on following text lines (until .Cl bracket-end ) should be used to build a bracket. .\" .Co bracket-end .\" .IP Terminates preceding .Cl bracket-begin . .\" .Co overstrike-begin .\" .IP Characters on following text lines (until .Cl overstrike-end ) should be overstruck. .\" .Co overstrike-end .\" .IP Terminates preceding .Cl overstrike-begin . .\" .Co zero-width \fIc\fR .\" .IP Print .I c without changing position on page. .\" .Bh "\(sc 13. Hyphenation" .\" .Co hyphenate \fIN\fR .\" .IP Set hyphenation mode. If .I N is zero, turn off hyphenation. If .I N is non-zero, interpret .I N as in the .I troff manual. .\" .Bh "\(sc 14. Three Part Titles" .\" .Co title-length \fIN\fR .\" .IP Set title length to .I N units. .\" .Co title-begin \fIc\fR .\" .IP Indicates the beginning of title part .I c , where .I c is .B l (left), .B c (center), or .B r (right). Text up to the next .Cl title-end control line should be taken as the content of this title part. .I troffcvt indicates title content by writing the following output sequence: .Ps \etitle-begin l \fItext of left title part\fP \etitle-end \etitle-begin m \fItext of middle title part\fP \etitle-end \etitle-begin r \fItext of right title part\fP \etitle-end .Pe If no text occurs between the .Cl title-begin and .Cl title-end lines, it means the specified title part is empty. No control words will occur between the .Cl title-begin and .Cl title-end lines. .\" .Co title-end .\" .IP Terminates preceding .Cl title-begin . .\" .Bh "\(sc 15. Tables" .\" .LP The .I troffcvt language contains special controls to indicate table structure. These result when .I tblcvt is used to preprocess .I troffcvt input. The controls should be written by .I troffcvt in a particular order, but .I troffcvt itself does no checking to verify the ordering. It relies on .I tblcvt to generate table-related requests that specify table elements in the proper sequence. For more details, see the document .H*ahref tblcvt.html .I "tblcvt \*- A troffcvt Postprocessor." .H*aend .LP For testing .I tblcvt , see the .I tblcvt/tests directory, which contains the tables from the Lesk .I tbl document, one table per file. .\" .Co table-begin \fIrows cols header-rows align expand box allbox doublebox\fP .\" .IP Indicates the beginning of a table. .IP .I rows and .I cols are the number of rows and columns in the table. (A row that draws a line is considered a data row.) .IP For tables that are specified to have a header (using .Rq TS .B H and .Rq TH ), .I header-rows is non-zero. Otherwise .I header-rows is 0. .I header-rows indicates how many of the initial data rows make up the table header. If this is non-zero, that many rows form a header that should be repeated if the table spans multiple pages. For a single-page table, header rows should be treated as just an ordinary part of the table. .IP .I align is .B L or .B C to indicate the table is left-justified or centered. .IP .I expand is .B y if the table is expanded to the full line width, .B n otherwise. .IP The .I box , .I allbox , and .I doublebox values are each .B y or .B n , depending on whether or not .B box , .B allbox , and .B doublebox were given in the table specification. (Note that .B allbox and .B doublebox both imply .B box .) .\" .Co table-end .\" .IP Indicates the end of the current table. .\" .Co table-column-info \fIwidth sep equal\fP .\" .IP Specifies values that apply to all cells in a table column. Following the .Cl table-begin control, there will be one .Cl table-column-info line for each column of the table. The column number is not specified; the controls for each column are written consecutively. .IP .I width is the minimum required width of the column. The value is non-zero if any entry in the given column specified a .B w option. If more than one entry specified .B w , the last one is used. If .I width is 0, no entry in the column specified .B w and the width is determined from the data values in the column. .IP .I sep is the column separation value. .IP The .I equal value is .B y if any entry in the column specified the .B e option, and .B n otherwise. All columns with an .I equal value of .B y should be made the same width. .\" .Co table-row-begin .\" .IP Indicates the beginning of a row within a table. .\" .Co table-row-end .\" .IP Indicates the end of the current table row. .\" .Co table-row-line \fIN\fP .\" .IP Indicates that the table row is a single or double table-width line. The value of .I N indicates the type of line: .Ps \etable-row-line 1 \fRTable-width single line\fP \etable-row-line 2 \fRTable-width double line\fP .Pe There is no end marker for this control, as none is needed. .\" .Co table-cell-info \fItype vspan hspan vadjust border\fP .\" .IP Indicates layout information for a a cell within a table row. .IP .I type is the cell type: .Ps .ne 5 .ta 1i L \fRLeft-justified\fP R \fRRight-justified\fP C \fRCentered\fP N \fRNumeric (align to decimal point)\fP A \fRAlphanumeric\fP .Pe .I vspan and .I hspan are the number of rows and columns spanned by the cell, including itself. Interpret these values as follows: .Ls B .Li If a cell doesn't span any other cells (the usual case), both .I vspan and .I hspan are 1. .Li If a cell spans other cells vertically, .I vspan is greater than 1. If a cell is spanned vertically by a cell from above, .I vspan is zero. .Li If a cell spans other cells horizontally, .I hspan is greater than 1. If a cell is spanned horizontally by a cell from the left, .I hspan is zero. .Le If all you want to know is whether or not a cell is spanned, the product of .I vspan and .I hspan is zero if and only if the cell is spanned. If you need to know whether spanning is in a particular direction, you need to examine .I vspan and .I hspan individually. This is summarized in the following table. .sp .5v .TS l lfB lfB lw(1i)fB lw(2i) lw(2i) . hspan = 0 hspan > 0 vspan = 0 spanned both ways spanned from above vspan > 0 spanned from left not spanned .TE .sp .5v .I vadjust is .B T if the cell contents should be vertically adjusted from the top, .B C if the contents should be vertically centered. .I vadjust is meaningful only for multiple-line cells. .IP .I border is the border value. If the value is 0, there is no border. Otherwise, the value is a bitmap with the following fields: .Ps .ne 9 .ta 1i 2i \fBBits Value Meaning\fP 0-1 1 \fRLeft border, single line\fP 3 \fRLeft border, double line\fP 2-3 1 \fRRight border, single line\fP 3 \fRRight border, double line\fP 4-5 1 \fRTop border, single line\fP 3 \fRTop border, double line\fP 6-7 1 \fRBottom border, single line\fP 3 \fRBottom border, double line\fP .Pe .\" .Co table-cell-begin .\" .IP Indicates the beginning of a table cell. .\" .Co table-cell-end .\" .IP Indicates the end of the current table cell. .\" .Co table-empty-cell .\" .IP Indicates a table cell that is empty. There is no end marker for this control, as none is needed. .\" .Co table-spanned-cell .\" .IP Indicates a table cell that is spanned by an earlier cell. There is no end marker for this control, as none is needed. Note that that spanned cell may be spanned by a cell with data in it, an empty cell, or a line-drawing cell. .\" .Co table-cell-line \fIN\fP .\" .IP Indicates that the content of a table cell is a line. The value of .I N indicates the type of line: .Ps \etable-cell-line 0 \fRColumn-data-width single line\fP \etable-cell-line 1 \fRColumn-width single line\fP \etable-cell-line 2 \fRColumn-width double line\fP .Pe There is no end marker for this control, as none is needed. pace \fIN\fR .\" .IP Space vertically .I N units (negative = upward). .\" .Co extra-space \fIN\fR .\" .IP Indicates that the current output line should have .I N \fBv\fP of extra space added to it. .\" .Bh "\(sc 6. Line Length and Indenting" .\" .Co indent \fIN\fR .\" .IP Set indent to .I N units. .\" .Co troffcvt-1.04/doc/tc2rtf.ms010064400017710000151000000161010634043512200173250ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 20 May 1997 .\" .EH 'tc2rtf Notes'- % -'' .OH ''- % -'tc2rtf Notes' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt or RTF control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .TL .ps +2 tc2rtf Notes .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .H*toc*title "Table of Contents" .\" .Ah Introduction .\" .LP .I tc2rtf is a postprocessor for converting .I troffcvt output to RTF. This document describes how it works and some of the design issues involved in writing it. .\" .Ah "General Paragraph Formatting Properties" .\" .LP In RTF paragraph formatting properties can only be set once per paragraph, which means that once a paragraph has begun its properties are frozen. Some ways of resetting them are: (i) after the .Cl par at the end of the previous paragraph, issue a .Cl pard followed by new settings; (ii) put each paragraph in a group, and issue settings within each group. Each approach is similar in that paragraph properties are reset to some default and then can be set as appropriate for a new paragraph. .LP There are some differences between the approaches. The first approach resets paragraph properties to the RTF defaults. The second resets them to the paragraph state in effect at the time the group for the first paragraph is begun. This means it's possible to set up some arbitrary default which can be restored simply by beginning a new group. But it also undoes any changes made to character properties within the group. The first approach is ``flatter'' because there are fewer groups, and simpler in the sense that it's not necessary to restore any character formatting properties. The second approach is simpler in the sense that it's likely fewer paragraph properties will need to be reset, since the default state is more likely to be close to the format used throughout the document. .LP It's not obvious that either approach enjoys clear advantages over the other. .I tc2rtf uses the first approach. .LP The above discussion assumes all changes to paragraph properties occur between paragraphs and not within paragraph text. It's possible for .I troffcvt output to contain within-paragraph changes, however, since .I troff requests can occur anywhere, and can be specified with a no-break control character. If such changes are written in the middle of a paragraph, they do bad things things to RTF readers (e..g., Microsoft Word 5.0 botches a paragraph badly if .Cl li or .Cl fi are set in the middle). Two ways to handle this problem are to force a .Cl par if a paragraph format change occurs within a paragraph, or to ignore the change when it occurs and let it take effect after the paragraph ends (``lazy evaluation!''). It's not evident that either solution is ``correct.'' .I tc2rtf adopts the latter. .\" .Ah "Margins and Indents" .\" .LP .I troff has concepts of page offset, indent, temporary indent, and line length. (These are expressed in .I troffcvt output as .Cl offset , .Cl indent , .Cl temp-indent and .Cl line-length ). These are not isomorphic to RTF, which has concepts for left and right margins, left and right indent, and first-line indent for the first line of a paragraph. (These are expressed in RTF as .Cl margl , .Cl margr , .Cl li , .Cl ri and .Cl fi .) .LP The .I troff settings can be changed at any time. The RTF left and right margin values are document formatting properties, and can only be set once (before any document text). The indents can only be set once per paragraph, as discussed above. .LP Differences between the two methods of expressing page layout are handled as follows. Output is turned off while .I tc2rtf is reading the setup section of .I troffcvt output. When the setup information has been completely read .Cl setup-end "" ( has been seen, .I tc2rtf assumes that the current offset+indent should be the document left margin, and that any space on the right not taken up by offset, indent or line length should be the right margin. Thereafter, changes in offset or indent may change the left indent, relative to the left margin. Changes in offset, indent or line length may change the right indent, relative to the right margin. .LP Changes in the temporary indent are mapped onto first-line indent, on the assumption that .Cl temp-indent will normally occur before the text of a paragraph. A difference between .I troff and RTF is that the .I troff temporary indent is relative to the page offset, while RTF first-line indent is relative to the current left indent. .LP The temporary indent is reset to be equal to the left indent at each .Cl par since in .I troff the .Rq ti setting is transient. .LP Another difference between .I troff and RTF is that the temporary indent changes the tab settings for the first line of a paragraph, whereas the first-line-indent in RTF does not. .I tc2rtf does not attempt to simulate .I troff 's behavior, since there isn't any way of knowing when the second line of a paragraph has been reached. (RTF includes no mechanism for expressing or discovering font metrics.) .\" .Ah Tabs .\" .LP .Cl leader-char and .Cl tab-char are both ignored. Leaders and tabs are always written as plain tab characters. .\" .Ah "Tables" .\" .LP A document containing .I tbl input is best handled by using .I tblcvt to preprocess the document before feeding the result to .I troffcvt and .I tc2rtf . .LP Tables are a pain to do well in RTF. As the RTF specification says, ``tables are probably the trickiest part of RTF to read and write correctly.'' While adding support for .I tblcvt -related output to .I tc2rtf , I found it alarmingly easy to crash or lock Word (both Macintosh and Windows versions) unless table controls were written just right. Even now I'm not overly confident that tables are written correctly, though .I tc2rtf table output no longer seems to cause crashes. One of the keys is to make sure to write .Cl intbl in each cell, even for empty cells. Further, it's typically a good idea to emit .Cl pard for each cell, but it must be written .B before the .Cl intbl , not after. Otherwise Word seems to forget that it's in a cell. (This seems silly. Surely if you've seen .Cl intbl but not .Cl cell or .Cl row it's reasonable to expect Word to consider itself still in the cell? Apparently not.) .\" .Ah "Brackets, Overstrikes" .\" .LP I don't know how to do these in RTF, so what .I tc2rtf does is write out ugly but highly visible sequences to make it obvious to the user that the document contains stuff that needs some hand tuning. Bracket characters are written out surrounded by .Cw BRACKET> . Characters which should be overstruck are written out surrounded by .Cw OVERSTRIKE> . Ick. troffcvt-1.04/doc/troffcvt.ms010064400017710000151000001231030633773157200177750ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 18 May 1997 .\" .EH 'troffcvt \*- A troff Converter'- % -'' .OH ''- % -'troffcvt \*- A troff Converter' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .de Ac \" action .LP .ta \n(LLuR \(bu \\$1 (\fB\\$2\fR) .br .. .TL .ps +2 troffcvt \*- A troff Converter .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .AB Yet another .I troff -related program, with yet another set of misassumptions about how .I troff interprets its input, and its own set of deficiencies and bugs. .AE .\" .H*toc*title "Table of Contents" .\" .Ah Introduction .\" .LP This document describes .I troffcvt (``\fItroff\fR convert''), a program which assists in the process of converting .I troff documents to other formats. .I troffcvt doesn't do the full job of translation itself; rather, it is a preprocessor that turns .I troff files into an intermediate format with a syntax that is easier to interpret than the raw .I troff input language. .I troffcvt is intended as a front end that supplies input to a postprocessor which finishes the translation to produce output in the target format. Since the job of writing a translator for a given target format then need not include writing a .I troff -parser, the burden of the translator writer is reduced. In a sense, .I troffcvt is simply another sort of .I ditroff , one that produces a different output language than does .I ditroff . .LP .I troffcvt started out as a .I sed script for converting .I troff to RTF (Rich Text Format), but it quickly became evident that that wasn't going to be a very simple job to do correctly. It seemed a better justification of effort to write a more general tool that would be useful in contexts other than that of RTF production. The source distribution contains some example translation methods (simple postprocessors) you can look at. A standard .I troffcvt output reader is included in the distribution; it can be configured for use with your own postprocessors. .LP .I troffcvt has a number of significant shortcomings. It doesn't do very well with input that has been passed through .I tbl , .I eqn or .I pic . (For input containing tables, you can use .I tblcvt rather than .I tbl to get better results.) .I troff constructs that involve determination of motion or sizes sometimes are calculated inaccurately since .I troffcvt knows nothing of font metrics. Conditional construct processing is problematic also, as are position-dependent traps. .I troffcvt has other limitations; if those just listed are insufficient to dissuade you from using it as the basis for a translator, see the document .H*ahref bugs.html .I "troffcvt \*- Notes, Bugs, Deficiencies\c" .H*aend \&. .\" .Ah "Translation Model" .\" .LP .I troff files consist of text to be formatted interspersed with markup requests indicating how the formatting is to be done. The language implemented by .I troff is essentially an inverted programming language, where document text comprises the comments and markup requests provide the program indicating how to format the comments. This language isn't especially easy to parse, which may be why there are few tools for translating .I troff documents into other formats. Most tools that do exists seem to use pattern match-based transformations, rather than making any attempt to actually understand the .I troff language. The purpose of .I troffcvt is to make it easier to write .I troff -to-XXX translators, for arbitrary XXX, by doing the hard work of turning .I troff input into something easier to interpret. This means part of the job is already done for postprocessor writers, who can then concentrate on producing output in the desired target format rather than on figuring out how to understand .I troff files. .LP For example, point size might be set by some disgusting sequence like this: .Ps .ne 5 \&.ds x *a \&.ds y *b \&.nr \e(\e*x\e(\e*x 12 \&.ds \e(\e*y\e(\e*y \e\en(\e(\e*x\e(\e*x \&.ps \e*(\e(\e*y\e(\e*y .Pe This is digested by .I troffcvt and appears in the output in somewhat simpler form: .Ps \epoint-size 12 .Pe .I Caveat: The quality of translators obviously depends on the quality of .I troffcvt 's preprocessing, which is suspect. Nor is the situation improved by the fact that various versions of .I troff sometimes do different things with identical input. This makes it difficult for .I troffcvt to do the ``correct'' thing in all cases, especially for input files that have been tailored to work with (i.e., around bugs in) a particular version of .I troff . .LP .I troffcvt produces output that preserves information about the structure of a document (e.g., margins, page length) and its contents (the text it contains). The goal is .I not to lay out text on pages. That is left to postprocessors, which are expected to lay out document content by interpreting structure information. Postprocessors may use the structure and/or content to varying extents. For instance, a postprocessor that simply extracts the text would ignore the structure information. A postprocessor that produces a summary of the structure (e.g., page layout information) would ignore the text. Most postprocessors will fall somewhere between these extremes. .LP Inevitably, a certain amount of information is lost. Usually this results from not knowing all the characteristics of the output device. For instance, no font metric information is used, so it's not possible to determine the position on the current page, or even to know what the current page number is. .LP An example of .I troffcvt operation is shown below. (The default resolution of 432 units/inch is assumed.) .Ps .ta 3i \f(CBInput Output\fP \&.ps 14 \epoint-size 14 \&.vs 16 \espacing 96 \&.ce \ecenter \&.ft B \efont B troffcvt\e\-a troff converter troffcvt \&.ft @minus a troff converter \ebreak \eadjust-full \efont R .Pe .\" .Ah "troffcvt Output" .\" .LP .I troffcvt produces a mixture of control and text lines. Control lines correspond to document structure. They consist of a backslash character .Cw \e followed by a control word and possibly some parameters for the control word, e.g., .Cl space , .Cl "font R" , .Cl "page-length 4752" . Text lines correspond to document content, and are either plain text written literally to the output, or begin with a ``@'' to indicate special characters (for instance, .St bullet for the ``\(bu'' character or .St alpha for ``\(*a''). .LP None of the control or special-text keywords overlap, but it's still convenient to use different leading characters .B \e and .B @ to make it easier for simple filter programs to distinguish between them. For example, the following command strips control lines from a file containing .I troffcvt output: .Ps % \f(CBsed \-e "/^\|\e\e\|/d"\fP \f(CIfilename\fP .Pe .I troffcvt output is rife with .I troff -isms, such as .Cl need and .Cl embolden . Little effort was made to map these to more general document layout concepts since it's not clear what gain, if any, there would be in doing so. .\" .Ah "How troffcvt Works" .\" .LP There are two steps to turning .I troff files into some other format: .Ls B .Li Run .I troffcvt to turn .I troff files into input for your postprocessor. .Li Run the postprocessor to generate final output. .Le .I troffcvt is configured by means of action files, which are described below. .I troffcvt postprocessor writing is a separate issue from understanding how .I troffcvt itself works, and is covered in a separate document, .H*ahref output.html .I "troffcvt Output Format and Postprocessor Writing\c" .H*aend \&. .LP Probably the easiest way to get some idea of the relationship of .I troffcvt 's input and output is to run some .I troff files through it and look at what comes out. When .I troffcvt runs, it reads one or more action files to configure itself, then processes input files according to the information in the action files. These are text files containing symbolic actions that specify what happens when requests occur. Action files are also used to define special characters and to set processing parameters. .LP .I troffcvt doesn't have built-in knowledge about any .I troff request. Stated another way, unless .I troffcvt is told how to implement a given .I troff request by means of some action file, it ignores that request. It also knows about very few of the characters that have special meaning (by design, since these vary from one version of .I troff to another). All of this stuff has to be specified in an action file. By default, .I troffcvt reads the action file .I actions when it runs. You can also name additional action files on the command line using the .B \-a option. .LP The format of action files is simple. Blank lines are ignored. Lines beginning with a ``#'' character are also ignored, so you can use them to include comments. Actions are specified on a line consisting of a leading keyword to indicate the action type (\fBimm\fR or \fBreq\fR), followed by an action list of zero or more actions. (An action line may be continued to the next line by putting a backslash at the end of the line.) Action lists can be executed immediately at the time the action file is read, or they can be associated with a request, to be executed whenever the request occurs in the input. .LP Immediate actions consist of the word .B imm followed by an action list that is executed as soon as it has been read. The first .B imm line below sets the point size to 10 points and vertical spacing to 12 points, whereas the second sets the font to roman: .Ps imm point-size 10 spacing 12p imm font R .Pe Request actions are similar but specify a request name, a set of actions for parsing the request's arguments, and a set of actions for processing those arguments after they have been parsed: .Ps req \f(CIrequest-name parsing-actions\fP eol \f(CIpost-parsing-actions\fP ... .Pe .I request-name is the name of the request (without the leading period). The .I parsing-actions section specifies how to parse the arguments expected by the request. If .I parsing-actions is empty, no request arguments are expected (or are to be ignored). The .B eol keyword is mandatory. It signifies the end of the parsing actions and causes .I troffcvt to skip to the end of the request line. (If this were not done, the remaining part of the request line would be read as a separate line to be processed.) The .I post-parsing-actions section specifies what should happen after the request arguments have been parsed. Typically this involves interpreting the request arguments. If the .I post-parsing-actions section is empty, nothing is done with the request (the request is ignored). .LP .I troffcvt associates each action name with the number of arguments that should follow the action when it occurs in action lists. When an action is performed, any arguments specified in the action list are passed to it. For instance, the .Rq so request can be described like this: .Ps req so parse-filename eol push-file $1 .Pe The .B parse-filename action parses the line on which the request occurs to find a filename. This filename becomes the value of argument 1, which can be referred to later as .B $1 . .B push-file pushes the file named by .B $1 on the input stack. Since .B $1 refers to the first argument parsed from the .Rq so request, if the request is ``.so junk'', then ``push-file $1'' becomes ``push-file junk'', and .I junk becomes the current input file. .LP The two .B req lines below show how the .Rq ps and .Rq ce requests can be defined: .Ps req ps parse-absrel-num x point-size eol point-size $1 req ce parse-num x eol center $1 .Pe The actions to take when a .Rq ps request occurs are: parse a number, which can be an absolute setting or relative to the current point size; skip to the end of the request line; set the point size using the previously parsed number. The actions for .Rq ce are to parse a number, skip to the end of the request line, and cause the next ``$1'' input lines to be centered. .LP ``Missing'' arguments are passed as empty strings. A reference to .B $n is passed to the action as the empty string if no .B n -th argument was present on the input request line. Suppose the .Rq ds request is defined like this: .Ps req ds parse-name parse-string-value y eol define-string $1 $2 .Pe Then if the following input line occurs, the .B parse-string-value action will find no string on the line, and the .B define-string action will define .B xx as the empty string: .Ps \&.ds xx .Pe The language implemented by .I troff is expressive (if somewhat unwieldy), so a large number of actions seem to be necessary to allow requests to be specified properly. Descriptions of all actions are given in the .H*ahref "actions.html" .I "troffcvt Action Reference" .H*aend document. .LP If you don't like the .I actions file supplied with the .I troffcvt distribution, you can modify it as necessary for your own purposes. .LP Specifying .I troffcvt 's behavior in terms of symbolic actions rather than hardwiring them into the code allows a good deal of flexibility, because .I troffcvt 's initial state and response to requests can be modified without changing .I troffcvt itself. For example, different versions of .I troff often know about different sets of special characters; building the list at runtime allows different versions to be accommodated. The initial page layout can also be specified this way, since although initial values for processing parameters are the same as those given in the Ossanna manual, you can change them. Thus you can set up layouts for letter size, legal, A4, etc. .LP This method of configuring .I troffcvt also meansx you can experiment quite easily with .I troffcvt 's response to particular requests. .\" .Ah "Names and Objects" .\" .LP Request, macro, string, and register definitions consist of two parts: a name, and the underlying object to which the name points. .I troffcvt allows .I groff -style aliases to be created, such that referring to an alias name is the same as referring to the original name. Aliases are implemented by creating multiple names that all point to the same underlying object. The object structure contains a reference count indicating how many names point to it. .LP For example, when a macro is defined, a name is allocated and pointed at a macro object structure that holds the macro contents (the body of the macro). The reference count in the object structure is set to one. If an alias to the macro is created, a new name is created and made to point to the same object structure as the original name. The reference count in the object structure is set to two. When a request, macro, string, or register is removed, the name is deallocated and the reference count is decremented. If the count goes to zero, the underlying object is no longer needed (no other names point to it), and the object structure is deallocated as well. .LP The reference count also includes the number of times an object is currently in use. When a request or macro is invoked or a string reference occurs, the reference count of the underlying object is incremented. When the request or macro terminates, or the end of the string is reached, the count is decremented. This use of the reference count has two purposes: .Ls B .Li It prevents an object from being deallocated while it's in use, even if all the names that point to it disappear while it's being used. .Li It allows infinite recursion to be detected easily. If the count gets ``too large,'' it's assumed that a recursion loop has occurred. .Le Consider the following example of a macro that removes itself: .Ps \&.de xx \&.rm xx \&.. .Pe When the macro is defined initially, the name .B xx is created and made to point at a macro object, which is given a reference count of one. Invoking the macro results in the following actions: .Ls B .Li When .B xx begins executing, the reference count is incremented to two. .Li When .B xx removes itself, the name .B xx is removed from the name list and the reference count in the macro object is decremented. Since the count goes from two to one (not zero), the macro object is not deallocated, even though no name points to it any more. (This is a good thing, because otherwise we'd be deallocating the current input source!) .Li When .B xx terminates, the reference count of the macro object is decremented again. This time the count goes to zero, and the macro object is deallocated. .Le Now consider the following slightly more complicated macro, which removes itself after creating an alias to itself: .Ps \&.de xx \&.als yy xx \&.rm xx \&.. .Pe The reference count is set to one when the macro is defined, two when the macro begins executing, three when the alias is created, two when .B xx removes itself, and one when .B xx terminates. In this case, however, since the reference count is still one when .B xx terminates (the name .B yy still points to the underlying macro object), the object is not deallocated. .LP Aliases provide a convenient way to implement the .Rq rn request. The new name is created as an alias for the existing name, and thus points to the same underlying object. The old name is then removed, but since the underlying object is now pointed to by another name, it persists as it should. .\" .Ah "Macro Package Handling" .\" .LP .I troff is commonly invoked with some sort of .B \-m \fIxx\fR flag (e.g., .B \-man , .B \-me , .B \-mm , .B \-ms ), so these need to be handled by .I troffcvt as well. There are several ways of handling a macro package, some better than others: .Ls B .Li Ignore it. Since none of the macros referenced in the input file then will have any definitions as far as .I troffcvt is concerned, they'll all be ignored. This isn't really very useful. .Li Read the contents of the macro file first before reading the input file named by the user. This capability is built into .I troffcvt : if an argument .B \-m \fIxx\fR is specified, .I troffcvt looks for an appropriate macro package file (e.g., .I /usr/lib/tmac/tmac.xx ) and reads it. The advantage of this approach is that you don't have to know anything about how the macro package works. There are two disadvantages: .Ls B "" \*- .Li First, it's likely that .I troffcvt will botch some of the macros. Macro packages tend to be very ugly, i.e., clever, complex, powerful, forbidding, and obviously written by people who understand .I troff better than I. Thus, you quickly discover just how unsophisticated .I troffcvt really is. .Li Second, .I troffcvt may write lots of output in response to a macro invocation in the input. A paragraphing macro may set point size, vertical spacing, font, indent, centering, underlining, etc. What you'll see in the .I troffcvt output are the effects of all the requests to which the macro expands. That's okay for preserving the appearance of a document. It won't be helpful if instead you want your postprocessor to recognize when the original macro was used in the .I troff file. .Le 0 .Li Redefine macros in an action file so that they generate an output string that a postprocessor can notice as signifying something special. For instance, the .Rq LP and .Rq IP macros from .B \-ms can be described like this: .Ps req LP eol output-control "\eother para" req IP eol output-control "\eother indented-para" .Pe This will cause .Cl other .B para or .Cl other .B indented-para to be written to the output when instances of .Rq LP or .Rq IP occur in the input. A postprocessor can recognize .Cl other .B para and .Cl other .B indented-para and do something sensible with them. .Li Redefine macros in an action file so that they mimic the effect of the real macros. This allows you to provide a definition of the macro that's simpler than the one found in the macro package, and that will be easier for .I troffcvt to handle. For example, the .Rq AB macro from .B \-ms can be defined, roughly, as: .Ps req AB parse-macro-args eol \e push-string ".br\en.ce\en\e\efIABSTRACT\e\efR\en.sp\en" .Pe You need to understand something about how the macros are supposed to work for this approach to be fruitful. .Le You can also use a combination of the methods above. Probably the easiest way to start is to run a few documents through .I troffcvt and supply only an .B \-m \fIxx\fP argument: .Ps % \f(CBtroffcvt -m\f(CIxx\fP myfile\f(CW .Pe This will tell you which macros .I troffcvt handles okay and which it botches. With that information in hand, you can construct an action file .I tc.mxx containing redefinitions for those macros that .I troffcvt needs help with. Try out the action file like this: .Ps % \f(CBtroffcvt -m\f(CIxx\fP -a tc.m\f(CIxx\fP myfile\f(CW .Pe By experimenting with .I tc.mxx , you can improve .I troffcvt 's handling of any document that uses the .B \-m \fIxx\fP macro package. .LP Some of the examples shown above demonstrate how to redefine macros, but do so by defining them using .B req lines. Thus, these ``macros'' are actually treated by .I troffcvt as requests. Before you redefine a macro as a request, be sure you understand the following points: .Ls B .Li .I troff treats requests and macros similarly, but not exactly the same. For example, you must specify the name of a macro and not a request as the argument to the input-trap macro and end macro requests .Rq it "" ( and .Rq em ). .I troffcvt enforces this constraint, too. .Li If you define a name as a request, you can't apply .Rq am to it later. (Actually, you can, but the effect is to delete the request definition and begin a new macro definition \*- probably not what you want.) .Le If a name that you're defining in an action file .I must refer to a macro and not to a request (e.g., if you want to use it with .Rq it or .Rq em , or if you want to be able to append to it later using .Rq am ), then don't define it using a .B req line. If you do, it'll be considered a request by .I troffcvt . Instead, use an .B imm line containing a .B push-string action to execute a string that contains the contents of a .Rq de request. For example: .Ps imm push-string ".de xx\en.tm this is macro xx\en..\en" .Pe If you provide redefinitions that might get used in concert with macro packages written for .I groff , here's something to watch out for: before redefining a name for which a definition may have already been read from the macro package file, it's prudent to remove the name first, like this: .Ps imm remove-name XX req XX \f(CIdefinition...\fP .Pe This is due to the way that .I groff implements macro packages. Consider the .B \-ms macros. These are supposed to be used such that .Rq TL , .Rq AU , .Rq AI , and .Rq AB occur in order if they are used. To make sure they aren't invoked out of order, the .I groff .B \-ms definitions initially create .Rq AU , .Rq AI , and .Rq AB as aliases to a macro that checks whether or not .Rq TL has been invoked. When .Rq TL is invoked it redefines the other macros appropriately with their ``real'' definitions. Now, suppose that you handle .B \-ms by reading the macro package file and then redefining in an action file some of the macros such as .Rq AI , and .Rq AB . If you simply provide a new definition of .Rq AI , what happens is that you also redefine all other names that are aliased along with .Rq AI . In other words, you also redefine .Rq AU and .Rq AB ! If you then redefine .Rq AB , you also redefine .Rq AU and .Rq AI . Removing a name before giving it a new definition avoids this problem. .\" .Bh "Conditions That Prevent Macro Redefinition" .\" .LP Suppose you normally format a document .I mydoc using a command something like this: .Ps % \f(CBtroff -ms mydoc\fP .Pe If you use .Rq so .B mymacros in .I mydoc to read a file of macro definitions, you may have a problem if you want to process .I mydoc with .I troffcvt . In particular, if you want to redefine any of the macros in .I mymacros for .I troffcvt 's benefit, you won't be able to use an action file to do so: .Ls B .Li Any action file that affects processing of .I mydoc has to be read prior to .I mydoc (and thus prior to .I mymacros , since that file is referenced from .I mydoc ). .Li The later definition always takes precedence, so the definitions in .I mymacros override any attempted redefinition in the action file. .Le If you really need to redefine the macros in .I mymacros when you format .I mydoc with .I troffcvt , you can use the following strategy: .Ls B .Li Remove the .Rq so .B mymacros request from .I mydoc and format the document this way: .Ps % \f(CBtroff -ms mymacros mydoc\fP .Pe 0 .Li Create an action file .I tc.mymacros and put into it any redefinitions for macros in .I mymacros that need to be redefined. Then to generate .I troffcvt output, use this command: .Ps % \f(CBtroffcvt -ms mymacros -a tc.mymacros mydoc\fP .Pe This will cause .I troffcvt to read, in order, the .B \-ms macros, the standard definitions of the macros in .I mymacros , the redefinitions in the action file .I tc.mymacros , and .I mydoc . .Le If you use .I groff , an alternative strategy can be used. Leave the .Rq so .I mymacros request in .I mydoc , but surround each definition in .I mymacros with an .Rq if .B d test: .Ps \&.if d xx .ig end_ignore \fI\&...macro definition here...\fP \&.end_ignore .Pe Then you can format the document with .I troffcvt like this: .Ps % \f(CBtroffcvt -ms -a tc.mymacros mydoc\fP .Pe When .I tc.mymacros is processed, it defines some or all the the macros used in .I mymacros . When .I mydoc is read and the .Rq so .I mymacros request is processed, only those macros that were not already defined in .I tc.mymacros will be defined. .LP Similar considerations apply if you define macros directly in your .I troff source file. You won't be able to override them in an action file because the definition in the .I troff source file occurs later and will take precedence. To work around this, put the macro definitions in a separate file and use the first strategy described above, or use .Rq if .B d as in the second strategy. .\" .Ah "Input/Output Mechanisms" .\" .H*aname character-coding .H*aend .Bh "Character Coding" .\" .LP .I ChIn() returns values of type .Cw XChar , which is .Cw typedef 'ed as an unsigned integer type. The return value falls into the following ranges: .IP 0 .sp .5v This value signifies end of file on the current input source. .IP "1..127 (0x01..0x7f)" .sp .5v Plain ASCII character. .IP "128..255 (0x80..0xff)" .sp .5v 8-bit (non-ASCII) input character. .IP "257..511 (0x101..0x1ff)" .sp .5v Escape code for ASCII or 8-bit character preceded by an escape character (except .Es ( , see below). The code for \fB\e\fIX\fR is constructed as 0x100\||\|\fIX\fR. Note that 0x100 is not a valid escape code because null bytes are stripped from the input. .IP ">=512 (>=0x200)" .sp .5v Special-character code. Sequences of the form \fB\e(\fIxx\fR or \fB\e[\fIxxx\fP]\fR are recognized and converted to special-character codes. These codes start at 512 so that they are greater than all ASCII, 8-bit, or escape codes. If a special-character reference is encountered for a name that has no definition (i.e., the character was not defined in any action file), a new special character with an empty value is created on the fly. This is done on the following grounds: .RS .Ls B .Li It's undesirable to simply panic. .Li It's undesirable to delete the sequence from the input, since that would break ugly (but perfectly legal) constructions like this: .Ps \&.if \e(xx\f(CIstring\fP\e(xx\f(CIstring\fP\e(xx\ \f(CIstuff\fP ... .Pe A warning is written to .I stderr when characters are created this way so it can be known there is a special-character definition missing from the action file (or that the input file contains an erroneous special-character reference). .Li If the character is put back onto the input with .I UnChIn() , the code can be converted back into the original name, even though the character has no definition. .sp .5v A minor problem occurs when the .Rq if .B c construction is used to test whether or not a character is defined, because .B any special character reference results in a valid .Cw SpChar structure being associated with it, even if the character didn't exist before being referenced. Therefore the test is made based on whether or not the character's value (definition) is empty. .Le .RE .LP .I UnChIn() takes an .Cw XChar argument, which is usually a value returned from .I ChIn() . .I UnChIn() pushes the argument onto the input pushback stack, unpacking escape and special-character codes into their original multiple-character input sequences. Unpacking is done to prevent problems. Suppose an escaped or special character is first seen in non-copy mode, then pushed back and reread in copy mode. If the escape code or special-character code itself were pushed back, the character wouldn't be reread in copy mode properly. .LP Values for plain ASCII and 8-bit characters can be represented in a single byte (as an unsigned character), but escape codes and special-character codes cannot, since they begin at 512. This is why the .Cw XChar type is wider than a single byte. .LP Special characters are disallowed in request arguments and escape sequences that might be written back out directly. For instance, .Rq ft .I F is written out as .Cl font .I F , so .I F isn't allowed to contain special characters. A similar restriction applies to diversion names. .LP Special-character names must consist entirely of printable ASCII characters. They are not allowed to be composed of other special characters, e.g., .B \e(\e(ts\e(ts is disallowed. .\" .Bh "Input Processing" .\" .LP Input may come from a file, a macro, a named string (created with the .B define-string action, usually in response to a .B \.ds request), or an anonymous string (defined below under the description of the .I AChIn() function). The bulk of input usually comes from input files named on the command line, which are processed in sequence. Inputs sources may be nested (e.g., a macro or string may be referenced while reading a file). The current input is suspended when another input source is interpolated into the input stream, and is resumed when the interpolated source is exhausted. .LP .I ChIn() returns the next input character from the input stream. Embedded newlines (introduced with a backslash character .B \e at the end of a line) are deleted so that the following input line appears contiguous with the current line to any higher-level routines. Comments (introduced with .B \e ) are deleted up to (but not including) the end of line character. For instance, this makes: .Ps text followed by comment\e" this is the comment .Pe appear to be: .Ps text followed by comment .Pe The handling of lines that begin with \fB\.\e"\fR happens properly; the comment stripping makes the line look like a line beginning with a control character but no request, so it is ignored. .I ChIn() also manages encoding of escaped characters, and pushing to input sources for number register, string or macro argument references. Handling of escape sequences differs depending on whether copy mode is in effect or not. .LP Input characters accepted by the file-input routine are non-null ASCII values (null bytes and bytes with bit 8 on are discarded). Escaped characters (\fB\e\fIx\fR) and special-character references \fB\e(\fIxx\fR or \fB\e[\fIxxx\fB]\fR) are converted to escape codes and special-character codes as described above under .H*ahref #character-coding ``Character Coding.'' .H*aend .LP Input source pushing occurs automatically in .I ChIn() when .Es n , .Es * or .Es $ occur (and also .Es w if not in copy mode): the input source switches to a string representing the value of the number register or string, the macro argument, or the result of the width calculation. Higher level routines also can cause the current input source to be pushed down, e.g., when a .Rq so request occurs. .LP .I ChIn() is also used for the ugly task of processing multi-line conditional input (bracketed with the .Es { and .Es } sequences). The conditional request processor saves the current if-level when it sees a .Es { , bumps it up one, then processes lines until the level drops back down to the saved value. .I ChIn() notices .Es } , silently deletes it and decrements the if-level, which is then noticed by the conditional processor. Pretty horrid. .LP .I UnChIn() is used to push characters back onto the input stream. It understands how to push back escape codes and special-character codes properly. It also understands how to push back multiple characters (characters must be pushed in the reverse order from that in which they were read). .LP .I ChIn0() returns the next raw (uninterpreted) character from the input stream. If there are any pushed back characters waiting to be reread, it returns the one most recently pushed. Otherwise, it returns the next input character from the current input source. If that source is exhausted, it resumes reading from the previous source. When there is no more input, it returns .Cw endOfInput . Input source unwinding is undetectable at any level above .I ChIn0() , including .I ChIn() . .LP .I FChIn() , .I MChIn() , and .I AChIn() are the lowest level input routines; they're called by .I ChIn0() . These return a single character from a file, macro or named string, or ``anonymous'' string input source. Each returns .Cw endOfInput when the source is exhausted (which only means the current source is done, not necessarily that all sources are done). .Cw EOF is not returned because that is typically \-1 (negative), and the input routines return a value of type .Cw XChar , which is unsigned. .LP .I FChIn() discards nulls. (It also converts CR or CRLF to LF; this has nothing to do with .I troff , but allows text files from MS-DOS or Macintosh machines to be read without requiring you to convert line endings first.) .LP .I MChIn() reads the next character from a macro or string definition. (Strings are implemented internally as macros without arguments.) .LP .I AChIn() reads the next character from an anonymous string, which is just some arbitrary string that is to be used as an input source. For instance, when a number register reference .Es n ) ( or width expression .Es w ) ( occur, the resulting value is converted to a character string, which becomes the current input until the string is completely read. References to macro arguments are treated similarly; the argument value is retrieved and pushed on the input stack. Another source of anonymous strings is the .B push-string action, which can be used in action files to push an arbitrary string onto the input stream. This is convenient for processing certain requests. For instance, if you want to redefine a macro, you can define the action for that macro to be one that pushes alternative input. Here's an example that shows how the .B \&.AB macro from the .B \-ms macro package might be redefined: .Ps req AB parse-macro-args eol \e push-string ".br\en.ce\en\e\efIABSTRACT\e\efR\en.sp\en" .Pe One sticky problem occurs with the .B \.nx request, usually processed with the .B switch-file action. When .B \.nx occurs, it might happen while other files or macros are active. If the current input source is a file there is no problem since the file pointer for that source is simply switched to the new file. But if the request occurs in the middle of a macro, it's less clear what should happen. Should the macro continue to be processed? I elect to terminate macro sources and unwind the source stack until a file is found, then switch the file pointer of the file source. Possibly this is wrong; the .I troff manual is ambiguous on this point. (Which may be why different versions of .I troff behave differently in this situation.) .LP For handling the .B \.ex request, the .B end-input action it used; it sets a flag causing .I ChIn () to return .Cw endOfInput forever after. .\" .Bh "Output Processing" .\" .LP At the lowest output level, there are two calls. One is for writing characters and it simply writes to the output file and dies if there was an error. The other is for writing strings; it calls the write-character routine for each character in the string. .LP The next level up manages the mechanics of collecting plain text lines and interspersing them with special text and control lines. The basic issues are insertion of spaces between successive output text lines and making sure that special text and control lines don't get written into the middle of a plain text line. .LP Control lines begin with a backslash character .Cw \e . Any plain text output line being collected is flushed so the control string doesn't appear on the same line. .LP There are two kinds of text output: plain text lines, and special text lines that indicate special characters (e.g., .St backslash for the .Cw \e character. Whenever text output (either kind) is written, a check is made to see whether it's necessary to write a preceding space first. A space is usually needed between consecutive input text lines (exceptions are when centering or no-fill are in effect, or if an input line ends with a .Es c ). For special text, any plain text output line being collected is flushed so the control string doesn't appear on the same line. .LP The output character set for text is such that most printable ASCII characters appear as themselves, and others are written out as special text lines. The characters tab, backspace, .B \e , and .B @ are printable but written as specials .St tab , .St backspace , .St backslash , and .St at . The leader character SOH is written as .St leader . .\" .Ah "Input Levels" .\" .LP .I troffcvt maintains a notion of input level. The level is incremented each time a new input source begins and decremented when the current source ends. A file interpolated with .Rq so is an input source, but so is a macro, a macro argument, a string, or a number register. This helps avoid the problem of interpreting something like this: .Ps \&.if '\e*[xx]'y' ... .Pe when the string .B xx contains an apostrophe. .I troffcvt uses the input level in such a way that .I troff constructs bounded by delimiters do not consider the closing delimiter to be found unless it occurs at the same input level as the opening delimiter. (If you simply look at characters as they occur, then the apostrophe in the string prematurely terminates the scan for the first of the strings to be compared, and throws off the comparison.) The affected constructs include: .Ps \&.if '\f(CIx\fP'\f(CIy\fP' \&.tl '\f(CIleft\fP'\f(CIcenter\fP'\f(CIright\fP' \eb'\f(CIabc...\fP' \eh'\f(CIN\fP' \el'\f(CINc\fP' \eL'\f(CINc\fP' \eo'\f(CIabc...\fP' \ev'\f(CIN\fP' \ew'\f(CIstring\fP' .Pe The input level also affects parsing of macro arguments that begin with a double quote. Only a quote at the same input level as the opening quote terminates the argument. .LP The behavior just described mimics how .I groff treats its input, not how standard .I troff treats its input. However, .I groff ignores the input level (and thus acts like standard .I troff ), in compatibility mode. .I troffcvt does the same. (Parsing routines that need to check the input level call the .I ILevel() function. In compatibility mode this function always returns zero, making all input appear to be at the same level.) .LP .I groff produces a quoted argument list when .Es $@ occurs in the input. The .I groff documentation says that it processes the list such that the quotes surrounding an argument appear at the same input level, whereas the argument itself is processed at a higher level. (This prevents the problems that would occur if an argument contained a quote.) I take this to mean that the quotes surrounding the arguments are at a level higher than the context in which the .Es $@ occurs, and the arguments one level higher than that, in case something like the following occurs in a macro: .Ps \&.xx "\e\e$@" .Pe If the quotes produced by .Es $@ here were treated as being at the same level as quotes in the surrounding text, the arguments to .Rq xx could be messed up. .LP .I troffcvt handles .Es $@ by constructing a string consisting of a list of argument references that looks like this: .Ps "\e\e$1" "\e\e$2" ... "\e\e$\f(CIn\fP" .Pe Then the string is pushed on the input stack. This causes the quotes to be processed a level higher than the surrounding text. When each argument reference in the string is encountered, the value of the argument is pushed on the stack, causing the reference to be processed another level higher. .LP .I troffcvt handles .Es $* in a manner similar to .Es $@ except that no quotes are added to the string containing the list of argument references. .\" .Ah "Macro Argument Quoting" .\" .LP Macro arguments consist of strings of non-white characters. Arguments may be quoted to allow whitespace to be included. An argument that begins with a double quote is parsed in quote mode until a closing quote, and the leading and terminating quotes are stripped off. .LP Double quotes in macro arguments are handled as follows: .Ls B .Li If not in quote mode, just treat the quote as part of the argument. .Li If in quote mode and the quote is doubled, one quote character is stripped off and the other becomes part of the argument. If the next character is not a quote, the quote is the closing quote of a quoted argument. .Le The quote stripping described above presents an interesting problem in standard .I troff . If an argument contains quotes, and then is used inside the macro by being passed to another macro, quote stripping occurs again. This is really ugly, because it means you must understand the implementation of the macros you're using and know how many extra quotes to put in your arguments so that they end up with the correct number when they finally reach the bottom-level macro. .LP Neither .I groff nor .I troffcvt have this problem, since quotes in arguments occur at a higher level than the surrounding text. (In compatibility mode, .I troffcvt uses the quote-stripping behavior of standard .I troff .) current input source to be pushed down, e.g., when a .Rq so request occurs. .LP .I ChIn() is also used for the ugly task of processing multi-line conditional input (bracketed with the .Es { and .Es } sequences). The conditional request processor saves the current if-level when it sees a .Es { , bumps it up one, then processes lines until the level drops back down to the saved value. .I ChIn() notices .Es } , silently deletes it and decrementroffcvt-1.04/doc/Imakefile010064400017710000151000000060210634147004400173740ustar00junkyarddatamgmt00000400000027XCOMM troffcvt documentation Makefile all:: documents-ps:: troffcvt.ps actions.ps output.ps \ bugs.ps tc2rtf.ps tc2html.ps tblcvt.ps groff.ps frontend.ps documents-html:: troffcvt.html actions.html output.html \ bugs.html tc2rtf.html tc2html.html tblcvt.html groff.html frontend.html documents-text:: documents-txt documents-txt:: troffcvt.txt actions.txt output.txt \ bugs.txt tc2rtf.txt tc2html.txt tblcvt.txt groff.txt frontend.txt documents-rtf:: troffcvt.rtf actions.rtf output.rtf \ bugs.rtf tc2rtf.rtf tc2html.rtf tblcvt.rtf groff.rtf frontend.rtf TroffMsToPostScript(troffcvt.ps,tmac.wrprc troffcvt.ms,NullArg,NullArg) TroffMsToHTML(troffcvt.html,troffcvt.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(troffcvt.txt,troffcvt.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(troffcvt.rtf,troffcvt.ms,tmac.wrprc,NullArg,NullArg) TroffMsToPostScript(actions.ps,tmac.wrprc actions.ms,NullArg,NullArg) TroffMsToHTML(actions.html,actions.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(actions.txt,actions.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(actions.rtf,actions.ms,tmac.wrprc,NullArg,NullArg) TroffMsToPostScript(output.ps,tmac.wrprc output.ms,|$(TBL),NullArg) TroffMsToHTML(output.html,output.ms,tmac.wrprc -a tc.wrprc-html,|$(TBLCVT),NullArg) TroffMsToText(output.txt,output.ms,tmac.wrprc,|$(TBLCVT),NullArg) TroffMsToRTF(output.rtf,tmac.wrprc output.ms,NullArg,|$(TBLCVT),NullArg) TroffMsToPostScript(bugs.ps,tmac.wrprc bugs.ms,NullArg,NullArg) TroffMsToHTML(bugs.html,bugs.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(bugs.txt,bugs.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(bugs.rtf,bugs.ms,tmac.wrprc,NullArg,NullArg) TroffMsToPostScript(tc2rtf.ps,tmac.wrprc tc2rtf.ms,NullArg,NullArg) TroffMsToHTML(tc2rtf.html,tc2rtf.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(tc2rtf.txt,tc2rtf.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(tc2rtf.rtf,tc2rtf.ms,tmac.wrprc,NullArg,NullArg) TroffMsToPostScript(tc2html.ps,tmac.wrprc tc2html.ms,NullArg,NullArg) TroffMsToHTML(tc2html.html,tc2html.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(tc2html.txt,tc2html.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(tc2html.rtf,tc2html.ms,tmac.wrprc,NullArg,NullArg) TroffMsToPostScript(tblcvt.ps,tmac.wrprc tblcvt.ms,|$(TBL),NullArg) TroffMsToHTML(tblcvt.html,tblcvt.ms,tmac.wrprc -a tc.wrprc-html,|$(TBLCVT),NullArg) TroffMsToText(tblcvt.txt,tblcvt.ms,tmac.wrprc,|$(TBLCVT),NullArg) TroffMsToRTF(tblcvt.rtf,tblcvt.ms,tmac.wrprc,|$(TBLCVT),NullArg) TroffMsToPostScript(groff.ps,tmac.wrprc groff.ms,NullArg,NullArg) TroffMsToHTML(groff.html,groff.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(groff.txt,groff.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(groff.rtf,groff.ms,tmac.wrprc,NullArg,NullArg) TroffMsToPostScript(frontend.ps,tmac.wrprc frontend.ms,NullArg,NullArg) TroffMsToHTML(frontend.html,frontend.ms,tmac.wrprc -a tc.wrprc-html,NullArg,NullArg) TroffMsToText(frontend.txt,frontend.ms,tmac.wrprc,NullArg,NullArg) TroffMsToRTF(frontend.rtf,frontend.ms,tmac.wrprc,NullArg,NullArg) troffcvt-1.04/doc/Makefile010066400017710000151000000437140634147004600172410ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./doc # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # troffcvt documentation Makefile all:: documents-ps:: troffcvt.ps actions.ps output.ps \ bugs.ps tc2rtf.ps tc2html.ps tblcvt.ps groff.ps frontend.ps documents-html:: troffcvt.html actions.html output.html \ bugs.html tc2rtf.html tc2html.html tblcvt.html groff.html frontend.html documents-text:: documents-txt documents-txt:: troffcvt.txt actions.txt output.txt \ bugs.txt tc2rtf.txt tc2html.txt tblcvt.txt groff.txt frontend.txt documents-rtf:: troffcvt.rtf actions.rtf output.rtf \ bugs.rtf tc2rtf.rtf tc2html.rtf tblcvt.rtf groff.rtf frontend.rtf troffcvt.ps:: tmac.wrprc troffcvt.ms $(SOELIM) tmac.wrprc troffcvt.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > troffcvt.ps clean:: $(RM) troffcvt.ps help_aux:: @echo "'make "troffcvt.ps"' to "format troffcvt.ps in PostScript troffcvt.html:: $(SOELIM) troffcvt.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >troffcvt.html clean:: $(RM) troffcvt.html help_aux:: @echo "'make "troffcvt.html"' to "format troffcvt.html in HTML troffcvt.txt:: $(SOELIM) troffcvt.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > troffcvt.txt clean:: $(RM) troffcvt.txt help_aux:: @echo "'make "troffcvt.txt"' to "format troffcvt.txt in plain text troffcvt.rtf:: troffcvt.ms $(SOELIM) troffcvt.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> troffcvt.rtf clean:: $(RM) troffcvt.rtf actions.ps:: tmac.wrprc actions.ms $(SOELIM) tmac.wrprc actions.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > actions.ps clean:: $(RM) actions.ps help_aux:: @echo "'make "actions.ps"' to "format actions.ps in PostScript actions.html:: $(SOELIM) actions.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >actions.html clean:: $(RM) actions.html help_aux:: @echo "'make "actions.html"' to "format actions.html in HTML actions.txt:: $(SOELIM) actions.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > actions.txt clean:: $(RM) actions.txt help_aux:: @echo "'make "actions.txt"' to "format actions.txt in plain text actions.rtf:: actions.ms $(SOELIM) actions.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> actions.rtf clean:: $(RM) actions.rtf output.ps:: tmac.wrprc output.ms $(SOELIM) tmac.wrprc output.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > output.ps clean:: $(RM) output.ps help_aux:: @echo "'make "output.ps"' to "format output.ps in PostScript output.html:: $(SOELIM) output.ms |$(TBLCVT) | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >output.html clean:: $(RM) output.html help_aux:: @echo "'make "output.html"' to "format output.html in HTML output.txt:: $(SOELIM) output.ms |$(TBLCVT) | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > output.txt clean:: $(RM) output.txt help_aux:: @echo "'make "output.txt"' to "format output.txt in plain text output.rtf:: tmac.wrprc output.ms $(SOELIM) tmac.wrprc output.ms |$(TBLCVT) | $(TROFF2RTF) $(TCMSMACROS) $(TROFFOPTS)> output.rtf clean:: $(RM) output.rtf bugs.ps:: tmac.wrprc bugs.ms $(SOELIM) tmac.wrprc bugs.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > bugs.ps clean:: $(RM) bugs.ps help_aux:: @echo "'make "bugs.ps"' to "format bugs.ps in PostScript bugs.html:: $(SOELIM) bugs.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >bugs.html clean:: $(RM) bugs.html help_aux:: @echo "'make "bugs.html"' to "format bugs.html in HTML bugs.txt:: $(SOELIM) bugs.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > bugs.txt clean:: $(RM) bugs.txt help_aux:: @echo "'make "bugs.txt"' to "format bugs.txt in plain text bugs.rtf:: bugs.ms $(SOELIM) bugs.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> bugs.rtf clean:: $(RM) bugs.rtf tc2rtf.ps:: tmac.wrprc tc2rtf.ms $(SOELIM) tmac.wrprc tc2rtf.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > tc2rtf.ps clean:: $(RM) tc2rtf.ps help_aux:: @echo "'make "tc2rtf.ps"' to "format tc2rtf.ps in PostScript tc2rtf.html:: $(SOELIM) tc2rtf.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >tc2rtf.html clean:: $(RM) tc2rtf.html help_aux:: @echo "'make "tc2rtf.html"' to "format tc2rtf.html in HTML tc2rtf.txt:: $(SOELIM) tc2rtf.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > tc2rtf.txt clean:: $(RM) tc2rtf.txt help_aux:: @echo "'make "tc2rtf.txt"' to "format tc2rtf.txt in plain text tc2rtf.rtf:: tc2rtf.ms $(SOELIM) tc2rtf.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> tc2rtf.rtf clean:: $(RM) tc2rtf.rtf tc2html.ps:: tmac.wrprc tc2html.ms $(SOELIM) tmac.wrprc tc2html.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > tc2html.ps clean:: $(RM) tc2html.ps help_aux:: @echo "'make "tc2html.ps"' to "format tc2html.ps in PostScript tc2html.html:: $(SOELIM) tc2html.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >tc2html.html clean:: $(RM) tc2html.html help_aux:: @echo "'make "tc2html.html"' to "format tc2html.html in HTML tc2html.txt:: $(SOELIM) tc2html.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > tc2html.txt clean:: $(RM) tc2html.txt help_aux:: @echo "'make "tc2html.txt"' to "format tc2html.txt in plain text tc2html.rtf:: tc2html.ms $(SOELIM) tc2html.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> tc2html.rtf clean:: $(RM) tc2html.rtf tblcvt.ps:: tmac.wrprc tblcvt.ms $(SOELIM) tmac.wrprc tblcvt.ms |$(TBL) | $(TROFF) $(MSMACROS) $(TROFFOPTS) > tblcvt.ps clean:: $(RM) tblcvt.ps help_aux:: @echo "'make "tblcvt.ps"' to "format tblcvt.ps in PostScript tblcvt.html:: $(SOELIM) tblcvt.ms |$(TBLCVT) | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >tblcvt.html clean:: $(RM) tblcvt.html help_aux:: @echo "'make "tblcvt.html"' to "format tblcvt.html in HTML tblcvt.txt:: $(SOELIM) tblcvt.ms |$(TBLCVT) | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > tblcvt.txt clean:: $(RM) tblcvt.txt help_aux:: @echo "'make "tblcvt.txt"' to "format tblcvt.txt in plain text tblcvt.rtf:: tblcvt.ms $(SOELIM) tblcvt.ms |$(TBLCVT) | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> tblcvt.rtf clean:: $(RM) tblcvt.rtf groff.ps:: tmac.wrprc groff.ms $(SOELIM) tmac.wrprc groff.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > groff.ps clean:: $(RM) groff.ps help_aux:: @echo "'make "groff.ps"' to "format groff.ps in PostScript groff.html:: $(SOELIM) groff.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >groff.html clean:: $(RM) groff.html help_aux:: @echo "'make "groff.html"' to "format groff.html in HTML groff.txt:: $(SOELIM) groff.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > groff.txt clean:: $(RM) groff.txt help_aux:: @echo "'make "groff.txt"' to "format groff.txt in plain text groff.rtf:: groff.ms $(SOELIM) groff.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> groff.rtf clean:: $(RM) groff.rtf frontend.ps:: tmac.wrprc frontend.ms $(SOELIM) tmac.wrprc frontend.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > frontend.ps clean:: $(RM) frontend.ps help_aux:: @echo "'make "frontend.ps"' to "format frontend.ps in PostScript frontend.html:: $(SOELIM) frontend.ms | $(TROFF2HTML) -ms tmac.wrprc -a tc.wrprc-html $(TROFFOPTS) - >frontend.html clean:: $(RM) frontend.html help_aux:: @echo "'make "frontend.html"' to "format frontend.html in HTML frontend.txt:: $(SOELIM) frontend.ms | $(UNROFF) -ms tmac.wrprc $(TROFFOPTS) - > frontend.txt clean:: $(RM) frontend.txt help_aux:: @echo "'make "frontend.txt"' to "format frontend.txt in plain text frontend.rtf:: frontend.ms $(SOELIM) frontend.ms | $(TROFF2RTF) $(TCMSMACROS) tmac.wrprc $(TROFFOPTS)> frontend.rtf clean:: $(RM) frontend.rtf # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend TBLCVT = tblcvt TROFF2HTML = troff2html troffcvt-1.04/doc/tmac.wrprc010064400017710000151000000123140632104375500175730ustar00junkyarddatamgmt00000400000027.\" .\" Font Notes: .\" CW, CB, CI are used for non-proportional, non-proportional bold, and .\" non-proportional italic (courier, courier-bold, courier-italic). If .\" the font names are different at your site, change definitions of .\" of .Cw, .Cb, and .Ci below. There may be other inline references to .\" CW, CB, and CI that need to be changed as well. .\" .\" The inline font reference is given using \f[xx], which requires a .\" version of troff that understands the [xx] notation, e.g., groff. .\" .\" .\" Ft - font reference .\" $1 = font to use for .ft switches .\" $2 = font to use for inline \f switches .\" $3 = thing to put in the given font .\" $4 = goes immediately after $3 .\" $5 = goes immediately before $4 .\" if $3-$5 are empty, simply switch font w/o switching back .de Ft .nr PQ \\n(.f .ie \(ts\\$3\\$4\\$5\(ts\(ts .ft \\$1 .el \&\\$5\\f[\\$2]\\$3\\f\\n(PQ\&\\$4 .. .\" .\" Cw - constant width font .de Cw .Ft CW CW "\\$1" "\\$2" "\\$3" .. .\" .\" Cb - bold constant width font .de Cb .Ft CB CB "\\$1" "\\$2" "\\$3" .. .\" .\" Ci - italic constant width font .de Ci .Ft CI CI "\\$1" "\\$2" "\\$3" .. .\" .\" I - italic font .de I .Ft I I "\\$1" "\\$2" "\\$3" .. .\" .\" B - bold font .de B .Ft B B "\\$1" "\\$2" "\\$3" .. .\" .\" Bi - bold italic font .de Bi .Ft BI BI "\\$1" "\\$2" "\\$3" .. .\" .\" Most of following are modified from ORA macros .\" .de Ps \" Printout start; $1 = indent (default is 5 spaces) .br .nr pS \\n(.s \" Save current point size .nr vS \\n(.v \" Save current vertical spacing .nr pF \\n(.f \" Save current font .nr pI \\n(.iu \" Save current indent .sp \\n(PDu .ns .\".ps 9 .\".vs 11 .ps 8 .vs 10 .ft CW .ie !"\\$1"" .in \\n(.iu+\\$1n .el .in \\n(.iu+5n \" default indent = +5n .nf .\" 4n doesn't work. How come? .\".ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n .nr Cw 4*\\w`n` .ta \\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu .rr Cw .. .de Pe \" Printout end; if $1 non-null, no concluding blank line .br .if "\\$1"" .sp \\n(PDu .ps \\n(pS .vs \\n(vSu .ft \\n(pF .in \\n(pIu .rr pS .rr vS .rr pF .rr pI .fi .. .\" .\" Vertical ellipsis with squished vertical spacing. Optional argument .\" sets indent (restored afterward). .\" .de Ve .if !`\\$1`` .in \\$1 .vs 4 \&. \&. \&. .vs .if !`\\$1`` .in .. .\" .nr l0 0 1 \" initialize list nesting level counter .\" .\" list start; $1 = A(LPHA), a(alpha), B(ullet), N(umeric), .\" R(oman), r(oman); $2 = indent; $3 = bullet char .de Ls .br .if !"\\$1"A" .if !"\\$1"B" .if !"\\$1"N" .if !"\\$1"R" \ . if !"\\$1"r" .if !"\\$1"a" .if !"\\$1"" \ .ab Ls: Need A B N R a r or null as list type--abort .nr l\\n+(l0 0 1 \" increment list level, create new l register for level n .nr In\\n(l0 \\n(.iu \" save initial indent .\".tm Ls indent In\\n(l0 is \\n[In\\n(l0] .ie "\\$1"" \{\ . if "\\n(l0"1" .af l\\n(l0 1 \" default to numeric at 1st level . if "\\n(l0"2" .af l\\n(l0 a \" default to lc alphabetic at 2nd level . if "\\n(l0"3" .af l\\n(l0 i \" default to lc roman at 3rd level . if "\\n(l0"4" .ds l\\n(l0 \(bu \" default to bullet at 4th level . if "\\n(l0"5" .ds l\\n(l0 \f3\-\f1 \" default to dash at 5th level . if \\n(l0-5 .ds l\\n(l0\(bu \" default to bullet above 5rd level . if \\n(l0-3 .nr l\\n(l0 0-1 . \} .el \{\ . if "\\$1"A" .af l\\n(l0 A . if "\\$1"a" .af l\\n(l0 a . if "\\$1"B"\{\ . if "\\$3"" .ds l\\n(l0 \(bu \" no 3rd arg = default bullet . if !"\\$3"" .ds l\\n(l0 \\$3 \" 3rd arg = bullet . nr l\\n(l0 0-1 . \} . if "\\$1"R" .af l\\n(l0 I . if "\\$1"r" .af l\\n(l0 i \} .ie !"\\$2"" .nr i\\n(l0 \\$2 \" 2nd arg = list indent, if given .el .nr i\\n(l0 \\n(.iu+3n \" default indent (used to be 5) .\".el .nr i\\n(l0 3 \" default indent (used to be 5) .\".nr I0 0 .if \\n(l0>1 .RS \" shift right if this is a nested list .. .de Li \" list item; $1 = 0 means no blank line before item .br .if "\\$1"0" .ns .ie "\\n(l\\n(l0"-1" .IP "\\*(l\\n(l0" "\\n(i\\n(l0u" .el \{\ . nr l\\n(l0 +1 . IP "\\n(l\\n(l0." "\\n(i\\n(l0u" .\} .. .de Le \" list end; $1 = 0 means no extra blank line following last item .br .rr l\\n(l0 .rr i\\n(l0 .rm l\\n(l0 .\".tm Le \\n(l0 indent1=\\n(.i .if \\n(l0>1 .RE \" shift left if this is a nested list .\".tm Le \\n(l0 indent2=\\n(.i .in \\n[In\\n(l0]u .rr In\\n(l0 .\".tm Le \\n(l0 indent3=\\n(.i .nr l0 -1 \" decrement list level .ie !\\n(l0 \{\ .\" if the current indent is now > 0 assume the list was inside an IP .\" and don't reset indent all the way back out . ie \\n(.i>0 \{\ . if !"\\$1"0" .sp \\n(PDu . \} . el \{\ . ie "\\$1"0" .LP 0 . el .LP . \} .\} .el .if !"\\$1"0" .sp \\n(PDu .\".if \\n(IP=0 'in 0 .. .\" .\" Ah, Bh, Ch - headings for various levels. $1 = heading .\" .de Ah .sp .RT .ne 5 .ps 14 .vs 16 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .de Bh .sp .RT .ne 5 .ps 11 .vs 13 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .de Ch .sp .RT .ne 5 .ps 10 .vs 12 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .\" .\" Reset margins and paragraph distance. .nr PO 1.2in \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance troffcvt-1.04/doc/tc2html.ms010064400017710000151000000535310631066466600175240ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 9 March 1997 .\" .EH 'tc2html Notes'- % -'' .OH ''- % -'tc2html Notes' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt or RTF control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .TL .ps +2 tc2html Notes .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .H*toc*title "Table of Contents" .\" .Ah Introduction .\" .LP .I tc2html is a postprocessor for converting .I troffcvt output to HTML. It's used by the .I troff2html front end. This document describes how .I tc2html works and some of the design issues involved in writing it. .LP In general, the goal of .I tc2html is that you should get reasonable HTML output with no need for special treatment of the .I troff input file. The most important thing is that you use a standard macro package. However, there are some additional principles you can follow that will improve the quality of the HTML that .I tc2html generates. For example, it's possible to embed hypertext links in your .I troff source with a little prior planning. Techniques for such things are discussed in the section .H*ahref #better-html ``Generating Better HTML.'' .H*aend If you're not interested in implementation details, you can skip directly to that section. .\" .Ah "Output Format" .\" .LP .I tc2html reads output from .I troffcvt and produces an HTML document that has the following general form: .Ps \fItitle text\fP

\fItitle text\fP

\fIbody text\fP .Pe The document HEAD part may be missing if .I tc2html detects no title in the input. In this case the initial heading at the beginning of the document BODY part also will be missing. The entire document BODY may be missing or empty if the input document is empty. .\" .Ah "Determining Input Document Structure" .\" .LP HTML documents typically are highly structured, being written in terms of elements such as headers, paragraphs, lists, and displays (preformatted text). But .I troffcvt output normally contains very little structural information beyond markers like those for inter-paragraph spacing and line breaks (in the form of .Cl space and .Cl break control lnes). The result when .I tc2html reads such .I troffcvt output is that it produces HTML that is relatively unstructured \*- just a lot of text broken by occasional

or
markers. .LP However, if your document is marked up using macros from a macro package such as .B \-ms or .B \-man , it's possible to get output from .I troffcvt that's much more suitable for .I tc2html . The trick is to map .I troff requests to HTML structure markers, rather than trying to guess the structure from the low-level .I troffcvt output that normally results from those requests. This is accomplished using the following strategy: .Ls B .Li Extend the .I troffcvt output language by defining an .Cl html control that provides information to .I tc2html about structural elements within the .I troffcvt output. For example, .Cl html .B para indicates the beginning of a paragraph. .Li Provide (in a .I troffcvt action file) a set of HTML-specific macros that generate the appropriate .Cl html controls for the various structural elements. For example, .Rq H*para generates .Cl html .B para . .Li For the important structure-related macros in your macro package, redefine them (in a .I troffcvt action file) so they're expressed in terms of the HTML-specific macros. (It's posssible, of course, to redefine the macros from the macro package so they generate the .Cl html controls themselves. But having the .Cl html controls available through a set of macros allows the macros to be invoked directly in your document. This is important for some HTML constructs that have no .I troff analog, such as hyperlinks.) .Le Note that ``extending'' the .I troffcvt output language to include the .Cl html control is done using request definitions in an action file. Source-level changes to .I troffcvt itself are not needed. .LP The effect of the strategy outlined above is to remap the macros in your macro package from their usual actions onto actions that produce document structure information that .I tc2html can recognize. For this to work well, all the important structure-related macros in a macro package must be redefined, so the redefinition files used for .I tc2html tend to be more extensive than those used for other postprocessors. This is really the source of most of the work involved in getting .I tc2html to function well. Once a set of redefinitions is written for a given macro package, translation from .I troff to HTML is a straighforward process that usually generates fairly reasonable HTML. .LP Here's an example of how the strategy described above works in practice. The .Rq LP macro in the .B \-ms macro package means ``begin paragraph.'' But .Rq LP typically is implemented by executing several other requests (restore font, margins, adjustment, spacing, point size, etc.), and the .I troffcvt output you'd get by processing those requests really contains nothing that specifically indicates a paragraph. To work around this, we use the fact that .I tc2html interprets .Cl html .B para as indicating a paragraph beginning, and define a macro to generate that control: .Ps req H*para eol output-control "html para" .Pe Then we can redefine the .Rq LP macro in terms of the .Rq H*para macro: .Ps req LP eol \e break center 0 fill adjust b font R \e push-string ".H*para\en" .Pe The .B break , .B fill , .B adjust , and .B font actions cause .I troffcvt to adjust its internal state to match the effect that the .Rq LP macro normally has. The call to .Rq H*para results in .Cl html .B para in the output, so that .I tc2html can recognize the paragraph beginning. .LP The .Cl html markers that .I tc2html recognizes are shown below: .Ps .ta 2.75i \ehtml title \fRBegin document title\fP \ehtml header \f(CIN\fP \fRBegin level \f(CIN\fP header\f(CW \ehtml header-end \fREnd header (any level)\fP \ehtml para \fRBegin paragraph\fP \ehtml blockquote \fRBegin block quote\fP \ehtml blockquote-end \fREnd block quote\fP \ehtml list \fRBegin list\fP \ehtml list-end \fREnd list\fP \ehtml list-item \fRBegin list item\fP \ehtml display \fRBegin display (preformatted text)\fP \ehtml display-end \fREnd display\fP \ehtml display-indent \f(CIN\fP \fRSet display indent to \f(CIN\fP spaces\f(CW \ehtml definition-term \fRBegin definition list term\fP \ehtml definition-desc \fRBegin definition list description\fP \ehtml shift-right \fRShift left margin right\fP \ehtml shift-left \fRShift left margin left\fP \ehtml anchor-href \f(CIURL\fP \fRBegin HREF anchor for link to \f(CIURL\f(CW \ehtml anchor-name \f(CILABEL\fP \fRBegin NAME anchor with label \f(CILABEL\f(CW \ehtml anchor-toc \f(CIN\fP \fRBegin NAME anchor for level \f(CIN\fP TOC entry\f(CW \ehtml anchor-end \fREnd anchor (any kind)\fP .Pe The .I troff -level macros used to generate the .Cl html controls are shown below. These macros are defined in the action file .I actions-html : .Ps .ta 2.75i \&.H*title \fRBegin document title\fP \&.H*header \f(CIN\fP \fRBegin level \f(CIN\fP header\f(CW \&.H*header-end \fREnd header (any level)\fP \&.H*para \fRBegin paragraph\fP \&.H*bq \fRBegin block quote\fP \&.H*bq-end \fREnd block quote\fP \&.H*list \fRBegin list\fP \&.H*list-end \fREnd list\fP \&.H*list-item \fRBegin list item\fP \&.H*disp \fRBegin display (preformatted text)\fP \&.H*disp-end \fREnd display\fP \&.H*disp-indent \f(CIN\fP \fRSet display indent to \f(CIN\fP spaces\f(CW \&.H*dterm \fRBegin definition list term\fP \&.H*ddesc \fRBegin definition list description\fP \&.H*shift-right \fRShift left margin right\fP \&.H*shift-left \fRShift left margin left\fP \&.H*ahref \f(CIURL\fP \fRBegin HREF anchor for link to \f(CIURL\f(CW \&.H*aname \f(CILABEL\fP \fRBegin NAME anchor with label \f(CILABEL\f(CW \&.H*atoc \f(CIN\fP \fRBegin NAME anchor for level \f(CIN\fP TOC entry\f(CW \&.H*aend \fREnd anchor (any kind)\fP .Pe Note that since these names are longer than two characters, they cannot be used in compatibility mode. .\" .Ah "Invoking tc2html" .\" .LP The .Cl html controls are defined in a file .I actions-html that you can access on the .I troffcvt command line using .B \-a .B actions-html . If you use a macro package .B \-m \f[BI]xx\fP, you specify it on the command line, along with the general and HTML-specific .I troffcvt redefinitions for that macro package; these are in the action files .I tc.mxx and .I tc.mxx-html . Thus, to translate a file that you'd normally process using .B \-ms , the command would look like this: .Ps % \f(CBtroffcvt -a actions.html -ms -a tc.ms -a tc.ms-html\fP \f(CImyfile.ms\fP \f(CB\e | tc2html >\fP \f(CImyfile.html\fP .Pe That's pretty ugly, of course; it's better to use a wrapper script like .I troff2html that supplies the necessary options for you: .Ps % \f(CBtroff2httml -ms\fP \f(CImyfile.ms\fP \f(CB>\fP \f(CImyfile.html\fP .Pe .\" .Ah "Implementation of Various HTML Constructs" .\" .LP This section provides some specifics on how several .I troff concepts are turned into HTML elements. It should be considered illustrative rather than exhaustive. .\" .H*aname title-collection .H*aend .Bh "Document Titles" .\" .LP Title macros are implemented in terms of .Rq H*title , which generates an .Cl html .B title control. When .I tc2html sees this control, it goes into document HEAD collection mode. If the document contains a title, the .Cl html .B title line must be the first .Cl html control that .I tc2html sees. Should any other .Cl html control or document text occur first, .I tc2html assumes no title is present. Any leading document whitespace .Cl space "" ( or .Cl break lines) occurring prior to the title is skipped. .LP The title is terminated by the next .Cl html line with a structural marker, such as .Cl html .B para . The title text is used to produce the TITLE in the document HEAD part and the initial header in the document BODY part. .Cl space and .Cl break lines within the title do .I not terminate title text collection; instead, they are turned into spaces in the title and into

and
in the initial header. Consider the following .I troff input (using .B \-ms macros): .Ps \&.TL My \&.sp Title \&.LP This is a line .Pe This is converted by .I troffcvt into the following: .Ps \ehtml title My \espace Title \ebreak \ehtml para This is a line. .Pe The output from .I troffcvt is converted in turn by .I tc2html into this HTML: .Ps My Title

My

Title

This is a line. .Pe .B \-T .I title may be specified on the .I tc2html or .I troff2html command line to specify a title explicitly. It overrides the title in the document if there is one. .\" .Bh "Standard Paragraphs" .\" .LP The ``standard'' paragraph is a paragraph with the first line flush left. There is no mechanism for writing paragraphs with an indented first line; they're treated simply as standard paragraphs. .LP The standard paragraph is implemented in terms of .Rq H*para , which generates an .Cl html .B para control. This is turned by .I tc2html into

. .LP In the document BODY part, .Cl space is also interpreted as a paragraph marker, but during document title collection, .Cl space is treated as described above under ``\c .H*ahref #title-collection Document Titles .H*aend \&.'' .\" .Bh "Indented Paragraphs" .\" .LP Indented paragraphs (with or without a hanging tag) are implemented using definition lists (

...
). The tag is written as a definition term (
...
) and the paragraph body is written as a definition description (
...
). If there is no tag, the term part is empty. .LP Indented paragraph macros are implemented in terms of .Rq H*dterm and .Rq H*ddesc , which generate .Cl html .B definition-term and .Cl html .B definition-desc controls. .LP One problem with mapping indented paragraphs onto definition lists is that it's not always clear from the .I troff input where the list ends. In HTML, the definition list is a container for which you must write both a beginning and ending tag, but in .I troff only the beginnings of paragraphs are specified. This problem is handled (perhaps poorly) by closing the list when other HTML structural elements like a standard paragraph or a header are seen. Suppose you write something like this: .Ps \&.IP (i) Para 1 \&.IP (ii) Para 2 \&.LP Para 3 .Pe This is converted by .I troffcvt into the following: .Ps \ehtml definition-term (i) \ehtml definition-desc Para 1 \ebreak \ehtml definition-term (ii) \ehtml definition-desc Para 2 \ebreak \ehtml para Para 3 \ebreak .Pe When .I tc2html sees the first .Cl definition-term , it begins a definition list. The second .Cl definition-term continues the same list. The .Cl html .B para (resulting from the .Rq LP ) is part of a different structural element, so .I tc2html closes the list and begins a standard paragraph. The resulting HTML looks like this: .Ps
(i)
Para 1
(ii)
Para 2

Para 3
.Pe .\" .Bh "Right and Left Shifts" .\" .LP In .I troff , the left margin can be shifted right and left, e.g., as is done with the .B \-ms and .B \-man packages using .Rq RS and .Rq RE . HTML has no good way of shifting the margin, so shifts are performed using

    and
. This is admittedly a hack, but it works reasonably well. Shift macros are redefined to be implemented in terms of .Rq H*shift*right and .Rq H*shift*left , which generate .Cl html .B shift-right and .Cl html .B shift-left controls. These in turn are converted by .I tc2html to
    and
. .\" .Bh "Displays" .\" .LP Displays are implemented as preformatted text (
...
). Tabstops are respected within displays, although they must be approximated since characters widths are unknown. .I tc2html assumes 10 characters/inch for determining the width of tabstops. .LP Display macros are implemented in terms of .Rq H*disp and .Rq H*disp*end . Preformatted text in HTML has no additional indent relative to the left margin, but .I troff displays often are indented a bit. To handle this, .Rq H*disp*indent .I N can be used to set the display indent to .I N spaces. .LP .Rq H*disp , .Rq H*disp*end , and .Rq H*disp*indent generate .Cl html .B display , .Cl html .B display-end , and .Cl html .B display-indent controls. The first two of these are converted by .I tc2html into
 and 
. .Cl html .B display-indent generates no output itself, but causes .I tc2html to add spaces to the beginning of each line of a display. .LP Centered and right-justified displays are not implemented. They're treated as regular displays. .\" .Bh "Tables" .\" .LP If your input document has tables written in the .I tbl language, preprocess the document with .I tblcvt rather than with .I tbl . Your output will look better that way. .LP Table cell borders are hard to do well. In .I tbl you can put a border on any cell boundary, but in HTML a table has either no borders or borders around every cell. Currently, .I tc2html puts borders around every cell. .\" .Bh "Font Handling" .\" .LP Fonts are handled in .I tc2html by means of a table that associates four tags with each font name. The first two tags are used to turn the font on and off in normal text. The second two tags are used to turn the font on and off in displays. This table is read at runtime from the .I html-fonts file. Here's an example of what the file might look like: .Ps .ta .5i +1.25i +1.5i +1.25i R "" "" "" "" I B BI C "" "" CW "" "" CI CB CBI .Pe The difference between the tags for regular text and display text is that, since browsers implicitly switch the font to monospaced font in displays, the only thing that can be done for font changes there is to change the style attributes. .LP The initial font when .I tc2html begins is .Cw R (roman). When a font change occurs, the new font's begin tag is written out after terminating the previous font by writing its end tag. Using the font table just shown, this input: .Ps \efont R abc \efont I def \efont CW ghi \efont R jkl .Pe becomes this output: .Ps abcdefghijkl .Pe .\" .Bh "Tabs" .\" .LP Tabs are ignored except in displays. Adding extra space to tab over has no effect in regular paragraphs anyway, because browsers typically collapse runs of spaces. .LP Right-justified and centered tabs are treated as left-justified tabs. That is, they're completely botched. .\" .H*aname better-html .H*aend .Ah "Generating Better HTML" .\" .LP This section describes how you can embed hypertext links in your .I troff source and how to produce a table of contents containing clickable links to the main sections of your document. .\" .Bh "Generating Hypertext Links" .\" .LP The .Cl html controls used to generate hypertext links are: .Ps \ehtml anchor-href \f(CIURL\fP \ehtml anchor-name \f(CILABEL\fP \ehtml anchor-end .Pe The first two controls generate opening \f(CW
\fR and \f(CW\fR tags; the third generates a closing .Cw "" tag. .LP To embed hypertext links in your .I troff source, you can use the macros .Rq H*ahref and .Rq H*aend , or .Rq H*aname and .Rq H*aend . To write an HREF link, the .I troff source looks like this: .Ps \&.H*ahref http://www.some.host/some/path hypertext link \&.H*aend .Pe The resulting HTML looks like this: .Ps hypertext link .Pe To write a NAME link, the .I troff source looks like this: .Ps \&.H*aname my-name name link \&.H*aend .Pe The resulting HTML looks like this: .Ps name link .Pe Section-header macros are usually redefined to generate a NAME anchor for the table of contents, so don't surround a section header with anchor-generating macros. You'll end up with nested anchors, which .I tc2html disallows. You can generate a NAME link for a section (e.g., so that you refer to it using a specific name) as long as you don't write the link like this: .Ps \&.H*aname better-html \&.SH "Generating Better HTML" \&.H*aend .Pe Instead, write it like this: .Ps \&.H*aname better-html \&.H*aend \&.SH "Generating Better HTML" .Pe Unfortunately, some browsers don't seem able to jump to .Cw NAME anchors unless there is some text between the .Cw "" and .Cw tags. .LP You can't make a section header a hypertext link. You'd have to put the header (which generates a NAME link for the TOC) between the .Rq H*ahref and .Rq H*aend macros, which would result in nested anchors. .\" .Bh "Generating a Table of Contents" .\" .LP Putting a table of contents (TOC) into an HTML document requires some postprocessing of the .I tc2html output. The TOC entries can't be written to the beginning of the document because they're not all known until the input has been read entirely. The approach adopted with .I tc2html is as follows: .Ls B .Li Write a marker to the document indicating the desired TOC position. You do this using a special macro, described below. .Li Collect TOC entries in memory as the input is processed. .Li Write the TOC contents as a list near the end of the document. .Li Run .I tc2html-toc , a script that examines the HTML document and moves the TOC contents to the location indicated by the TOC position marker. .Le If you run .I tc2html directly, you must also run .I tc2html-toc directly. If you use .I troff2html , .I tc2html-toc is run for you automatically. .LP The .Cl html controls used to generate TOC entries are: .Ps \ehtml anchor-toc \f(CIN\fP \ehtml anchor-end .Pe Text occurring between .Cl html .B anchor-toc and .Cl html .B anchor-end pairs is written to the output, but it's also collected and remembered. When .I tc2html encounters end of file on its input, it writes the TOC entries to the output between two other HTML comments: .Ps \fITOC entries\fP .Pe If you want to generate a TOC entry explicitly in your .I troff source, use .Rq H*atoc and .Rq H*aend . For example: .Ps \&.H*atoc 1 My TOC Entry \&.H*aend .Pe The argument to .Rq H*atoc is the TOC entry level (1, 2, 3, ...). .LP It's unnecessary to invoke TOC macros directly if the section-header macros in your macro package are redefined to invoke the TOC macros for you. For example, the .Rq SH for the .B \-ms package is redefined like this in the .I tc.ms-html action file: .Ps req SH parse-macro-args eol \e break fill adjust b \e push-string ".H*atoc 1\en" \e push-string ".H*header 2\en" \e push-string "$1\en" \e push-string ".H*header*end\en" \e push-string ".H*aend\en" .Pe To specify the TOC title and generate the TOC position marker, use the .Rq H*toc*title macro. Invoke it as shown below, passing the title of your TOC as the first argument: .Ps \&.H*toc*title "Table of Contents" .Pe .Rq H*toc*title writes the TOC title to the output followed by a special HTML comment: .Ps Table of Contents .Pe The INSERT TOC HERE comment is used by .I tc2html-toc , along with the TOC BEGIN and TOC END comments, to find the TOC entries and move them to the desired location. .LP Action files that provide macro package redefinitions for .I tc2html can try to place an advisory TOC location marker in the document. This is used if you don't specify a location marker explicitly with .Rq H*toc*title : .Ps .Pe For instance, the .B \-man redefinitions put out this marker when the .Rq TH macro has been seen. The marker causes a TOC to be placed after the title line and the first man page section, unless one is specified explicitly. No TOC title is written with the advisory marker however, so the TOC will be ``title-less.'' (
...
). If there is no tag, the term part is empty. .LP Indented paragraph macros are implemented in terms of .Rq H*dterm and .Rq H*ddesc , which generate .Cltroffcvt-1.04/doc/tc.wrprc-html010064400017710000151000000027200630363405000202110ustar00junkyarddatamgmt00000400000027# tmac.wrprc-specific stuff. # HTML-specific redefinitions for tmac.wrprc # Ah, Bh, Ch need additional break before output text imm remove-name y Ah req Ah parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*header 2\n" \ push-string ".H*atoc 1\n" \ push-string "$1\n" \ push-string ".H*aend\n" \ push-string ".H*header*end\n" imm remove-name y Bh req Bh parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*header 3\n" \ push-string ".H*atoc 2\n" \ push-string "$1\n" \ push-string ".H*aend\n" \ push-string ".H*header*end\n" imm remove-name y Ch req Ch parse-macro-args eol \ break center 0 fill adjust b \ font "B" \ push-string ".H*atoc 3\n" \ push-string "$1\n" \ push-string ".H*aend\n" \ font "R" # for the fill stuff, should really save the fill value, then restore imm remove-name y Ps req Ps parse-macro-args eol \ break center 0 nofill \ push-string ".ta 4n +4n +4n +4n +4n +4n +4n +4n\n" \ push-string ".H*disp*indent 3\n" \ push-string ".H*disp\n" imm remove-name y Pe req Pe parse-macro-args eol \ break center 0 fill \ push-string ".ta .5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i\n" \ push-string ".H*disp*end\n" imm remove-name y Ls req Ls parse-macro-args eol \ break \ push-string ".H*list\n" imm remove-name y Li req Li parse-macro-args eol \ break \ push-string ".H*list*item\n" imm remove-name y Le req Le parse-macro-args eol \ break \ push-string ".H*list*end\n" troffcvt-1.04/doc/tblcvt.ms010064400017710000151000000514620634046200600174310ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 20 May 1997 .\" .EH 'tblcvt \*- A troffcvt Preprocessor'- % -'' .OH ''- % -'tblcvt \*- A troffcvt Preprocessor' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .de Ac \" action .LP .ta \n(LLuR \(bu \\$1 (\fB\\$2\fR) .br .. .TL .ps +2 tblcvt \*- A troffcvt Preprocessor .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .AB .I tblcvt reads .I troff input and converts the .I tbl -related parts to a format that .I troffcvt can understand more easily than raw .I tbl output. .AE .\" .H*toc*title "Table of Contents" .\" .Ah Introduction .\" .LP This document describes .I tblcvt (``\fItbl\fR convert''), a program that assists the process of using .I troffcvt to convert .I troff documents into other formats. It's assumed here that you're familiar with .I tbl . If you don't have the standard .I tbl documentation .I "Tbl \- A Program to Format Tables" , ( by M. E. Lesk), check the archive site from which you obtained the .I troffcvt distribution. .LP .I tblcvt exists because tables written in the .I tbl input language present a problem for .I troffcvt . .I troffcvt understands only the .I troff language and knows nothing of the .I tbl language, so input files containing tables need to be run through some sort of preprocessor before being given to .I troffcvt . In theory, you could run your .I troff files through .I tbl (since .I tbl generates output written in .I troff \^), and feed the result to .I troffcvt for processing. In practice, .I tbl output is generally arcane and incomprehensible, and .I troffcvt doesn't do a very good job with it. The purpose of .I tblcvt is to convert the parts of .I troff input files that are intended for .I tbl into something that's easier for .I troffcvt to understand. This makes it more likely that .I troffcvt will generate output that its postprocessors will be able to put back together into something that looks like a table in the target format. Not every table will look great, but any tables in this document are simple enough that they should appear reasonably good if the document is formatted with .I troff2html , .I troff2rtf , or .I unroff . .LP .I tblcvt is intended as a drop-in replacement for .I tbl . Suppose you'd normally format a document using a command like this: .Ps % \f(CBtbl\fP \f(CIfile\fP ... \f(CB| troff\fP [\f(CIoptions\fP] .Pe The analogous command using .I tblcvt and .I troffcvt looks something like this: .Ps % \f(CBtblcvt\fP \f(CIfile\fP ... \f(CB| troffcvt\fP [\f(CIoptions\fP] \f(CB|\fP \f(CIpostprocessor\fP .Pe Or, if you use one of the front ends like .I troff2html that invoke .I troffcvt and the appropriate postprocessor for you, the command might look like this: .Ps % \f(CBtblcvt\fP \f(CIfile\fP ... \f(CB| troff2html\fP [\f(CIoptions\fP] .Pe If it seems that .I troffcvt or a front end are not reading the output from .I tblcvt , specify .B \- after the option list to explicitly tell them to read the standard input after processing their other options: .Ps % \f(CBtblcvt\fP \f(CIfile\fP ... \f(CB| troffcvt\fP [\f(CIoptions\fP] \f(CB- |\fP \f(CIpostprocessor\fP % \f(CBtblcvt\fP \f(CIfile\fP ... \f(CB| troff2html\fP [\f(CIoptions\fP] \f(CB-\fP .Pe .\" .Ah "tblcvt Output Format" .\" .LP .I tblcvt ignores its input except for those parts between corresponding pairs of .Rq TS (table start) and .Rq TE (table end) requests. For each table, .I tblcvt digests its specification, figures out the table structure, and produces .I troff output that indicates the structure using a special set of requests. The output format has the property that it explicitly indicates the beginning and end of each table, each row within a table, and each cell within a row. The general form of table information written by .I tblcvt looks like this: .Ps .ne 11 \&.T*table*begin [\f(CItable options\fP] \&.T*column*info [\f(CIcolumn 1 options\fP] \fI\&...options for remaining columns...\fP \&.T*row*begin \&.T*cell*info [\f(CIcell layout options\fP] \fI\&...options for remaining cells in row...\fP \&.T*cell*begin [\f(CIcell formatting options\fP] \fI\&...cell contents...\fP \&.T*cell*end \fI\&...remaining cells in row...\fP \&.T*row*end \fI\&...remaining rows in table...\fP \&.T*table*end .Pe Shortcut requests are used in certain circumstances. If a cell is empty, .I tblcvt writes the single request .Rq T*empty*cell rather than .Rq T*cell*begin , .Rq T*cell*end , and the cell data between them. Similarly, if a cell of the table matrix is part of the area spanned by an earlier cell, .I tblcvt writes .Rq T*spanned*cell . If an entire row consists of a table-width line, .I tblcvt writes the single request .Rq T*row*line rather than .Rq T*row*begin , .Rq T*row*line , and the cell information between then. .LP Note that since .I tblcvt output uses long request names, you can't use compatibility mode .B \-C "" ( option) with .I troffcvt or a .I troffcvt front end. .\" .Bh "Table Beginning and Ending Requests" .\" .LP Each table begins with a .Rq T*table*begin request, which has the following form: .Ps \&.T*table*begin \f(CIrows cols header-rows align expand box allbox doublebox\fP .Pe .I rows and .I cols are the number of rows and columns in the table. (A row that draws a line is considered a data row.) .LP For tables that are specified to have a header (using .Rq TS .B H and .Rq TH ), .I tblcvt writes a non-zero value for the .I header-rows value. Otherwise .I header-rows is 0. .LP .I align is .B L or .B C to indicate the table is left-justified or centered. .LP .I expand is .B y if the table is expanded to the full line width, .B n otherwise. .LP The .I box , .I allbox , and .I doublebox values are each .B y or .B n , depending on whether or not .B box , .B allbox , and .B doublebox were given in the table specification. (Note that .B allbox and .B doublebox both imply .B box .) .LP Each table is terminated by a .Rq T*table*end request. .\" .Bh "Column Information Requests" .\" .LP Following the .Rq T*table*begin request, .I tblcvt writes one .Rq T*column*info line for each column of the table, in the format: .Ps \&.T*column*info \f(CIwidth sep equal\fP .Pe The column number is not specified; .Rq T*column*info lines will appear in consecutive order. .LP .I width is the minimum required width of the column. The value is non-zero if any entry in the given column specified a .B w option. If more than one entry specified .B w , the last one is used. If .I width is 0, no entry in the column specified .B w and the width is determined from the data values in the column. .LP .I sep is the column separation value. .LP The .I equal value is .B y if any entry in the column specified the .B e option, and .B n otherwise. All columns with an .I equal value of .B y should be made the same width. .\" .Bh "Row Beginning and Ending Requests" .\" .LP If a table row does not consist of a table-width line, the row begins and ends with .Rq T*row*begin and .Rq T*row*end requests. Information for the individual cells is written between these two requests (see .H*ahref #cell-requests "Cell Information Requests"\c .H*aend ). .LP If a row consists of a table-width single or double line, the .Rq T*row*begin and .Rq T*row*end requests are not used. Instead, the row is specified completely by a single .Rq T*row*line request, written using one of the following forms: .Ps .ne 2 .ta 2i \&.T*row*line 1 \fRTable-width single line\fP \&.T*row*line 2 \fRTable-width double line\fP .Pe .\" .H*aname cell-requests .H*aend .Bh "Cell Information Requests" .\" .LP Between each pair of .Rq T*row*begin and .Rq T*row*end requests, .I tblcvt writes out the information for each cell (column) in the row. First a set of .Rq T*cell*info lines is written, one for each cell. These requests provide basic layout parameters. Then the contents of the cells are written. For the usual case, a cell is written using .Rq T*cell*begin and .Rq T*cell*end requests, with the cell data appearing between the requests. Empty, spanned, or line-drawing cells are written using .Rq T*empty*cell , .Rq T*spanned*cell , and .Rq T*cell*line requests. .LP This means that cells begin with any of .Rq T*cell*begin , .Rq T*empty*cell , .Rq T*spanned*cell , or .Rq T*cell*line , and end with any of .Rq T*cell*end , .Rq T*empty*cell , .Rq T*spanned*cell , or .Rq T*cell*line . .LP The .Rq T*cell*info request has the following form: .Ps \&.T*cell*info \f(CItype vspan hspan vadjust border\fP .Pe The column number of the cell is not specified; .Rq T*cell*info lines will appear in consecutive order. .LP .I type is the cell type: .Ps .ne 5 .ta 1i L \fRLeft-justified\fP R \fRRight-justified\fP C \fRCentered\fP N \fRNumeric (align to decimal point)\fP A \fRAlphanumeric\fP .Pe .I vspan and .I hspan are the number of rows and columns spanned by the cell, including itself. Interpret these values as follows: .Ls B .Li If a cell spans no other cells, both .I vspan and .I hspan are 1. .Li If a cell spans other cells vertically, .I vspan is greater than 1. If a cell is spanned vertically by a cell from above, .I vspan is zero. .Li If a cell spans other cells horizontally, .I hspan is greater than 1. If a cell is spanned horizontally by a cell from the left, .I hspan is zero. .Le If all you want to know is whether or not a cell is spanned, the product of .I vspan and .I hspan is zero if and only if the cell is spanned. If you need to know whether spanning is in a particular direction, you need to examine .I vspan and .I hspan individually. This is summarized in the following table. .sp .5v .TS l lfB lfB lw(1i)fB lw(2i) lw(2i) . hspan = 0 hspan > 0 vspan = 0 spanned both ways spanned from above vspan > 0 spanned from left not spanned .TE .sp .5v .I vadjust is .B T if the cell contents should be vertically adjusted from the top, .B C if the contents should be vertically centered. .I vadjust is meaningful only for multiple-line cells. .LP .I border is the border value. If the value is 0, there is no border. Otherwise, the value is a bitmap with the following fields: .Ps .ne 9 .ta 1i 2i \fRBits Value Meaning\fP 0-1 1 \fRLeft border, single line\fP 2 \fRLeft border, double line\fP 2-3 1 \fRRight border, single line\fP 2 \fRRight border, double line\fP 4-5 1 \fRTop border, single line\fP 2 \fRTop border, double line\fP 6-7 1 \fRBottom border, single line\fP 2 \fRBottom border, double line\fP .Pe .LP The .Rq T*cell*begin request has the following form: .Ps \&.T*cell*begin \f(CIfont ptsize vspace\fP .Pe .I font is the font to use for formatting the cell, 0 if no font was specified. .LP .I ptsize is the point size to use for formatting the cell, 0 if no size was specified. .LP .I vspace is the vertical spacing to use for formatting the cell, 0 if no spacing was specified. .LP The .Rq T*cell*end request has no arguments: .Ps \&.T*cell*end .Pe If a cell is empty or spanned or draws a line, the .Rq T*cell*begin and .Rq T*cell*end requests are not used. Instead, the cell is specified using one of the following requests: .Ls B .Li A cell that has no data is indicated by .Rq T*empty*cell . This is functionally equivalent to: .Ps .ne 2 \&.T*cell*begin \&.T*cell*end .Pe except that it's not necessary to scan ahead to the second request to find out that the cell is empty. .Li A cell that is spanned by a cell occurring earlier in the table is indicated by .Rq T*spanned*cell . The .Rq T*cell*info lines written at the beginning of the row contain the information necessary to determine whether the cell is spanned from the top or from the left or both. Note that that spanned cell may be spanned by a cell with data in it, an empty cell, or a line-drawing cell. .Li A cell that draws a line is indicated by the .Rq T*cell*line request, written using one of the following forms: .Ps .ne 3 .ta 2i \&.T*cell*line 0 \fRColumn-data-width single line\fP \&.T*cell*line 1 \fRColumn-width single line\fP \&.T*cell*line 2 \fRColumn-width double line\fP .Pe A column-data-width line is a single line as wide as the contents of the column. It does not extend the full width of the column. This type of cell results from a .B \e_ data value in the table specification. .Le .\" .Ah "troffcvt Handling of tblcvt Output" .\" .LP The .Rq T* \f(BIxxx\fP requests are defined in the default .I actions file that .I troffcvt reads when it starts up. The actions for the requests cause .I troffcvt to perform a relatively simple mapping: .Ps .ne 12 .ta 3i \fBtblcvt output troffcvt output\fP \&.T*table*begin \f(CIarguments\fP \etable-begin \f(CIarguments\fP \&.T*table*end \etable-end \&.T*column*info \f(CIarguments\fP \etable-column-info \f(CIarguments\fP \&.T*row*begin \etable-row-begin \&.T*row*end \etable-row-end \&.T*cell*info \f(CIarguments\fP \etable-cell-info \f(CIarguments\fP \&.T*cell*begin \f(CIarguments\fP \etable-cell-begin \&.T*cell*end \etable-cell-end \&.T*row*line \f(CIargument\fP \etable-row-line \f(CIargument\fP \&.T*cell*line \f(CIargument\fP \etable-cell-line \f(CIargument\fP \&.T*spanned*cell \etable-spanned-cell \&.T*empty*cell \etable-empty-cell .Pe When a request written by .I tblcvt has arguments, the corresponding control written by .I troffcvt is written with arguments that are similar to, but not necessarily exactly the same. The primary exception is that the .I font , .I ptsize , and .I vspace arguments to .Rq T*cell*begin are converted directly by the .I troffcvt actions file into font and size .I troff directives, then translated into the .I troffcvt intermediate language. The font and size controls appear in .I troffcvt output immediately following the .Cl table-cell-begin control. See .H*ahref output.html .I "troffcvt Output Format and PostProcessor Writing" .H*aend for the exact format of the .Cl table- controls. .LP In addition to the .Rq T* \f(BIxxx\fP request names used by .I tblcvt , .I troffcvt uses the register names .B T*cell*ft , .B T*cell*ps , and .B T*cell*vs for internal purposes. .\" .Ah "Calculating Spans" .\" .LP Table specifications may indicate that a table element spans multiple rows or columns, or both. However, not all spanning specifications are legal, and .I tblcvt tries to catch those that are malformed. The spanning constraints enforced by .I tblcvt are: .Ls B .Li A cell cannot span left if there is no column to span into, so the .B s format cannot be used in the first table column. .Li A cell cannot span upward if there is no row to span into, so the .B ^ format cannot be used in the first table row. .I tblcvt "" ( does allow .B ^ to be used on the first format line following .Rq T& , since the column entry can span up into the last row of the previous section.) .Li A spanned area must comprise a rectangular block of cells. .Le The smallest illegal table specifications that include spans are shown below; each of them violates one of the first two spanning constraints: .Ps .ne 4 .ta 2i \&.TS .TS s . ^ . \fIdata\fP \fIdata\fP \&.TE .TE .Pe Assuming the first two constraints are satisfied, the smallest illegal table specifications that include spans are shown below .B l "" ( is used here, but any non-spanning column type may be substituted): .Ps .ne 5 .ta 2i \&.TS .TS l l l s ^ s . l ^ . \fIdata\fP \fIdata\fP \&.TE .TE .Pe The first table is illegal by the following reasoning. The cells in the first column form a single vertically-spanned element. The second column could be part of that element if both cells spanned to the left, since the resulting spanned area would be rectangular. However, since only one of the cells spans to the left, the spanned area is L-shaped, which is illegal. The second table is illegal by similar reasoning. The top two cells form a single element. The bottom two cells could be part of that element if they both spanned upward, but only one of them does. .LP .I tblcvt uses the strategy outlined below to determine the extent of spanned elements and to discover non-rectangularies in cell spanning. The strategy works by operating on a matrix with one column for each column specified in the format section of the table specification, and one row for each row of table data given in the data section of the specification. Working from left to right and top to bottom, each cell of the matrix is visited and the following checks are applied: .Ls B .Li If the current cell format is .B s or .B ^ , it's illegal, because it should have been found to be part of some spanning block to the left or above. (This check also discovers .B s in the first table column and .B ^ in the first row.) .Li If the current cell is not .B s or .B ^ , determine how far it spans other cells vertically and horizontally. The vertical span includes the cell itself and as many consecutive .B ^ -format cells that lie below the cell. The horizontal span is similar, but is determined by the number of consecutive .B s -format cells lying to the right of the cell. Denote the vertical and horizontal span count by .I vspan and .I hspan . .Li If .I vspan and .I hspan are both one, the cell stands alone and doesn't span any other cells. A standalone cell forms a 1\ \(mu\ 1 rectangle, so the cell is okay. Mark it as visited and go to the next unvisited cell. .Li If .I vspan or .I hspan (or both) are greater than one, then for the span to be rectangular, the cell must span a block of .I vspan\ \(mu\ hspan cells. We know that the cells directly to the right of and below the upper left corner cell are spanned properly, since they determine the span extents. Therefore, it's necessary only to examine the (\fIvspan\fP\^\-1)\ \(mu\ (\fIhspan\fP\^\-1) block of cells to the immediate lower right of the corner cell. These cells must span into the left column or top row of the block. This condition is satisfied if all the cells are of type .B s or type .B ^ , in any combination. (Proof left as an exercise for the reader.\^.\^.) If the condition is not satisfied, the table specification is illegal. Otherwise mark the cells in the spanned block as visited and proceed to the next unvisited cell. .Le Some tables are examined below to illustrate the strategy just described. .LP .B "Example 1:" The table shown below is illegal. .Ps .ne 5 \&.TS l s s l ^ s s s . \fIdata\fP \&.TE .Pe Beginning at the upper left, we see that the vertical and horizontal spans are 2 and 3. The remaining cells in this 2\ \(mu\ 3 block are the second and third cells in the second row. They both span into the first cell of the second row, so they are part of the span block. Therefore, the upper 2\ \(mu\ 3 block is okay. The next unvisited cell is the fourth cell in the first row. This cell is a standalone cell, so it's okay. The last unvisited cell is the fourth cell of the second row. This cell is a spanned cell, but it can't span into the block to the left without forming a non-rectangular block. The table specification is bad. .LP .B "Example 2:" Here's a table that appears at first glance as though it may be illegal. Is it? .Ps .ne 6 \&.TS l s s s ^ s ^ ^ ^ ^ s s . \fIdata\fP \&.TE .Pe Beginning at the upper left, we see that the vertical and horizontal spans are 3 and 4. This means 12 cells should be in the span block. We know that the three .B s cells to the right of the corner cell and the two .B ^ cells below the corner cell are part of the block, so the next step is to examine the remaining 2\ \(mu\ 3 block at the lower right. In the second row of the block, the second cell spans left into the first column (and is thus part of the span block), and the third and fourth cells span up into the first row (and are thus part of the span block). In the third row, the second cell spans up into the second row (and is thus part of the span block since that row has already been determined to be part of the block), and the third and fourth cells span into the third cell (which, since that cell has just been determined to be part of the block, makes the last two cells part of the block as well). .LP Therefore, in spite of its unusual specification, the table is legal. It consists of a single 3\ \(mu\ 4 spanned entry. .LP .B "Example 3:" Span calculations are performed with separate matrices for vertical and horizontal spans that initially assume all spans are 1. Suppose we have a table specification that looks like this: .Ps \&.TS l s l l s l ^ s l . a1 a2 b1 b2 c d \&.TE .Pe There are three format columns. There are three format rows but four data rows, so the last format line is used for the third and fourth data rows. The vertical and horizontal span matrices are 4\ \(mu\ 3, and start out like this: .Ps 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .Pe After calculating spans, the matrices end up like this: .Ps 1 1 1 2 0 1 3 3 1 2 0 1 0 0 1 2 0 1 0 0 1 2 0 1 .Pe matting the cell, 0 if no font was specified. .LP .I ptsize is the point size to use for formatting the cell, 0 if no size was specified. .LP .I vspace is the vertical spacing to use for formatting the celltroffcvt-1.04/doc/groff.ms010066400017710000151000000037630634144107500172450ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 9 April 1997 .\" .EH 'troffcvt Support for groff'- % -'' .OH ''- % -'troffcvt Support for groff' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .TL .ps +2 troffcvt Support for groff .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .LP .I troffcvt supports the following .I groff extensions to standard .I troff : .Ls B .Li Long names. Contexts in which long names are legal include: .Ps .ta 1.5i \&.xxx \fRLong request and macro names\fP \e[xxx] \fRLong special character names\fP \e*[xxx] \fRLong string names\fP \en[xxx] \fRLong register names\fP \ef[xxx] \fRLong font names\fP \e$[nnn] \fRLong (>9) macro argument references\fP .Pe 0 .Li Compatibility mode. The .Rq cp request and .B \&.C register are supported. Compatibility may be turned on from the .I troffcvt command line with the .B \-C option. .Li The .Rq mso request. .Li The .Rq do request. .Li The .B \e$* and .B \e$@ macro argument references. .Li The .B \e$0 macro name reference. .Li More than 9 macro arguments may be referenced (up to 99, though .I groff allows more). For macros above .B \e$9 , the notation \fB\e[\fInnn\fB]\fR may be used. .Li Aliases (the .Rq als and .Rq aln requests). .Li The .Rq shift request. .Li Named environments and the .B \&.ev string-valued register. .Li The .Es A '\fIxx\fR' escape sequence. .Li The .Rq if .B d conditional test. .Li The .Rq if .B r conditional test. .Li The .Rq if .B c conditional test. .Le troffcvt-1.04/doc/frontend.ms010066400017710000151000000061470632351453700177640ustar00junkyarddatamgmt00000400000027.\" this document requires the tmac.wrprc macros .\" .\" $(TROFF) $(MSMACROS) tmac.wrprc thisfile .\" .\" revision date - change whenever this file is edited .ds RD 11 April 1997 .\" .EH 'troffcvt Front End Writing'- % -'' .OH ''- % -'troffcvt Front End Writing' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .de St \" troffcvt special text \\&\\$3\fB@\\$1\fR\\$2 .. .de Cl \" troffcvt or RTF control \\&\\$3\fB\e\\$1\fR\\$2 .. .de Rq \" troff request \\&\\$3\fB\.\\$1\fR\\$2 .. .de Es \" troff escape \\&\\$3\fB\e\\$1\fR\\$2 .. .TL .ps +2 troffcvt Front End Writing .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .LP .I troffcvt converts .I troff input into an intermediary easily-parsed token stream. .I troffcvt postprocessors turn that token stream into some other target format. For example, .I tc2rtf turns the token stream into Rich Text Format (RTF), whereas .I tc2text turns it into slightly-formatted plain text. .LP A front end is typically a shell or Perl script that glues .I troffcvt and some postprocessor together via a pipe. It provides a convenience for users, who then need neither know nor care about the existence of .I troffcvt itself or the postprocessor; they only know that their .I troff input turns into some other format by invoking the front end. .LP When you write a .I troffcvt front end, the main thing you need to be concerned about is argument processing. .I troffcvt understands a certain set of flags, and the postprocessor very likely understands certain flags as well. The front end can determine its own syntax to some extent, but some of .I troffcvt 's options should be recognized and passed straight through. For instance, in order to preserve the correspondence between .I troff and .I troffcvt , the front end should pass through any .B \-m \fIxxx\fR flags. .LP Suppose you normally use something like this to format a document .I myfile.ms : .Ps % \f(CBtroff -ms myfile.ms\fP .Pe With .I troffcvt , you might use a command like this: .Ps % \f(CBtroffcvt -ms -a tc.ms myfile.ms | \f(CIpostprocessor\fP .Pe If additional files are used for the postprocessor, the front end can typically deduce what they are on the basis of any .B \-m \f[BI]xx\fP argument. In most cases, if .B \-m \f[BI]xx\fP is specified, the front end should also pass .B \-a .B tc.m \f[BI]xx\fP to provides any general .B \-m \f[BI]xx\fP-specific redefinitions. The front end may also pass a file that provides redefinitions that are appropriate for a specific postprocessor. For example, if .B \-ms is specified, .I troff2html will pass not only .I tc.ms , but .I tc.ms-html as well. There may be other arguments that the front end supplies. For example, .I tc2html has its own action file .I actions-html ), ( that's used in addition to the standard action file .I actions ) ( that .I troffcvt reads when it starts up: .Ps % \f(CBtroffcvt -a actions-html -ms -a tc.ms -a tc.ms-html myfile.ms | tc2html\fP .Pe troffcvt-1.04/man/004077500017710000151000000000000634147230100155755ustar00junkyarddatamgmt00000400000027troffcvt-1.04/man/troff2rtf.man010064400017710000151000000046130634044721400202130ustar00junkyarddatamgmt00000400000027.TH TROFF2RTF 1 .SH NAME troff2rtf \- convert \fItroff\fR documents to Rich Text Format .SH SYNTAX .B troff2rtf [ .BI \-m xx ] [ .B \-S .I charset ] [ .I file \&... ] .SH DESCRIPTION .I troff2rtf processes documents written to be formatted with .I troff (or .IR nroff , or any of the other .I *roff variants) and converts them to Rich Text Format. RTF is a reasonably portable interchange standard; files in RTF format can be read by a variety of applications, e.g., Microsoft Word, WordPerfect (Macintosh version 2.0 and up), WriteNow. .PP The main use for .I troff2rtf is to make it easier to transport .I troff documents for use with microcomputers. First, convert your document to RTF: .sp .5v .RS .ps -2 \f(CW% troff2rtf [\f(CIoptions\fP] file > file.rtf\fR .ps .RE .sp .5v The available options are described below. The one you'll most likely use is .BI \-m xx to specify a macro package like .B \-me or .BR \-ms . If the document contains tables, the conversion can be done like this instead: .sp .5v .RS .ps -2 \f(CW% tblcvt file | troff2rtf [\f(CIoptions\fP] > file.rtf\fR .ps .RE .sp .5v Then move the RTF file to your target machine and read it into your document processor. .PP Optional flags may be given to modify the operation of .IR troff2rtf , as follows: .TP .BI \-m xx Specify macro package, usually .BR \-man , .BR \-me , .BR \-mm , or .BR \-ms . .TP .B \-S\ \fIcharset\fR Specify the RTF character set. .I charset can be one of the following: .B ansi .B mac .B pc .BR pca . The default is the Macintosh character set. For documents that you intend to use under Windows, .B \-S .B ansi is a better choice. .SH "SEE ALSO" .BR tblcvt (1), .BR troffcvt (1) .SH "WHO-TO-BLAME" Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .SH BUGS .PP Table output generated when .I troff2rtf is used in concert with .I tblcvt has been known to crash Word outright; caution may be in order. In addition, you may need to read the resulting RTF document into a word processor and tweak column widths manually. .PP Word97 adds support for vertically merging table cells (using the .B \eclvmgf and .B \eclvmrg control words). .I troff2rtf supports vertical spans using these controls, but earlier versions of Word don't yet understand them. Consequently, what you'll see for .IR n -cell vertical spans is .I n individual cells, with all the text in the top cell and .IR n \-1 empty cells below it. troffcvt-1.04/man/Imakefile010064400017710000151000000052530634147040600174120ustar00junkyarddatamgmt00000400000027XCOMM troffcvt manual page Makefile all:: documents-ps:: troffcvt.ps tc2html.ps troff2html.ps tc2html-toc.ps \ troff2rtf.ps unroff.ps tblcvt.ps documents-html:: troffcvt.html tc2html.html troff2html.html tc2html-toc.html \ troff2rtf.html unroff.html tblcvt.html documents-text:: documents-txt documents-txt:: troffcvt.txt tc2html.txt troff2html.txt tc2html-toc.txt \ troff2rtf.txt unroff.txt tblcvt.txt documents-rtf:: troffcvt.rtf tc2html.rtf troff2html.rtf tc2html-toc.rtf \ troff2rtf.rtf unroff.rtf tblcvt.rtf AllTarget(troffcvt.man) FileFromMsubTemplate(troffcvt.man,troffcvt.msub,NullArg) TroffManToPostScript(troffcvt.ps,troffcvt.man,NullArg,NullArg) TroffManToHTML(troffcvt.html,troffcvt.man,NullArg,NullArg,troffcvt.man) TroffManToText(troffcvt.txt,troffcvt.man,NullArg,NullArg,troffcvt.man) TroffManToRTF(troffcvt.rtf,troffcvt.man,NullArg,NullArg,troffcvt.man) InstallManPage(troffcvt) TroffManToPostScript(tc2html.ps,tc2html.man,NullArg,NullArg) TroffManToHTML(tc2html.html,tc2html.man,NullArg,NullArg,tc2html.man) TroffManToText(tc2html.txt,tc2html.man,NullArg,NullArg,tc2html.man) TroffManToRTF(tc2html.rtf,tc2html.man,NullArg,NullArg,tc2html.man) InstallManPage(tc2html) TroffManToPostScript(troff2html.ps,troff2html.man,NullArg,NullArg) TroffManToHTML(troff2html.html,troff2html.man,NullArg,NullArg,troff2html.man) TroffManToText(troff2html.txt,troff2html.man,NullArg,NullArg,troff2html.man) TroffManToRTF(troff2html.rtf,troff2html.man,NullArg,NullArg,troff2html.man) InstallManPage(troff2html) TroffManToPostScript(tc2html-toc.ps,tc2html-toc.man,NullArg,NullArg) TroffManToHTML(tc2html-toc.html,tc2html-toc.man,NullArg,NullArg,tc2html-toc.man) TroffManToText(tc2html-toc.txt,tc2html-toc.man,NullArg,NullArg,tc2html-toc.man) TroffManToRTF(tc2html-toc.rtf,tc2html-toc.man,NullArg,NullArg,tc2html-toc.man) InstallManPage(tc2html-toc) TroffManToPostScript(troff2rtf.ps,troff2rtf.man,NullArg,NullArg) TroffManToHTML(troff2rtf.html,troff2rtf.man,NullArg,NullArg,troff2rtf.man) TroffManToText(troff2rtf.txt,troff2rtf.man,NullArg,NullArg,troff2rtf.man) TroffManToRTF(troff2rtf.rtf,troff2rtf.man,NullArg,NullArg,troff2rtf.man) InstallManPage(troff2rtf) TroffManToPostScript(unroff.ps,unroff.man,NullArg,NullArg) TroffManToHTML(unroff.html,unroff.man,NullArg,NullArg,unroff.man) TroffManToText(unroff.txt,unroff.man,NullArg,NullArg,unroff.man) TroffManToRTF(unroff.rtf,unroff.man,NullArg,NullArg,unroff.man) InstallManPage(unroff) TroffManToPostScript(tblcvt.ps,tblcvt.man,NullArg,NullArg) TroffManToHTML(tblcvt.html,tblcvt.man,NullArg,NullArg,tblcvt.man) TroffManToText(tblcvt.txt,tblcvt.man,NullArg,NullArg,tblcvt.man) TroffManToRTF(tblcvt.rtf,tblcvt.man,NullArg,NullArg,tblcvt.man) InstallManPage(tblcvt) troffcvt-1.04/man/Makefile010066400017710000151000000455400634147041100172420ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./man # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # troffcvt manual page Makefile all:: documents-ps:: troffcvt.ps tc2html.ps troff2html.ps tc2html-toc.ps \ troff2rtf.ps unroff.ps tblcvt.ps documents-html:: troffcvt.html tc2html.html troff2html.html tc2html-toc.html \ troff2rtf.html unroff.html tblcvt.html documents-text:: documents-txt documents-txt:: troffcvt.txt tc2html.txt troff2html.txt tc2html-toc.txt \ troff2rtf.txt unroff.txt tblcvt.txt documents-rtf:: troffcvt.rtf tc2html.rtf troff2html.rtf tc2html-toc.rtf \ troff2rtf.rtf unroff.rtf tblcvt.rtf all:: troffcvt.man all:: troffcvt.man troffcvt.man:: troffcvt.msub $(RM) $@ $(MSUB) troffcvt.msub > $@ clean:: $(RM) troffcvt.man help_aux:: @echo "'make "troffcvt.man"' to "build troffcvt.man troffcvt.ps:: troffcvt.man $(SOELIM) troffcvt.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > troffcvt.ps clean:: $(RM) troffcvt.ps help_aux:: @echo "'make "troffcvt.ps"' to "format troffcvt.ps in PostScript troffcvt.html:: troffcvt.man $(SOELIM) troffcvt.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >troffcvt.html clean:: $(RM) troffcvt.html help_aux:: @echo "'make "troffcvt.html"' to "format troffcvt.html in HTML troffcvt.txt:: troffcvt.man $(SOELIM) troffcvt.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > troffcvt.txt clean:: $(RM) troffcvt.txt help_aux:: @echo "'make "troffcvt.txt"' to "format troffcvt.txt in plain text troffcvt.rtf:: troffcvt.man troffcvt.man $(SOELIM) troffcvt.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> troffcvt.rtf clean:: $(RM) troffcvt.rtf install.man:: i.troffcvt.man i.troffcvt.man:: troffcvt.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) troffcvt.man $(MANDIR)/troffcvt.$(MANSUFFIX) help_aux:: @echo "'make "i.troffcvt.man"' to "install troffcvt.man manual page tc2html.ps:: tc2html.man $(SOELIM) tc2html.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > tc2html.ps clean:: $(RM) tc2html.ps help_aux:: @echo "'make "tc2html.ps"' to "format tc2html.ps in PostScript tc2html.html:: tc2html.man $(SOELIM) tc2html.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >tc2html.html clean:: $(RM) tc2html.html help_aux:: @echo "'make "tc2html.html"' to "format tc2html.html in HTML tc2html.txt:: tc2html.man $(SOELIM) tc2html.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > tc2html.txt clean:: $(RM) tc2html.txt help_aux:: @echo "'make "tc2html.txt"' to "format tc2html.txt in plain text tc2html.rtf:: tc2html.man tc2html.man $(SOELIM) tc2html.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> tc2html.rtf clean:: $(RM) tc2html.rtf install.man:: i.tc2html.man i.tc2html.man:: tc2html.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) tc2html.man $(MANDIR)/tc2html.$(MANSUFFIX) help_aux:: @echo "'make "i.tc2html.man"' to "install tc2html.man manual page troff2html.ps:: troff2html.man $(SOELIM) troff2html.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > troff2html.ps clean:: $(RM) troff2html.ps help_aux:: @echo "'make "troff2html.ps"' to "format troff2html.ps in PostScript troff2html.html:: troff2html.man $(SOELIM) troff2html.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >troff2html.html clean:: $(RM) troff2html.html help_aux:: @echo "'make "troff2html.html"' to "format troff2html.html in HTML troff2html.txt:: troff2html.man $(SOELIM) troff2html.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > troff2html.txt clean:: $(RM) troff2html.txt help_aux:: @echo "'make "troff2html.txt"' to "format troff2html.txt in plain text troff2html.rtf:: troff2html.man troff2html.man $(SOELIM) troff2html.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> troff2html.rtf clean:: $(RM) troff2html.rtf install.man:: i.troff2html.man i.troff2html.man:: troff2html.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) troff2html.man $(MANDIR)/troff2html.$(MANSUFFIX) help_aux:: @echo "'make "i.troff2html.man"' to "install troff2html.man manual page tc2html-toc.ps:: tc2html-toc.man $(SOELIM) tc2html-toc.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > tc2html-toc.ps clean:: $(RM) tc2html-toc.ps help_aux:: @echo "'make "tc2html-toc.ps"' to "format tc2html-toc.ps in PostScript tc2html-toc.html:: tc2html-toc.man $(SOELIM) tc2html-toc.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >tc2html-toc.html clean:: $(RM) tc2html-toc.html help_aux:: @echo "'make "tc2html-toc.html"' to "format tc2html-toc.html in HTML tc2html-toc.txt:: tc2html-toc.man $(SOELIM) tc2html-toc.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > tc2html-toc.txt clean:: $(RM) tc2html-toc.txt help_aux:: @echo "'make "tc2html-toc.txt"' to "format tc2html-toc.txt in plain text tc2html-toc.rtf:: tc2html-toc.man tc2html-toc.man $(SOELIM) tc2html-toc.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> tc2html-toc.rtf clean:: $(RM) tc2html-toc.rtf install.man:: i.tc2html-toc.man i.tc2html-toc.man:: tc2html-toc.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) tc2html-toc.man $(MANDIR)/tc2html-toc.$(MANSUFFIX) help_aux:: @echo "'make "i.tc2html-toc.man"' to "install tc2html-toc.man manual page troff2rtf.ps:: troff2rtf.man $(SOELIM) troff2rtf.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > troff2rtf.ps clean:: $(RM) troff2rtf.ps help_aux:: @echo "'make "troff2rtf.ps"' to "format troff2rtf.ps in PostScript troff2rtf.html:: troff2rtf.man $(SOELIM) troff2rtf.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >troff2rtf.html clean:: $(RM) troff2rtf.html help_aux:: @echo "'make "troff2rtf.html"' to "format troff2rtf.html in HTML troff2rtf.txt:: troff2rtf.man $(SOELIM) troff2rtf.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > troff2rtf.txt clean:: $(RM) troff2rtf.txt help_aux:: @echo "'make "troff2rtf.txt"' to "format troff2rtf.txt in plain text troff2rtf.rtf:: troff2rtf.man troff2rtf.man $(SOELIM) troff2rtf.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> troff2rtf.rtf clean:: $(RM) troff2rtf.rtf install.man:: i.troff2rtf.man i.troff2rtf.man:: troff2rtf.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) troff2rtf.man $(MANDIR)/troff2rtf.$(MANSUFFIX) help_aux:: @echo "'make "i.troff2rtf.man"' to "install troff2rtf.man manual page unroff.ps:: unroff.man $(SOELIM) unroff.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > unroff.ps clean:: $(RM) unroff.ps help_aux:: @echo "'make "unroff.ps"' to "format unroff.ps in PostScript unroff.html:: unroff.man $(SOELIM) unroff.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >unroff.html clean:: $(RM) unroff.html help_aux:: @echo "'make "unroff.html"' to "format unroff.html in HTML unroff.txt:: unroff.man $(SOELIM) unroff.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > unroff.txt clean:: $(RM) unroff.txt help_aux:: @echo "'make "unroff.txt"' to "format unroff.txt in plain text unroff.rtf:: unroff.man unroff.man $(SOELIM) unroff.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> unroff.rtf clean:: $(RM) unroff.rtf install.man:: i.unroff.man i.unroff.man:: unroff.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) unroff.man $(MANDIR)/unroff.$(MANSUFFIX) help_aux:: @echo "'make "i.unroff.man"' to "install unroff.man manual page tblcvt.ps:: tblcvt.man $(SOELIM) tblcvt.man | $(TROFF) $(MANMACROS) $(TROFFOPTS) > tblcvt.ps clean:: $(RM) tblcvt.ps help_aux:: @echo "'make "tblcvt.ps"' to "format tblcvt.ps in PostScript tblcvt.html:: tblcvt.man $(SOELIM) tblcvt.man | $(TROFF2HTML) $(TCMANMACROS) $(TROFFOPTS) - >tblcvt.html clean:: $(RM) tblcvt.html help_aux:: @echo "'make "tblcvt.html"' to "format tblcvt.html in HTML tblcvt.txt:: tblcvt.man $(SOELIM) tblcvt.man | $(UNROFF) $(TCMANMACROS) $(TROFFOPTS) - > tblcvt.txt clean:: $(RM) tblcvt.txt help_aux:: @echo "'make "tblcvt.txt"' to "format tblcvt.txt in plain text tblcvt.rtf:: tblcvt.man tblcvt.man $(SOELIM) tblcvt.man | $(TROFF2RTF) $(TCMANMACROS) $(TROFFOPTS)> tblcvt.rtf clean:: $(RM) tblcvt.rtf install.man:: i.tblcvt.man i.tblcvt.man:: tblcvt.man @if [ -d $(MANDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(MANDIR)); fi $(INSTALL) $(INSTMANFLAGS) tblcvt.man $(MANDIR)/tblcvt.$(MANSUFFIX) help_aux:: @echo "'make "i.tblcvt.man"' to "install tblcvt.man manual page # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend scan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = troffcvt-1.04/man/troffcvt.msub010064400017710000151000000124110631213160600203120ustar00junkyarddatamgmt00000400000027.TH TROFFCVT 1 .SH NAME troffcvt \- \fItroff\fP-to-XXX converter .SH SYNTAX .B troffcvt [ .I options ] .I file \&... .SH DESCRIPTION .PP .I troffcvt converts .I troff input into an intermediate form that is easier to interpret than raw .I troff language. This intermediate form can then be used by postprocessors like .I tc2html or .I tc2rtf to produce final output in a target format such as HTML or RTF. .PP .I troffcvt understands the options listed below. Except as noted, options must be specified before the first input file named on the command line. .TP .B \-A Normally, .I troffcvt reads the default action file before reading any action or macro files named on the command line using the .B \-a or .B \-m options. If .B \-A is specified, .I troffcvt doesn't read the default action file. This option is rarely used, but it can be helpful when you want to try out a modified default file. .TP .BI \-a "file," \0\-a "\0file" Read the given action file. .B \-a may also be specified in the input file part of the argument list. .TP .B \-C Turn on .IR groff -style compatibility mode. Specifically, this option disables recognition of long (> 2 character) request and macro names, and special character, register, string, font, and macro argument references of the forms .BI \e[ xxx ]\fR,\fP .BI \en[ xxx ]\fR,\fP .BI \e*[ xxx ]\fR,\fP .BI \ef[ xxx ]\fR,\fP and .BI \e$[ nnn ]\fR.\fP .IP If .B \-C is specified, compatibility mode is turned on when the first input file is about to be read. (Macro packages specified with .B \-m may turn on compatibility mode themselves, of course. However, compatibility mode is always turned off while action files are read.) .TP .BI \-d N, \0\-d "\0N" Turn on debugging flag .IR N . The flags are listed in .IR troffcvt.h . If .B \-d is not followed by a number, all flags are turned on. .TP .B \-l Generate .B \eline controls in the output to indicate the point at which each input line was read. These controls have the following form: .sp .5v .RS .nf \eline \fIfilename linenumber\fP .fi .RE .sp .5v where .I filename is the current input filename and .I linenumber is the current input line in that file. .TP .BI \-m xx Read the given macro package (e.g., .BR \-man , .BR \-ms ) before the input files are read. .TP .BI \-r N, \0\-r "\0N" Specify a resolution of .I N units per inch. The default is 432 units/inch. .TP .BI \-t formatter-type, \0\-t "\0formatter-type" Specify a formatter type that .I troffcvt should try to act like. Valid .I formatter-type values are: .RS .TP .B nroff Act like .I nroff .TP .B troff Act like .I troff .RE .IP This option has little effect on .IR troffcvt 's behavior other than to determine the result of the .B \&.if .B t and .B \&.if .B n conditionals. .PP .I troffcvt finds action files by looking in the following locations: .IP \(bu The current directory. .IP \(bu The .I troffcvt library directory, .IR $(PROJLIBDIR) . .PP .I troffcvt finds macro packages by looking in the following locations: .IP \(bu The directories named by the .B TROFFCVT_TMAC_PATH environment variable, if that variable is set. .B TROFFCVT_TMAC_PATH consists of one or more directories, separated by colons. .IP \(bu The directory named by the .B TROFFCVT_LIB_DIR environment variable, if that variable is set. .IP \(bu The current directory. .IP \(bu The compiled-in .I troffcvt library directory .IR $(PROJLIBDIR) . This allows you to override a system macro package by placing a different version in the .I troffcvt library. .IP \(bu The system macro directory (e.g., .I /usr/lib/tmac or .IR /usr/share/groff/tmac ). .PP Macro and action files specified with .B \-m and .B \-a prior to the first input file are processed in order before the first input file is read. Once the initial options have been read and processed, .I troffcvt reads the input files, or the standard input if no files are read. The name .B \- may be used to refer explicitly to the standard input. .B \-a may be used to intersperse action files with input files in this part of the argument list. For example: .sp .5v .RS % troffcvt -ms mymacros -a tc.mymacros mydoc .RE .sp .5v .\" .SH DIAGNOSTICS .PP If .I troffcvt cannot open a macro file, you will see this message: .sp .5v .RS \f(CWcannot open macro file -m\f(CIxx\fR .RE .sp .5v This message is fatal. .PP If .I troffcvt cannot open an action file, you will see this message: .sp .5v .RS \f(CWcannot open action file <\f(CIxx\f(CW>\fR .RE .sp .5v This message usually indicates a problem, but is not fatal (except for the default action file .IR actions , which must be available for .I troffcvt to do anything at all). If you still get reasonable output, you can ignore it. To make the message go away, create an empty file named .I xx in any of the directories in which .I troffcvt looks for action files. If you don't get reasonable output, then a non-empty file needs to be created that redefines the macros that confuse .IR troffcvt . .\" .SH FILES .ta 3i \fI$(PROJLIBDIR)\fP \fItroffcvt\fP library directory .SH WHO-TO-BLAME Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .\" .SH "SEE ALSO" .BR tc2html (1), .BR tc2rtf (1), .BR tc2text (1), .BR troff2html (1), .BR troff2rtf (1), .BR unroff (1). .PP \fItroffcvt \- Notes, Bugs, Deficiencies\fP. .SH BUGS .PP There are many. See the document \fItroffcvt \- Notes, Bugs, Deficiencies\fP. ]\fR,\fP .BI \en[ xxx ]\fR,\fP .BI \e*[ xxx ]\fR,\fP .BI \ef[ xxx ]\fR,\fP and .BI \e$[ nnn ]\fR.\fP .IP If .B \-C is specified, compatibility mode is turned on when the first input file is about to be read. (Macro packages specified with .B \-m mtroffcvt-1.04/man/troff2html.man010064400017710000151000000027120631007500000203450ustar00junkyarddatamgmt00000400000027.TH TROFF2HTML 1 .SH NAME troff2html \- convert \fItroff\fR documents to Hypertext Markup Language .SH SYNTAX .B troff2html [ .I options ] .I file \&... ] .SH DESCRIPTION .I troff2html converts files written in the .I troff input language and converts them to Hypertext Markup Language (HTML). It works by running the input files through .I troffcvt and then through .I tc2html and .IR tc2html-toc . .PP .I troff2html understands the usual .I troffcvt options. It also understands the additional options listed below: .TP .B \-D Enable debugging output. .TP .B \-E Cause .I tc2html to echo token information to .I stderr as tokens are read from .IR troffcvt . .TP .B \-n No execution. Just show the commands that .I troff2html would execute to process the document. .TP .B \-p Don't run the postprocessors .RI ( tc2html and .IR tc2html-toc ). The output from .I troff2html will be in the .I troffcvt output language. .TP .BI \-T \0title Specify a title for the document. This can be used for documents that do not contain any recognizable title. If the document does contain a title, it is overridden. .SH "SEE ALSO" troffcvt(1), tc2html(1) .SH "WHO-TO-BLAME" Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .SH BUGS .I troff2html uses a set of special macros that tell .I troffcvt how to generate .IR tc2html -specific output that .I tc2html uses to recognize HTML structural elements. These macros do not work in compatibility mode. troffcvt-1.04/man/tc2html-toc.man010066400017710000151000000047770632351463400204540ustar00junkyarddatamgmt00000400000027.TH TC2HTML-TOC 1 .SH NAME tc2html-toc \- table of contents processor for \fItc2html\fP .SH SYNTAX .B tc2html-toc .I file \&... .SH DESCRIPTION .I tc2html is a postprocessor for .I troffcvt that produces Hypertext Markup Language (HTML). .I tc2html is capable of generating a table of contents (TOC). However, since TOC entries cannot all be known until the entire input document has been read, .I tc2html writes the TOC near the end of the HTML document. .PP To handle this problem, .I tc2html-toc examines .I tc2html output for a table of contents and moves it to the correct location. .I tc2html-toc is invoked for your automatically if you use .I troff2html (which also invokes .IR tc2html ). If you run .I tc2html manually, you must also run .I tc2html-toc manually. .PP .I tc2html and .I tc2html-toc cooperate by means of the following conventions. If .I tc2html writes a TOC, it surrounds them with the following two HTML comments: .sp .5v .RS .nf .fi .RE .sp .5v If the user wishes to explicitly specify a location for the TOC, this may be done by invoking the .B \&.H*toc*title request in the document. This request writes a TOC title followed by this HTML comment: .sp .5v .RS .RE .sp .5v In addition, macro package redefinitions used with .I tc2html can make a guess about where the TOC should be located in the absence of an explicit location marker. To do so, a redefinition can write the following advisory marker comment: .sp .5v .RS .RE .sp .5v For example, redefinitions for the .B \-man macros can write an advisory location for the TOC after the .B \&.TH macro invocation has been seen. .PP Given these conventions, .I tc2html-toc reads the input and examines it for the TOC and TOC location. The input is written unchanged to the output if no TOC is found. Otherwise, the locations listed below are used to reposition the TOC (with locations listed first taking priority): .IP \(bu The position of the TOC location marker. .IP \(bu The position of the advisory TOC location marker. .IP \(bu The beginning of the part of the document. .\" .SH "SEE ALSO" .H*ahref troffcvt.html .B troffcvt\c .H*aend (1), .H*ahref tc2html.html .B tc2html\c .H*aend (1), .H*ahref tc2html.html .B troff2html\c .H*aend (1) .SH "WHO-TO-BLAME" Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .SH DIAGNOSTICS .I tc2html-toc exits with an error if it discovers that the TOC location marker lies within the TOC itself. troffcvt-1.04/man/tblcvt.man010066400017710000151000000056040633515767600176140ustar00junkyarddatamgmt00000400000027.TH TBLCVT 1 .SH NAME tblcvt \- \fItroffcvt\fP preprocessor to convert \fItbl\fP-format tables .SH SYNTAX .B tblcvt [ .I file ] \&... .SH DESCRIPTION .PP .I tblcvt examines .I troff input for tables that would normally be processed by the .I tbl program, i.e., for lines bracketed by the .B \&.TS table start and .B \&.TE table end requests. .I tblcvt parses table specifications and data and converts it to a form that .I troffcvt can more easily handle. This is useful for document processing commands that use .IR troffcvt , since .I troffcvt has knowledge only of the .I troff input language, and knows nothing of the .I tbl input language. .PP .I tblcvt is a direct replacement for .IR tbl . Suppose you would normally process a document using .I tbl and .I troff (or .IR groff, etc.) like this: .sp .5v .RS .ps -2 \f(CW% tbl file ... | troff ...\fP .ps .RE .sp .5v To format the document using .I tblcvt and .IR troffcvt , use a command like this: .sp .5v .RS .ps -2 \f(CW% tblcvt file ... | troffcvt ...\fP .ps .RE .sp .5v Actually, it's more likely that you'll be using one of the .I troffcvt front ends such as .IR troff2html than that you'll be using .I troffcvt directly. .I troffcvt in the preceding command may be replaced by the name of the front end: .sp .5v .RS .ps -2 \f(CW% tblcvt file ... | troff2html ...\fP .ps .RE .sp .5v If it seems that .I troffcvt or a front end are not reading the output from .I tblcvt , specify .B \- after the option list to explicitly tell them to read the standard input after processing their other options: .sp .5v .RS .nf .ps -2 \f(CW% tblcvt file ... | troffcvt ... -\fP \f(CW% tblcvt file ... | troff2html ... -\fP .ps .fi .RE .sp .5v .\" .SH DIAGNOSTICS .PP Diagnostic messages are written in this format: .sp .5v .RS .ps -2 \f(CWtblcvt:line \f(CIl\fP (table \f(CIt\fP, section \f(CIs\fP): \f(CImessage...\fR .ps .RE .sp .5v This indicates that a problem was detected at line number .IR l , and that .I tblcvt considers the line to be part of table number .I t and section .I s within the table. Section numbers start at one and are incremented for each .B \&.T& request that occurs within a table specification. .\" .SH "SEE ALSO" .BR troffcvt (1) .PP \fItblcvt \- A troffcvt Preprocessor\fP .\" .SH WHO-TO-BLAME Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .\" .SH BUGS .PP For the most part, .I tblcvt assumes your tables make sense, i.e., are legal according to the .I tbl input language. .I tblcvt may complain about malformed table constructs (if it detects them), but it may also get confused by them and generate garbage output. .PP .I tblcvt generates .I troff output that uses long request names, so you can't use compatibility mode .B \-C "" ( option) with .I troffcvt or a .I troffcvt front end. .PP .I tblcvt doesn't support vertically-spanned lines. It prints a warning when it detects one, but the table output won't be correct. troffcvt-1.04/man/tc2html.man010064400017710000151000000021040631007665000176420ustar00junkyarddatamgmt00000400000027.TH TC2HTML 1 .SH NAME tc2html \- convert \fItroffcvt\fR output to Hypertext Markup Language .SH SYNTAX .B tc2html [ .I options ] .I file \&... ] .SH DESCRIPTION .I tc2html is a postprocessor for .I troffcvt and converts .I troffcvt output to to Hypertext Markup Language (HTML). It's usually invoked by running the .I troffcvt front end .I troff2html . .PP .I tc2html understands the following options: .TP .B \-D Enable debugging output. .TP .B \-E Cause .I tc2html to echo token information to .I stderr as tokens are read from .IR troffcvt . .TP .BI \-T \0title Specify a title for the document. This can be used for documents that do not contain any recognizable title. If the document does contain a title, it is overridden. .SH "SEE ALSO" troffcvt(1), troff2html(1) .SH "WHO-TO-BLAME" Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .SH BUGS .I tc2html uses a set of special macros that tell .I troffcvt how to generate .IR tc2html -specific output that indicates HTML structural elements. These macros do not work in compatibility mode. troffcvt-1.04/man/unroff.man010064400017710000151000000043550634070222500175730ustar00junkyarddatamgmt00000400000027.TH UNROFF 1 .SH NAME unroff \- convert \fItroff\fR documents to plain text .SH SYNTAX .B unroff [ .B \-E ] [ .B \-J ] [ .B \-8 ] [ .BI \-m xx ] [ .I file \&... ] .SH DESCRIPTION .I unroff processes documents written to be formatted with .I troff (or .IR nroff , or any of the other .I *roff variants) and converts them to plain text. This is similar to what .I deroff does, but the result is sometimes better than .I deroff output. .PP Optional flags may be given to modify the operation of .IR unroff , as follows: .TP .B \-E Echo input tokens as they are read. Useful mainly for debugging. .TP .B \-J Join output lines that would be part of a single paragraph so they form a single output line. This is useful if you plan to move the resulting output into a document formatter that treats paragraphs as a single line. The default is to do line wrapping according to the line length specified in the input document. .TP .B \-8 Write 8-bit ISO Latin-1 (ISO 8859-1) characters. This option may be useful for producing output intended to be viewed on devices capable of 8-bit character display. Without this option, 8-bit Latin-1 characters will generall appear in the output as ``[[name]]'' where ``name'' is the .I troffcvt internal name for the character, e.g., ``[[Aacute]]''. For some of these characters, an ASCII approximation will be used if something reasonably close is available. .TP .BI \-m xx Specify macro package, usually .BR \-man , .BR \-me , .BR \-mm , or .BR \-ms . .SH DIAGNOSTICS .PP .B "line length clipped to nnn chars." A very long line length was requested, so long that it would likely result in output line assembly buffer overflow. The length is clipped to prevent this. .PP .B "output buffer capacity exceeded." This means some line is so long that it couldn't be collected in the output line assembly buffer. Most likely this signals a bug in .IR tc2text , since the length is supposed to be kept within reasonable bounds (see previous paragraph). .\" .SH "SEE ALSO" .BR troffcvt (1), .BR tc2text (1) .\" .SH "WHO-TO-BLAME" Paul DuBois, .H*ahref mailto:dubois@primate.wisc.edu .IR dubois@primate.wisc.edu\c .H*aend \&. .\" .SH BUGS .PP .I unroff doesn't do so well with tables, particularly tables with multiple-line cells. Table centering isn't handled. troffcvt-1.04/config/004077500017710000151000000000000632576261200163005ustar00junkyarddatamgmt00000400000027troffcvt-1.04/config/site.p-def010064400017710000151000000002340626662671000201550ustar00junkyarddatamgmt00000400000027#ifdef BeforeVendorCF #endif /* BeforeVendorCF */ #ifdef AfterVendorCF #ifdef SunArchitecture #define TmpDir /usr/tmp #endif #endif /* AfterVendorCF */ troffcvt-1.04/config/Imake.p-params010064400017710000151000000043370632576113600207720ustar00junkyarddatamgmt00000400000027# ifndef ProjectName # define ProjectName troffcvt # endif # ifndef ProjectMajorRelease # define ProjectMajorRelease 1 # endif # ifndef ProjectMinorRelease # define ProjectMinorRelease 04 # endif /* * Name of file to include to get string function definitions. Override * as on systems that don't have */ #ifndef StringH #if defined(SYSV) || defined(SVR4) #define StringH #else #define StringH #endif #endif #ifndef StringHDefines #define StringHDefines -D'STRING_H=$(STRING_H)' #endif #ifndef ProjectDefines #define ProjectDefines $(VARARGS_DEFINES) $(STRING_H_DEFINES) #endif #ifndef ProjectIncludes #define ProjectIncludes -I. -I$(INCLUDESRC) #endif #ifndef LibDir #define LibDir $(LOCALUSRLIBDIR)/troffcvt #endif #ifndef ProjLibDir #define ProjLibDir $(LIBDIR) #endif /* * Directory in which system macro files are found. */ #ifndef MacroLibDir #define MacroLibDir $(USRLIBDIR)/tmac #endif /* * Prefix for constructing a system macro filename. These filenames * are usually things like tmac.e or tmac.s, but some systems (e.g., * Solaris) use names like e or s. */ #ifndef MacroFilePrefix #define MacroFilePrefix tmac. #endif #ifndef TcGenLib #define TcGenLib $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a #endif #ifndef DepTcGenLib #define DepTcGenLib $(LIBSRC)/libtcgen.a #endif #ifndef TcReadLib #define TcReadLib $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a #endif #ifndef DepTcReadLib #define DepTcReadLib $(LIBSRC)/libtcread.a #endif #ifndef TcUnixLib #define TcUnixLib $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a #endif #ifndef DepTcUnixLib #define DepTcUnixLib $(LIBUNIXSRC)/libtcunix.a #endif LIBDIR = LibDir PROJLIBDIR = ProjLibDir MACROLIBDIR = MacroLibDir MACROFILEPREFIX = MacroFilePrefix STRING_H = StringH STRING_H_DEFINES = StringHDefines INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = TcGenLib DEPTCGENLIB = DepTcGenLib TCREADLIB = TcReadLib DEPTCREADLIB = DepTcReadLib TCUNIXLIB = TcUnixLib DEPTCUNIXLIB = DepTcUnixLib troffcvt-1.04/config/sun.p-cf010064400017710000151000000006120626662671100176510ustar00junkyarddatamgmt00000400000027/* * Sun parameters. This has been tested on SunOS 4.1.1B and SunOS 5.4. */ /* * Parameters that depend on the OS version. */ #ifdef SVR4Architecture /* SunOS 5.x */ #ifndef MacroFilePrefix #define MacroFilePrefix /* empty */ #endif #else /* SunOS 4.x */ /* need to compile with gcc, not regular cc (source uses prototypes) */ #ifndef HasGcc2 #define HasGcc2 YES #endif #endif troffcvt-1.04/config/FreeBSD.p-cf010064400017710000151000000000770626662671100202630ustar00junkyarddatamgmt00000400000027#ifndef MacroLibDir #define MacroLibDir /usr/share/tmac #endif troffcvt-1.04/config/hp.p-cf010066400017710000151000000001650627103520300174420ustar00junkyarddatamgmt00000400000027 /* need to compile with gcc, not regular cc (source uses prototypes) */ #ifndef HasGcc2 #define HasGcc2 YES #endif troffcvt-1.04/config/Mips.p-cf010066400017710000151000000002620631402504600177430ustar00junkyarddatamgmt00000400000027/* need to compile with gcc, not regular cc (source uses prototypes) */ #ifndef HasGcc2 #define HasGcc2 YES #endif #ifndef MacroLibDir #define MacroLibDir /usr/lib/tmac #endif troffcvt-1.04/config/linux-pmac.p-cf010064400017710000151000000001030626662671100211140ustar00junkyarddatamgmt00000400000027#ifndef MacroLibDir #define MacroLibDir /usr/lib/groff/tmac #endif troffcvt-1.04/h/004077500017710000151000000000000634014070100152445ustar00junkyarddatamgmt00000400000027troffcvt-1.04/h/troffcvt.h010064400017710000151000000407520633770404500172720ustar00junkyarddatamgmt00000400000027/* * troffcvt.h -- troffcvt interface stuff */ /* * Param - internal parameter type (should be 4 bytes at least), used * for passing around generic signed integer values. */ typedef long Param; /* * XChar - "extended" character. This is the type used internally to hold * character values. * * The encoding is as follows: * 1) plain (ASCII) character - the character is stored in the low-order byte. * Since ASCII characters are < 128, only the lower 7 bits are used. Null * bytes are stripped, so a zero value is never stored. * 2) 8-bit character - the character is stored in the low-order byte, but the * values are in the range 128-255. * 3) escaped character (\c) - the character c is stored in the low-order byte, * and the first bit of the second byte is turned on. Thus escape codes are * in the range 1-511. (256 will never occur because that would be an escaped * null.) * 4) special characters (\(xx or \[xxx]) - the characters xx or xxx are * converted to a special-character code (a value >= 512). * * An unsigned value is used to avoid problems with sign bits. */ typedef unsigned long XChar; #define escBase 0x100 /* escape code base (9th bit turned on) */ #define spCharBase 0x200 /* first special-char code */ /* * Some convenience defines for typecasting operations on XChar * strings. */ #define XStrFree(s) Free ((char *) s) /* * Internal end-of-input-source indicator. EOF isn't used because that's * -1 on many (all?) systems, and the input routines return an unsigned * value. */ #define endOfInput 0 /* * Debugging flags and macro for testing debug setting. * To turn on flag 1L<oRequest #define nMacro nObject->oMacro #define nRegister nObject->oRegister }; struct Object { short oType; short oRefCount; union ObjInfo { Request *oReqPtr; Macro *oMacPtr; Register *oRegPtr; } oInfo; #define oRequest oInfo.oReqPtr #define oMacro oInfo.oMacPtr #define oRegister oInfo.oRegPtr }; struct Request { Action *reqPActions; /* parsing actions */ Action *reqPPActions; /* post-parsing actions */ }; /* * Macro structure is also used to hold troff strings. A string * is treated like a macro without arguments. */ struct Macro { XChar *macBuf; /* macro body */ long macSiz; /* current size of macro body */ long macMaxSiz; /* maximum size of macBuf */ }; struct Register { Param regValue; Param regIncrement; short regFormat; short regFmtWidth; short regReadOnly; }; struct Action { char *actName; int (*actFunc) (); int actArgc; XChar *actArgv[maxActionArgs]; Action *actNext; }; /* * Special characters appear as \(xx or \[xxx] in the input, where xx or * xxx consist of plain (ASCII) characters. * * The name is the string xx or xxx. * * The hash value is computed from the name and is used to speed up lookups. * * The code is a value >=256 that is the internal representation of the * special character. * * The value is the string that appears in the output when the special * character appears in the input. E.g., \(bu in the input turns into * @bullet in the output. This value is written literally to the output, * so it cannot itself contain any special characters. Because of that * it's sufficient for the spChar member to be char* rather than XChar*. * (NewSpChar() takes an XChar* argument for the value because it's easier * to arrange to pass that type of string, but it's converted in NewSpChar * to an ordinary char* string.) * * spNext points to the next structure in the list of special characters. */ struct SpChar { XChar *spName; long spHash; XChar spCode; char *spValue; SpChar *spNext; }; /* * Environment structure */ typedef struct Environ Environ; struct Environ { XChar *eName; /* environment name */ Param eSize; Param ePrevSize; Param eSpaceSize; XChar eFont[maxFontNameLen]; XChar ePrevFont[maxFontNameLen]; Param eFillMode; Param eAdjust; Param eAdjMode; Param eCenterCount; Param eVSize; Param ePrevVSize; Param eLineSpacing; Param ePrevLineSpacing; Param eLineLen; Param ePrevLineLen; Param eIndent; Param ePrevIndent; Param eTempIndent; XChar *eItMacro; Param eItCount; Param eTabCount; Param eTabPos[maxTabStops]; char eTabType[maxTabStops]; XChar eTabChar; XChar eLeaderChar; Param eUlCount; Param eCUlCount; XChar eCtrlChar; XChar eNbCtrlChar; Param eHyphenMode; XChar eHyphenChar; Param eTitleLen; Param ePrevTitleLen; /* nm is not supported */ /* nn is not supported */ /* mc is not supported */ Environ *eNext; /* next in environment list */ }; void SetOpenMacroFileProc (FILE *(*proc) ()); FILE *OpenMacroFile (char *file, char *mode); void ReadInput (void); int ReadActionFile (char *filename); void FreeActions (Action *ap); int ProcessActionList (Action *ap); int ProcessLine (void); void ProcessRequest (short jiggerCompat); void ProcessText (void); char *CharToOutputStr (XChar c); XChar *InterpretActionArg (XChar *p); int ParseNumber (int defUnit, int relAllowed, Param curVal, Param *val); Param ParseSizeRef (void); Name *ParseRegisterRef (void); XChar *ParseNameRef (void); void ParseWidth (void); void ParseNameTest (void); int AParseARNumber (int argc, XChar **argv); int AParseChar (int argc, XChar **argv); int AParseCondition (int argc, XChar **argv); int AParseFileName (int argc, XChar **argv); int AParseMacroArgs (int argc, XChar **argv); int AParseName (int argc, XChar **argv); int AParseNames (int argc, XChar **argv); int AParseNumber (int argc, XChar **argv); int AParseEmbolden (int argc, XChar **argv); int AParseStringValue (int argc, XChar **argv); int AParseTabStops (int argc, XChar **argv); int AParseTitle (int argc, XChar **argv); int AParseTransList (int argc, XChar **argv); int AProcessCondition (int argc, XChar **argv); int AProcessDo (int argc, XChar **argv); int APointSize (int argc, XChar **argv); int ASpaceSize (int argc, XChar **argv); int AConstantWidth (int argc, XChar **argv); int AEmbolden (int argc, XChar **argv); int AFont (int argc, XChar **argv); int AFontPosition (int argc, XChar **argv); int APageLength (int argc, XChar **argv); int ABeginPage (int argc, XChar **argv); int APageNumber (int argc, XChar **argv); int AOffset (int argc, XChar **argv); int ANeed (int argc, XChar **argv); int AMarkVertical (int argc, XChar **argv); int AReturnVertical (int argc, XChar **argv); int AFlush (int argc, XChar **argv); int ABreak (int argc, XChar **argv); int AFill (int argc, XChar **argv); int ANofill (int argc, XChar **argv); int AAdjust (int argc, XChar **argv); int ANoAdjust (int argc, XChar **argv); int ACenter (int argc, XChar **argv); int ASpacing (int argc, XChar **argv); int ALineSpacing (int argc, XChar **argv); int ASpace (int argc, XChar **argv); int ASaveSpace (int argc, XChar **argv); int AOutputSpace (int argc, XChar **argv); int ANoSpace (int argc, XChar **argv); int ALineLength (int argc, XChar **argv); int AIndent (int argc, XChar **argv); int ATempIndent (int argc, XChar **argv); int ADefineMacro (int argc, XChar **argv); int AAppendMacro (int argc, XChar **argv); int AAliasMacro (int argc, XChar **argv); int ADefineString (int argc, XChar **argv); int AAppendString (int argc, XChar **argv); int ARenameName (int argc, XChar **argv); int ARemoveNames (int argc, XChar **argv); int ADiversion (int argc, XChar **argv); int AAppendDiversion (int argc, XChar **argv); XChar *CurrentDiversion (void); int AEndMacro (int argc, XChar **argv); int AInputTrap (int argc, XChar **argv); int ADefineRegister (int argc, XChar **argv); int AAliasRegister (int argc, XChar **argv); int ARegisterFormat (int argc, XChar **argv); int ATabStops (int argc, XChar **argv); int ASetTabChar (int argc, XChar **argv); int ASetLeaderChar (int argc, XChar **argv); int ASetFieldChars (int argc, XChar **argv); int ASetEscape (int argc, XChar **argv); int ANoEscape (int argc, XChar **argv); int ALigature (int argc, XChar **argv); int AUnderline (int argc, XChar **argv); int ACUnderline (int argc, XChar **argv); int AUnderlineFont (int argc, XChar **argv); int ASetControl (int argc, XChar **argv); int ASetControl2 (int argc, XChar **argv); int ATransliterate (int argc, XChar **argv); int AHyphenation (int argc, XChar **argv); int ASetHyphenChar (int argc, XChar **argv); int AHyphenWords (int argc, XChar **argv); int ATitle (int argc, XChar **argv); int APageNumChar (int argc, XChar **argv); int ATitleLength (int argc, XChar **argv); int ALineNumbering (int argc, XChar **argv); int ANoNumbering (int argc, XChar **argv); int AEnvironment (int argc, XChar **argv); int AExit (int argc, XChar **argv); int AAbort (int argc, XChar **argv); int APushFile (int argc, XChar **argv); int APushMacroFile (int argc, XChar **argv); int AShiftArguments (int argc, XChar **argv); int ASwitchFile (int argc, XChar **argv); int ASetCompatibility (int argc, XChar **argv); int AEcho (int argc, XChar **argv); int AIgnore (int argc, XChar **argv); int ASpecialChar (int argc, XChar **argv); int APushStr (int argc, XChar **argv); int AEol (int argc, XChar **argv); int AWriteControl (int argc, XChar **argv); int AWriteText (int argc, XChar **argv); int AWriteSpecial (int argc, XChar **argv); int ADebugFlag (int argc, XChar **argv); int ADumpMacro (int argc, XChar **argv); int ADumpBadRequests (int argc, XChar **argv); int ADumpInputStack (int argc, XChar **argv); Param InterpretParam (XChar *s, Param defValue); int InterpretCharParam (XChar *s, int defValue); void SetPageLength (Param val); void SetCFA (Param nCenter, Param nFill, Param nAdjust, Param nAdjMode); void SetUnderline (Param ul, Param cul); void SetFont (XChar *name); XChar *GetFontName (XChar *p); XChar *GetFontNameBySlot (Param pos); void SetFontNameBySlot (Param pos, XChar *name); void SetRegisterFormat (Register *rp, XChar *format); XChar *FormatRegister (Register *rp); Param GetRegisterValue (XChar *name); void SetRegisterValue (XChar *name, Param value); Param StrGetRegisterValue (char *name); void StrSetRegisterValue (char *name, Param value); void SetSize (Param val); void SetSpaceSize (Param val); void SetOffset (Param val); void SetSpacing (Param val); void SetLineSpacing (Param val); void SetLineLength (Param val); void SetIndent (Param val); void SetTempIndent (Param val); void SetHyphenation (Param val); void SetTitleLength (Param val); void SetPageNumber (Param val); void SetTabStops (Param n, Param *pos, char *type); Param SetCompatMode (Param newCompat); void InitEnvironments (void); void PushEnvironment (XChar *name); void PopEnvironment (void); XChar *CurrentEnvironmentName (void); void RenameName (Name *nd, XChar *name); Name *NewName (XChar *name, Object *op, short type); Request *NewRequest (XChar *name); Macro *NewMacro (XChar *name); Register *NewRegister (XChar *name, Param initial, Param increment, XChar *format, short readonly); Register *StrNewRegister (char *name, Param initial, Param increment, char *format, short readonly); Name *LookupName (XChar *name, short type); Request *LookupRequest (XChar *name); Macro *LookupMacro (XChar *name); Register *LookupRegister (XChar *name); void RemoveNamedObject (XChar *name, short numReg); void GrabObject (Object *op); void ReleaseObject (Object *op); SpChar *NewSpChar (XChar *name, XChar *value); SpChar *LookupSpCharByName (XChar *name); SpChar *LookupSpCharByCode (XChar code); void CopyMode (int onoff); void ResumeInput (void); short ILevel (void); char *FileInfo (void); void DumpInputStack (void); char *FindMacroFile (char *name); int SwitchFile (char *name); int PushFile (char *name); int PushMacro (XChar *s, int argc, XChar *argv[]); int PushAnonString (XChar *s, short pauseAfter); void ShiftMacroArguments (short n); XChar ChPeek (void); XChar ChIn (void); void UnChIn (XChar c); void InitTransliterate (void); void Transliterate (int in, XChar out); void Break (void); void ControlOut (char *s); void CommentOut (char *s); void SpecialTextOut (char *s); void TextXStrOut (XChar *s); void TextXChOut (XChar c); void TextStrOut (char *s); void TextChOut (int c); void FlushOText (void); void StrOut (char *s); void ChOut (int c); int AllowOutput (int yesno); void SkipWhite (void); void SkipToEol (void); XChar ToEsc (XChar c); XChar FromEsc (XChar c); int Esc (XChar c); int Special (XChar c); int Eol (XChar c); int Sign (XChar c); int White (XChar c); int WhiteOrEol (XChar c); int UnitChar (XChar c); int Digit (XChar c); int EmptyArg (XChar *arg); int NumericArg (XChar *arg); int AsciiStr (XChar *s); Param ToBU (double n, int u); double FromBU (Param n, int u); XChar *XStrAlloc (XChar *xstr); XChar *XStrCpy (XChar *xdst, XChar *xsrc); XChar *XStrNCpy (XChar *xdst, XChar *xsrc, long n); XChar *XStrCat (XChar *xdst, XChar *xsrc); int XStrCmp (XChar *xstr1, XChar *xstr2); int XStrNCmp (XChar *xstr1, XChar *xstr2, long n); int XStrLen (XChar *xstr); char *XCharToStr (XChar xc); char *XStrToStr (XChar *xstr); XChar *StrToXStr (char *str); Param GetPid (void); extern int troff; extern Param resolution; extern int allowInput; extern XChar escChar; extern int doEscapes; extern int inCharTest; extern XChar ctrlChar; extern XChar nbCtrlChar; extern XChar curCtrlChar; extern XChar fieldDelimChar; extern XChar fieldPadChar; extern int fieldDelimCount; extern XChar optHyphenChar; extern XChar tabChar; extern XChar leaderChar; extern long debug; extern Param compatMode; extern short writeLineInfo; extern short dumpBadReq; extern int needSpace; extern int inContinuation; extern int ifLevel; extern int ifResult; extern XChar fontTab[maxFonts][maxFontNameLen]; extern XChar curFont[]; extern XChar prevFont[]; extern XChar *itMacro; extern Param itCount; extern XChar *endMacro; extern Param centerCount; extern Param ulCount; extern Param cUlCount; extern Param fillMode; extern Param adjMode; extern Param adjust; extern Param curSize; extern Param prevSize; extern Param curSpaceSize; extern Param curVSize; extern Param prevVSize; extern Param curLineSpacing; extern Param prevLineSpacing; extern Param curIndent; extern Param prevIndent; extern Param curTempIndent; extern Param curLineLen; extern Param prevLineLen; extern Param curOffset; extern Param prevOffset; extern Param curPageLen; extern Param curPageNum; extern Param curHyphenMode; extern Param pageNumChar; extern Param curTitleLen; extern Param prevTitleLen; extern Param curTabCount; extern Param tabPos[]; extern char tabType[]; extern XChar lastCharRead; ; XChar eTabChar; XCtroffcvt-1.04/h/tcunix.h010064400017710000151000000003040626662671100167400ustar00junkyarddatamgmt00000400000027/* * Library functions for UNIX versions of translators */ void UnixSetProgPath (char *path); FILE *UnixOpenLibFile (char *file, char *mode); FILE *UnixOpenMacroFile (char *file, char *mode); troffcvt-1.04/h/tcread.h010064400017710000151000000076510634113077000166710ustar00junkyarddatamgmt00000400000027/* * tcread.h -- troffcvt reader header file */ #ifndef bufSiz #define bufSiz 1024 #endif /* * Return pointer to new element of type t, or NULL * memmgr.h should be included in any source file that makes * use of this. */ #define New(t) ((t *) Alloc ((int) sizeof (t))) #if defined(SYSV) || defined(SVR4) #define index strchr #endif /* * How to add a new control or special text keyword: * * 1) #define it below somewhere. * 2) Add it to the appropriate lookup table in r-read.c. If it's * a control keyword, add it to the arg count table in r-read.c. * 3) Put it in the appropriate switch statements in your application, * and add code to take whatever action is necessary when it occurs. */ #define tcrEOF 0 /* eof on input */ #define tcrControl 1 /* control word */ #define tcrText 2 /* literal text char */ #define tcrSText 3 /* special text */ /* * Control class major numbers */ #define tcrCUnknown 0 #define tcrComment 1 #define tcrSetupBegin 2 #define tcrSetupEnd 3 #define tcrResolution 4 #define tcrPass 5 #define tcrInputLine 6 #define tcrOther 7 #define tcrPointSize 10 #define tcrSpaceSize 11 #define tcrConstantWidth 12 #define tcrNoConstantWidth 13 #define tcrEmbolden 14 #define tcrSEmbolden 15 #define tcrFont 16 #define tcrPageLength 20 #define tcrBeginPage 21 #define tcrPageNumber 22 #define tcrOffset 23 #define tcrNeed 24 #define tcrMark 25 #define tcrBreak 30 #define tcrCFA 31 /* CFA = center, fill, adjust */ #define tcrNofill 0 #define tcrCenter 1 #define tcrAdjFull 2 #define tcrAdjLeft 3 #define tcrAdjRight 4 #define tcrAdjCenter 5 #define tcrBreakSpread 32 #define tcrSpacing 40 #define tcrLineSpacing 41 #define tcrSpace 42 #define tcrExtraSpace 43 #define tcrLineLength 50 #define tcrIndent 51 #define tcrTempIndent 52 #define tcrDiversionBegin 60 #define tcrDiversionAppend 61 #define tcrDiversionEnd 62 #define tcrResetTabs 70 #define tcrFirstTab 71 #define tcrNextTab 72 #define tcrTabChar 73 #define tcrLeaderChar 74 #define tcrUnderline 80 #define tcrNoUnderline 81 #define tcrCUnderline 82 #define tcrULineFont 83 #define tcrMotion 90 #define tcrBeginOverstrike 100 #define tcrOverstrikeEnd 101 #define tcrBracketBegin 102 #define tcrBracketEnd 103 #define tcrZeroWidth 104 #define tcrLine 105 #define tcrHyphenate 110 #define tcrTitleLength 120 #define tcrTitleBegin 121 #define tcrTitleEnd 122 #define tcrTableBegin 130 #define tcrTableEnd 131 #define tcrColumnInfo 132 #define tcrRowBegin 133 #define tcrRowEnd 134 #define tcrRowLine 135 #define tcrCellInfo 136 #define tcrCellBegin 137 #define tcrCellEnd 138 #define tcrCellLine 139 #define tcrEmptyCell 140 #define tcrSpannedCell 141 /* * Special text major numbers. The only ones explicitly * assigned numbers are those built into troffcvt, for the * most part. */ #define tcrSTUnknown 0 #define tcrBackslash 1 #define tcrAtSign 2 #define tcrLSglQuote 3 #define tcrRSglQuote 4 #define tcrLDblQuote 5 #define tcrRDblQuote 6 #define tcrZeroSpace 7 #define tcrTwelfthSpace 8 #define tcrSixthSpace 9 #define tcrDigitSpace 10 #define tcrHardSpace 11 #define tcrMinus 12 #define tcrGraveAccent 13 #define tcrAcuteAccent 14 #define tcrBackspace 15 #define tcrOptHyphen 16 #define tcrTab 17 #define tcrLeader 18 #define tcrFieldBegin 19 #define tcrFieldEnd 20 #define tcrFieldPad 21 #define tcrBold 0x01 #define tcrItal 0x02 typedef struct TCRFont TCRFont; /* font information */ struct TCRFont { char *tcrTroffName; /* font's troff name */ char *tcrTypeFace; /* typeface (font family) */ long tcrAtts; /* font attributes */ int tcrFontNum; /* font number */ TCRFont *nextTCRFont; /* next font in list */ }; void TCRInit (void); int TCRGetToken (void); int TCRGetLine (char *buf, int size, FILE *f); int TCRReadFonts (char *filename); TCRFont *TCRLookupFont (char *fontname); extern TCRFont *tcrFontList; extern int tcrClass; extern int tcrMajor; extern int tcrMinor; extern int tcrArgc; extern char *tcrArgv[]; extern long tcrLineNum; troffcvt-1.04/h/tcmac.h010064400017710000151000000124000626662671100165150ustar00junkyarddatamgmt00000400000027/* * tc-mac.h */ /* * troffcvt folder name in Preferences folder */ #define tcLibFolderName "\ptroffcvt" #define docType 'TEXT' /* default file type */ #define docCreator 'ttxt' /* default output/error file creator */ /* * Required resource numbers */ #define aboutAlrtRes 1000 /* "About" alert */ #define msgeAlrtRes 1001 /* general message alert */ #define quitAlrtRes 1002 /* quit confirmation alert */ #define whatStringRes 1000 /* "what application does" string */ #define fileMenuRes 1000 /* File menu */ #define editMenuRes 1001 /* Edit menu */ #define statusWindRes 1000 /* status window */ #define logWindRes 1001 /* log window */ #define helpWindRes 1002 /* help window */ /* * Optional resource numbers */ #define helpTextRes 1000 /* help window text */ #define acurRes 128 /* animated cursor info */ typedef struct AppState AppState; struct AppState { short documentsProcessed; Boolean processingDocument; Boolean quitRequestPending; Boolean quitAfterDocsProcessed; FSSpec fssInput; FSSpec fssOutput; long inputSize; }; /* * Structure used by host application to pass information to MacintoshWrapper() * so it knows how to call writer code, and for extending the basic Macintosh * interface elements. * * The file suffixes should be Pascal strings and must be non-nil. */ typedef struct AppInfo AppInfo; struct AppInfo { void (*pMenuInit) (); /* application-specific menu setup */ void (*pMenuAdjust) (); /* application-specific menu adjustment */ void (*pWriterInit) (); /* writer one-time initialization */ void (*pWriterEnd) (); /* writer one-time cleanup */ int (*pWriterBeginFile) (); /* per-file initialization */ void (*pWriterEndFile) (); /* per-file cleanup */ void (*pPrefs) (); /* function to handle Preferences dialog */ Str31 inputSuffix; /* input file suffix to strip if present */ Str31 outputSuffix; /* output file suffix for autonaming */ Str31 errorSuffix; /* error file suffix for autonaming */ long outputCreator; /* creator of output files */ long errorCreator; /* creator of error files */ int flags; /* flags to control wrapper behavior */ }; /* * If persistentStatus is set, the status window is always visible. Otherwise, * it's visible only during file translations. * * If prefsInEditMenu is set, the wrapper adds a gray line and a * "Preferences..." item to the bottom of the Edit menu, and calls the pPrefs * function in the AppInfo structure to process the preferences dialog. * * If usesOutputFile is set, it means the translator expects to write to * an output file. If the flag is set, the autoNameOutputFile and * autoOpenOutputFile flags are also examined (they're ignored if * usesOutputFile isn't set). * - If autoNameOutputFile is set, the output filename is automatically * generated, and the user can't override it. If the flag isn't set, the * name is still generated, but used as the suggested default that the user * can override by means of the standard file dialog that is presented. * - If autoOpenOutputFile is set, the output file is opened by the wrapper on * stdout. Otherwise, the writer is expected to open the output file itself. * * usesErrorFile and autoNameErrorFile are similar to autoNameOutputFile * and autoOpenOutputFile, but they apply to the error file. There is no * autoOpenErrorFile; * if an error file name is used, the wrapper always * opens it (on stderr). * * The writer can call ETMMsg()/ETMPanic() even if no error file is created, * because diagnostic output will go the log window anyway. * * If the autoname flags are set, the file suffixes in the AppInfo structure * are used for creating the names. */ #define persistentStatus 0x01 #define prefsInEditMenu 0x02 #define usesOutputFile 0x04 #define autoNameOutputFile 0x08 #define autoOpenOutputFile 0x10 #define usesErrorFile 0x20 #define autoNameErrorFile 0x40 #define TstAppFlag(ap,mask) ((((ap)->flags) & (mask)) == (mask)) /* non-prototyped (because passed to troffcvt lib as callback) */ FILE *MacOpenLibFile (); /* prototyped */ /* fileops.c */ void MakeDirPath (long dirID, short vRefNum, StringPtr path); void MakeCFilePath (StringPtr dir, StringPtr basename, char *file); char *AppFolderPath (void); char *PrefsFolderPath (void); Boolean SelectInputFile (FSSpec *fss, OSType type); Boolean SelectOutputFile (FSSpec *fss, StringPtr fileType); void MakeOutputFileName (StringPtr inName, StringPtr inSuffix, StringPtr outName, StringPtr outSuffix); /* aevents.c */ void AppleEventsInit (void); short PendingDocuments (void); void AddDocument (FSSpec *fss); Boolean RemoveDocument (FSSpec *fss); /* helpwind.c */ void HelpWindow (void); /* logwind.c */ void LogWindInit (void); /* prefs.c */ Boolean ReadPrefs (StringPtr name, char **p, long *size); Boolean WritePrefs (StringPtr name, OSType creator, char *p, long size); /* statuswind.c */ void StatusWindInit (void); void StatusWindUpdate (void); /* misc.c */ StringPtr ApplicationName (void); void PStrCpy (StringPtr dst, StringPtr src); void PStrCat (StringPtr dst, StringPtr src); void PStrInsert (StringPtr dst, StringPtr src); Boolean PStrEqual (StringPtr s1, StringPtr s2); /* wrapper.c */ void MacintoshWrapper (AppInfo *ap); void RequestQuit (void); extern AppState *appState; extern AppInfo *appInfo; troffcvt-1.04/h/tcgen.h010064400017710000151000000002140626662671100165260ustar00junkyarddatamgmt00000400000027# ifndef bufSiz # define bufSiz 1024 # endif void TCRSetOpenLibFileProc (FILE *(proc) ()); FILE *TCROpenLibFile (char *file, char *mode); troffcvt-1.04/h/tctbl.h010066400017710000151000000011520634014070100165210ustar00junkyarddatamgmt00000400000027/* * Stuff for handling tblcvt-related troffcvt output */ #define tblMaxCol 200 /* should be enough...! */ /* * indices of \table-begin arguments */ #define tblRowsArg 0 #define tblColsArg 1 #define tblHdrRowsArg 2 #define tblAlignArg 3 #define tblExpandArg 4 #define tblBoxArg 5 #define tblAllBoxArg 6 #define tblDblBoxArg 7 /* * indices of \table-column-info arguments */ #define colWidthArg 0 #define colSepArg 1 #define colEqWidthArg 2 /* * indices of \table-cell-info arguments */ #define cellTypeArg 0 #define cellVSpanArg 1 #define cellHSpanArg 2 #define cellVAdjustArg 3 #define cellBorderArg 4 troffcvt-1.04/lib/004077500017710000151000000000000634140161000155635ustar00junkyarddatamgmt00000400000027troffcvt-1.04/lib/Imakefile010064400017710000151000000004560626662671000174140ustar00junkyarddatamgmt00000400000027 GENSRCS = libfile.c GENOBJS = libfile.o READERSRCS = r-font.c r-read.c READEROBJS = r-font.o r-read.o SRCS = $(GENSRCS) $(READERSRCS) NormalLibraryObjectRule() BuildNormalLibrary(tcgen,$(GENSRCS),$(GENOBJS)) BuildNormalLibrary(tcread,$(READERSRCS),$(READEROBJS)) DependTarget() troffcvt-1.04/lib/Makefile010066400017710000151000000301150634136770500172400ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./lib # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile GENSRCS = libfile.c GENOBJS = libfile.o READERSRCS = r-font.c r-read.c READEROBJS = r-font.o r-read.o SRCS = $(GENSRCS) $(READERSRCS) .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libtcgen.a libtcgen.a: $(GENOBJS) $(RM) $@ $(AR) $@ $(GENOBJS) clean:: $(RM) libtcgen.a lint:: lint.libtcgen.a lint.libtcgen.a: $(LINT) $(LINTFLAGS) $(GENSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.libtcgen.a"' to "lint sources for libtcgen.a help_aux:: @echo "'make "libtcgen.a"' to "build the libtcgen.a library all:: libtcread.a libtcread.a: $(READEROBJS) $(RM) $@ $(AR) $@ $(READEROBJS) clean:: $(RM) libtcread.a lint:: lint.libtcread.a lint.libtcread.a: $(LINT) $(LINTFLAGS) $(READERSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.libtcread.a"' to "lint sources for libtcread.a help_aux:: @echo "'make "libtcread.a"' to "build the libtcread.a library depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE libfile.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h libfile.o: .././h/tcgen.h r-font.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h r-font.o: /usr/include/ctype.h /usr/include/string.h /usr/local/include/etm.h r-font.o: /usr/local/include/memmgr.h /usr/local/include/tokenscan.h r-font.o: .././h/tcgen.h .././h/tcread.h r-read.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h r-read.o: /usr/include/ctype.h /usr/local/include/etm.h r-read.o: /usr/local/include/memmgr.h /usr/local/include/tokenscan.h r-read.o: .././h/tcread.h ENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Editroffcvt-1.04/lib/math.c010064400017710000151000000006340626662671000166760ustar00junkyarddatamgmt00000400000027/* math.c - stuff to compensate for silliness about where math routines are declared. */ # include # if defined(__STDC_) || defined(THINK_C) /* for atoi()/atol()/atof() */ # include # else # include # endif # include "troffcvt.h" double Atof (s) char *s; { return (atof (s)); } long Atol (s) char *s; { return (atol (s)); } int Atoi (s) char *s; { return (atoi (s)); } troffcvt-1.04/lib/r-font.c010064400017710000151000000042620630146204600171410ustar00junkyarddatamgmt00000400000027/* * r-font.c -- troffcvt reader font machinery. */ # include # include # ifndef STRING_H # define STRING_H # endif # include STRING_H # include "etm.h" # include "memmgr.h" # include "tokenscan.h" # include "tcgen.h" # include "tcread.h" TCRFont *tcrFontList = (TCRFont *) NULL; /* * Read font information file. Format of lines is * * troff-font-name typeface attributes * * attributes is empty (plain), or some combination of "italic" or "bold", * indicating what style attributes the font has in relation to the plain * font for the typeface. E.g., * * R Times * I Times italic * B Times bold * BI Times bold italic */ int TCRReadFonts (char *filename) { FILE *f; char buf[bufSiz]; TCRFont *fp, *fp2; char *tName; char *face; char *p; static int fnum = 0; if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) return (0); while (TCRGetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') /* skip comments */ continue; TSScanInit (buf); if ((tName = TSScan ()) == (char *) NULL || (face = TSScan ()) == (char *) NULL) continue; fp = New (TCRFont); fp->tcrTroffName = StrAlloc (tName); fp->tcrTypeFace = StrAlloc (face); fp->tcrAtts = 0; /* start with "plain" */ while ((p = TSScan ()) != NULL) { if (strcmp (p, "italic") == 0) fp->tcrAtts |= tcrItal; else if (strcmp (p, "bold") == 0) fp->tcrAtts |= tcrBold; else { ETMMsg ("%s: unknown attribute for font %s: %s", "TCRReadFonts", fp->tcrTroffName, p); } } /* * See if this is first font in family and assign * new number if so; use existing number otherwise. */ for (fp2 = tcrFontList; fp2 != (TCRFont *) NULL; fp2 = fp2->nextTCRFont) { if (strcmp (fp2->tcrTypeFace, face) == 0) break; } if (fp2 == (TCRFont *) NULL) fp->tcrFontNum = ++fnum; else fp->tcrFontNum = fp2->tcrFontNum; fp->nextTCRFont = tcrFontList; tcrFontList = fp; } (void) fclose (f); return (1); } TCRFont * TCRLookupFont (char *fontname) { TCRFont *fp; for (fp = tcrFontList; fp != (TCRFont *) NULL; fp = fp->nextTCRFont) { if (strcmp (fontname, fp->tcrTroffName) == 0) break; } return (fp); /* NULL if not found */ } troffcvt-1.04/lib/r-read.c010064400017710000151000000206530634113075400171120ustar00junkyarddatamgmt00000400000027/* * Probably should install a simpler scanner. * * reader.c -- Tokenizes input stream, which is assumed to have been * produced by troffcvt. * * tcrArgv[] points into cstBuf or ptBuf and its elements should * be considered READ-ONLY. * * The reader turns off the tokenscan escaping mechanism, so any application * using both the reader and tokenscan routines itself should be aware of * that and modify/restore the scanner accordingly. */ #include #include #include "etm.h" #include "memmgr.h" #include "tokenscan.h" #include "tcread.h" # define maxArg 10 static void LookupInit (void); static void Lookup (char *s, int class); static int Hash (char *s); static int prevChar = '\n'; int tcrClass; int tcrMajor; int tcrMinor; char *tcrArgv[maxArg]; int tcrArgc = 0; long tcrLineNum = 0; /* * Control and special text lines are read into this buffer, and * tcrArgv[] is set up to point at the words in the line. * ptBuf is used for single-char plain text tokens. */ static char cstBuf[bufSiz]; static char ptBuf[2]; /* * Initialize the reader. This may be called multiple times, * to read multiple files. Each one is assumed open on stdin. */ void TCRInit (void) { TSScanner scanner; char *scanEscape; tcrClass = tcrEOF; tcrArgc = 0; tcrArgv[0] = (char *) NULL; tcrLineNum = 0; /* initialize lookup tables */ LookupInit (); /* * Turn off backslash escape mechanism while parsing * input. Perhaps it should be restored later, but where? * (There's no TCREnd() call.) */ TSGetScanner (&scanner); scanEscape = scanner.scanEscape; scanner.scanEscape = ""; TSSetScanner (&scanner); } /* * Read input stream to find next token. If stream is at * beginning of line (prevChar = '\n') look for control or special * text line, read the whole thing in one swoop and parse it apart * to set the tcrArgv[] vector. Otherwise the character is just * plain text, which becomes its own token. */ int TCRGetToken (void) { int c; char *p; if ((c = getchar ()) == EOF) return (tcrClass = tcrEOF); if (prevChar != '\n' || (c != '\\' && c != '@')) /* plain text */ { ptBuf[0] = c; ptBuf[1] = '\0'; tcrArgv[tcrArgc = 0] = ptBuf; tcrMajor = prevChar = c; return (tcrClass = tcrText); } /* control or special text */ if (c == '\\') tcrClass = tcrControl; else tcrClass = tcrSText; cstBuf[0] = c; if (!TCRGetLine (cstBuf+1, (int) sizeof (cstBuf)-1, stdin)) cstBuf[1] = '\0'; prevChar = '\n'; TSScanInit (cstBuf); tcrArgc = 0; while ((p = TSScan ()) != (char *) NULL) { /* \comment and \pass are special cases */ if (tcrArgc == 0 && (strcmp (p, "\\comment") == 0 || strcmp (p, "\\pass") == 0)) { tcrArgv[tcrArgc++] = p; tcrArgv[tcrArgc++] = TSGetScanPos (); break; } if (tcrArgc + 1 >= maxArg) { ETMMsg ("too many arguments on %s line", tcrArgv[0]); break; } tcrArgv[tcrArgc++] = p; } tcrArgv[tcrArgc] = (char *) NULL; if (tcrArgc == 0) ETMPanic ("trash line found"); Lookup (tcrArgv[0], tcrClass); return (tcrClass); } /* * Read a line from a file, strip any cr, lf or crlf from the * end. Return zero for EOF, non-zero otherwise. */ int TCRGetLine (char *buf, int size, FILE *f) { int len; if (fgets (buf, size, f) == (char *) NULL) return (0); if ((len = strlen (buf)) > 0 && buf[len-1] == '\n') buf[len-1] = '\0'; if ((len = strlen (buf)) > 0 && buf[len-1] == '\r') buf[len-1] = '\0'; return (1); } /* ---------------------------------------------------------------------- */ /* * Symbol lookup routines */ typedef struct TCRKey TCRKey; struct TCRKey { int major; /* major number */ int minor; /* minor number */ char *str; /* symbol name */ int hash; /* symbol name hash value */ }; /* * A minor number of -1 means the token has no minor number * (all valid minor numbers are >= 0). */ static TCRKey tcrControlKey[] = { tcrComment, -1, "comment", 0, tcrSetupBegin, -1, "setup-begin", 0, tcrSetupEnd, -1, "setup-end", 0, tcrResolution, -1, "resolution", 0, tcrPass, -1, "pass", 0, tcrInputLine, -1, "line", 0, tcrOther, -1, "other", 0, tcrBreak, -1, "break", 0, tcrFont, -1, "font", 0, tcrPointSize, -1, "point-size", 0, tcrSpacing, -1, "spacing", 0, tcrLineSpacing, -1, "line-spacing", 0, tcrOffset, -1, "offset", 0, tcrIndent, -1, "indent", 0, tcrTempIndent, -1, "temp-indent", 0, tcrLineLength, -1, "line-length", 0, tcrPageLength, -1, "page-length", 0, tcrPageNumber, -1, "page-number", 0, tcrSpace, -1, "space", 0, tcrCFA, tcrCenter, "center", 0, tcrCFA, tcrNofill, "nofill", 0, tcrCFA, tcrAdjFull, "adjust-full", 0, tcrCFA, tcrAdjLeft, "adjust-left", 0, tcrCFA, tcrAdjRight, "adjust-right", 0, tcrCFA, tcrAdjCenter, "adjust-center", 0, tcrUnderline, -1, "underline", 0, tcrCUnderline, -1, "cunderline", 0, tcrNoUnderline, -1, "nounderline", 0, tcrULineFont, -1, "underline-font", 0, tcrBreakSpread, -1, "break-spread", 0, tcrExtraSpace, -1, "extra-space", 0, tcrLine, -1, "line", 0, tcrMark, -1, "mark", 0, tcrMotion, -1, "motion", 0, tcrBracketBegin, -1, "bracket-begin", 0, tcrBracketEnd, -1, "bracket-end", 0, tcrBeginOverstrike, -1, "overstrike-begin", 0, tcrOverstrikeEnd, -1, "overstrike-end", 0, tcrBeginPage, -1, "begin-page", 0, tcrZeroWidth, -1, "zero-width", 0, tcrSpaceSize, -1, "space-size", 0, tcrConstantWidth, -1, "constant-width", 0, tcrNoConstantWidth, -1, "noconstant-width", 0, tcrNeed, -1, "need", 0, tcrEmbolden, -1, "embolden", 0, tcrSEmbolden, -1, "embolden-special", 0, tcrResetTabs, -1, "reset-tabs", 0, tcrFirstTab, -1, "first-tab", 0, tcrNextTab, -1, "next-tab", 0, tcrHyphenate, -1, "hyphenate", 0, tcrDiversionBegin, -1, "diversion-begin", 0, tcrDiversionEnd, -1, "diversion-end", 0, tcrDiversionAppend, -1, "diversion-append", 0, tcrTabChar, -1, "tab-char", 0, tcrLeaderChar, -1, "leader-char", 0, tcrTitleLength, -1, "title-length", 0, tcrTitleBegin, -1, "title-begin", 0, tcrTitleEnd, -1, "title-end", 0, tcrTableBegin, -1, "table-begin", 0, tcrTableEnd, -1, "table-end", 0, tcrColumnInfo, -1, "table-column-info", 0, tcrRowBegin, -1, "table-row-begin", 0, tcrRowEnd, -1, "table-row-end", 0, tcrRowLine, -1, "table-row-line", 0, tcrCellInfo, -1, "table-cell-info", 0, tcrCellBegin, -1, "table-cell-begin", 0, tcrCellEnd, -1, "table-cell-end", 0, tcrCellLine, -1, "table-cell-line", 0, tcrEmptyCell, -1, "table-empty-cell", 0, tcrSpannedCell, -1, "table-spanned-cell", 0, 0, -1, (char *) NULL, 0 }; static TCRKey tcrSTextKey[] = { tcrBackslash, -1, "backslash", 0, tcrAtSign, -1, "at", 0, tcrLSglQuote, -1, "quoteleft", 0, tcrRSglQuote, -1, "quoteright", 0, tcrLDblQuote, -1, "quotedblleft", 0, tcrRDblQuote, -1, "quotedblright", 0, tcrZeroSpace, -1, "zerospace", 0, tcrTwelfthSpace, -1, "twelfthspace", 0, tcrSixthSpace, -1, "sixthspace", 0, tcrDigitSpace, -1, "digitspace", 0, tcrHardSpace, -1, "hardspace", 0, tcrMinus, -1, "minus", 0, tcrGraveAccent, -1, "grave", 0, tcrAcuteAccent, -1, "acute", 0, tcrBackspace, -1, "backspace", 0, tcrOptHyphen, -1, "opthyphen", 0, tcrTab, -1, "tab", 0, tcrLeader, -1, "leader", 0, tcrFieldBegin, -1, "fieldbegin", 0, tcrFieldEnd, -1, "fieldend", 0, tcrFieldPad, -1, "fieldpad", 0, 0, -1, (char *) NULL, 0 }; /* * Initialize lookup table hash values. Only need to do this once. */ static void LookupInit (void) { static int inited = 0; TCRKey *rp; if (inited == 0) { for (rp = tcrControlKey; rp->str != (char *) NULL; rp++) rp->hash = Hash (rp->str); for (rp = tcrSTextKey; rp->str != (char *) NULL; rp++) rp->hash = Hash (rp->str); ++inited; } } /* * Determine major and minor number of control token. If it's * not found, the major number turns into tcr{C,ST}Unknown. */ static void Lookup (char *s, int class) { TCRKey *rp; int hash; ++s; /* skip over the leading \ character */ hash = Hash (s); if (class == tcrControl) { rp = tcrControlKey; tcrMajor = tcrCUnknown; } else if (class == tcrSText) { rp = tcrSTextKey; tcrMajor = tcrSTUnknown; } else ETMPanic ("Lookup: class = %d", class); for (/* empty */; rp->str != (char *) NULL; rp++) { if (hash == rp->hash && strcmp (s, rp->str) == 0) { tcrMajor = rp->major; tcrMinor = rp->minor; break; } } } /* * Compute hash value of symbol */ static int Hash (char *s) { char c; int val = 0; while ((c = *s++) != '\0') val += (int) c; return (val); } ------------------------------------------------ */ /* * Symbol lookup routines */troffcvt-1.04/lib/libfile.c010064400017710000151000000005120626662671000173460ustar00junkyarddatamgmt00000400000027/* * Open a library file. */ #include #include "tcgen.h" static FILE *(*libFileOpen) () = NULL; void TCRSetOpenLibFileProc (FILE *(*proc) ()) { libFileOpen = proc; } FILE * TCROpenLibFile (char *file, char *mode) { if (libFileOpen == NULL) return ((FILE *) NULL); return ((*libFileOpen) (file, mode)); } troffcvt-1.04/libmac/004077500017710000151000000000000627103501700162525ustar00junkyarddatamgmt00000400000027troffcvt-1.04/libmac/m-getpid.c010064400017710000151000000004060626662671100201320ustar00junkyarddatamgmt00000400000027/* * Fake routine to return "process id" on Macintosh * * Actually, since System 7 is required for the applications now, * perhaps a real process id can be returned. */ # include # include "troffcvt.h" Param GetPid () { return ((Param) 0); } troffcvt-1.04/libunix/004077500017710000151000000000000634140161000164675ustar00junkyarddatamgmt00000400000027troffcvt-1.04/libunix/Imakefile010064400017710000151000000004600630224334700203030ustar00junkyarddatamgmt00000400000027SRCS = u-libfile.c u-macfile.c u-getpid.c OBJS = u-libfile.o u-macfile.o u-getpid.o XCOMM any special -D's or other flags for compiling DEFINES = \ -D'PROJLIBDIR="$(PROJLIBDIR)"' \ -D'MACROLIBDIR="$(MACROLIBDIR)"' NormalLibraryObjectRule() BuildNormalLibrary(tcunix,$(SRCS),$(OBJS)) DependTarget() troffcvt-1.04/libunix/Makefile010066400017710000151000000271640634136770600201570ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./libunix # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile SRCS = u-libfile.c u-macfile.c u-getpid.c OBJS = u-libfile.o u-macfile.o u-getpid.o # any special -D's or other flags for compiling DEFINES = \ -D'PROJLIBDIR="$(PROJLIBDIR)"' \ -D'MACROLIBDIR="$(MACROLIBDIR)"' .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: libtcunix.a libtcunix.a: $(OBJS) $(RM) $@ $(AR) $@ $(OBJS) clean:: $(RM) libtcunix.a lint:: lint.libtcunix.a lint.libtcunix.a: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.libtcunix.a"' to "lint sources for libtcunix.a help_aux:: @echo "'make "libtcunix.a"' to "build the libtcunix.a library depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE u-libfile.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h u-libfile.o: /usr/local/include/memmgr.h .././h/tcgen.h .././h/tcunix.h u-macfile.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h u-macfile.o: /usr/local/include/memmgr.h .././h/tcgen.h .././h/tcunix.h u-getpid.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h u-getpid.o: .././h/troffcvt.h troffcvt-1.04/libunix/u-macfile.c010064400017710000151000000014210630224343400204730ustar00junkyarddatamgmt00000400000027/* * u-macfile.c -- file operations for UNIX versions of translators. * * UnixOpenMacroFile () - Open a troff macro file. Looks in the current * directory and the MACROLIBDIR directory. * * Exception: if file is an absolute pathname, look only for file as named. * * Returns NULL if file cannot be found and opened. */ #include #include "memmgr.h" #include "tcgen.h" #include "tcunix.h" FILE * UnixOpenMacroFile (char *file, char *mode) { FILE *f; char buf[bufSiz]; char *p; if ((f = fopen (file, mode)) != (FILE *) NULL) return (f); /* if abolute pathname, give up, else look in library */ if (file[0] == '/') { return ((FILE *) NULL); } sprintf (buf, "%s/%s", MACROLIBDIR, file); f = fopen (buf, mode); /* NULL if it fails */ return (f); } troffcvt-1.04/libunix/u-getpid.c010064400017710000151000000002030626662671100203600ustar00junkyarddatamgmt00000400000027/* * Return UNIX process id */ #include #include "troffcvt.h" Param GetPid (void) { return ((Param) getpid ()); } troffcvt-1.04/libunix/u-libfile.c010064400017710000151000000032630630224323300205040ustar00junkyarddatamgmt00000400000027/* * u-libfile.c -- file operations for UNIX versions of translators. * * UnixOpenLibFile () - Open a library file. Looks in the following * directories: * - Looks in current directory. * - if TROFFCVT_LIB_DIR environment variable is set, looks in directory * named by it. * - Looks in executable program's directory, if UnixSetProgPath() has * been called. * - Looks in compiled-in library directory, LIBDIR. * * Exception: if file is an absolute pathname, look only for file as named. * * Returns NULL if file cannot be found and opened. */ #include #include "memmgr.h" #include "tcgen.h" #include "tcunix.h" extern char *getenv (); static char *progPath = (char *) NULL; void UnixSetProgPath (char *path) { int i, j, n; n = strlen (path); for (j = -1, i = 0; i < n; i++) { if (path[i] == '/') j = i; } if (j < 0) /* no slash found */ { path = "."; j = 1; } if ((progPath = Alloc (j + 1)) != (char *) NULL) { (void) strncpy (progPath, path, j); progPath[j] = '\0'; } } FILE * UnixOpenLibFile (char *file, char *mode) { FILE *f; char buf[bufSiz]; char *p; if ((f = fopen (file, mode)) != (FILE *) NULL) { return (f); } /* if abolute pathname, give up, else look in library */ if (file[0] == '/') { return ((FILE *) NULL); } if ((p = getenv ("TROFFCVT_LIB_DIR")) != (char *) NULL) { sprintf (buf, "%s/%s", p, file); if ((f = fopen (buf, mode)) != (FILE *) NULL) return (f); } if (progPath != (char *) NULL) { sprintf (buf, "%s/%s", progPath, file); if ((f = fopen (buf, mode)) != (FILE *) NULL) return (f); } sprintf (buf, "%s/%s", PROJLIBDIR, file); f = fopen (buf, mode); /* NULL if it fails */ return (f); } troffcvt-1.04/troffcvt/004077500017710000151000000000000634140401100166505ustar00junkyarddatamgmt00000400000027troffcvt-1.04/troffcvt/input.c010064400017710000151000001065340633770525500202020ustar00junkyarddatamgmt00000400000027/* * What does it mean to do .nx inside a macro? * * input.c - input operations * * Comments (\"...) are deleted whenever input is read or reread. * Embedded newlines (\(newline)) are also deleted whenever input * is read, except within comments. * * FChIn(), MChIn(), AChIn() return endOfInput (zero) when input * source is exhausted. FChIn() discards nulls and characters with high * bit set. * * ChIn0() always returns the next character from the input stream, or * endOfInput when there is no more input from any source. * * ChIn() collapses escChar+next char into one XChar value as appropriate * (depending on whether or not copy mode is on). Special character * references (in \(xy format) are also returned as a single XChar value. * * Ugly hack: In copy mode, \\, \t, \a and \. are returned as \, tab, * SOH and ., respectively. If the character is pushed back, there's * no way to determine from looking at the character itself that a \ * character should be pushed back, too. (E.g., if you read a \\, you * get a \; if you push it back, the first \ is lost, which loses a * level of escaping - not good.) The flag escStripped is used to keep * track of whether or not the last character returned by ChIn() had an * escape stripped off, and UnChIn() looks at that flag to be able to * tell whether or not to put it back. This would be a problem if more * than one character were read and pushed back in copy mode. In practice * that doesn't happen, but it's still unattractive. */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "etm.h" #include "memmgr.h" #include "troffcvt.h" #define maxPushChar 32 #define maxMacRecursion 50 #define macroSource 1 #define anonStringSource 2 #define fileSource 3 /* * Macro argument information. This is not part of the MacSrc * structure because one macro can cause another macro to inherit * its own arguments by interpolating it as a string. * * The structure holds a copy of the name under which the macro was * invoked so that \$0 can be implemented. (Must keep a copy rather * that a pointer to a Name structure, since it's possible the macro * will remove itself, which deletes the name from the name list.) * Also maintain an array of the arguments for references to $1..$99. * These are exported out when necessary through the MacroArgument() * function. * * The reference count is set to one when the structure is created, * for a macro invoked as a macro (.xx). If the macro to which the * structure is attached invokes another macro as a string (\*y, * \*(yy, \*[yyy]), the other macro inherits the structure, and the * reference count is incremented. As each macro using the structure * terminates, the count is decremented, and deallocated when the * count reaches zero. */ typedef struct MacArg MacArg; struct MacArg { XChar *mName; /* macro name (\$0) */ XChar mArgc; /* number of arguments */ XChar *mArgv[maxMacroArgs]; /* macro arguments (\$1, \$2, ...) */ short mRefCount; /* no. of macros using this struct */ }; typedef struct MacSrc MacSrc; typedef struct AnonStrSrc AnonStrSrc; typedef struct FileSrc FileSrc; typedef struct Source Source; /* * Information for macro input sources. The structure holds a pointer * to the argument information (including the macro name). It also * maintains the current position within the macro body and a pointer * to the end position. */ struct MacSrc { Object *objPtr; MacArg *mArg; long curPos; long endPos; Source *prevMacSrc; }; struct AnonStrSrc { XChar *anonStr; XChar *curAPtr; }; struct FileSrc { char *fileName; /* name of input file */ FILE *filePtr; /* file descriptor */ int prevChar; /* previous char read from file */ Param inputLine; /* current input line (zero-based) */ }; /* * Input source information structure. * * Each input source specifies the function needed to return the next * character from the source. Input functions must return endOfInput * when they encounter the end of their input source. For example, * MChIn() returns endOfInput when it reaches the end of the macro * definition. * * The sFakeEof member is non-zero if ChIn() should return endOfInput * when the input source is exhausted. This way a source can be pushed * on the stack and the caller can regain control when that source is * finished. To resume reading from any pending input sources, the * caller executes ResumeInput(). */ struct Source { short sType; /* source type */ short sFakeEof; /* return eof when source exhausted? */ XChar (*sChIn) (); /* character input function */ union { MacSrc sMacSrc; AnonStrSrc sAnonStrSrc; FileSrc sFileSrc; } sInfo; # define sMacro sInfo.sMacSrc # define sAnonString sInfo.sAnonStrSrc # define sFile sInfo.sFileSrc Source *sPrev; /* previous input source */ }; static XChar MChIn (void); /* next character from macro */ static XChar AChIn (void); /* next character from anonymous string */ static XChar FChIn (void); /* next character from file */ static XChar ChIn0 (void); /* * Pointers to current input source and most recent macro input source. * Most recent macro is used when references to macro arguments are found * in input sources that occur within macros, e.g., in a file that's .so'd * from within a macro. This way it's not necessary to traverse back * through the input stack to find the macro. */ static Source *curSrc = (Source *) NULL; static Source *curMacSrc = (Source *) NULL; static short returnEof = 0; /* * Pushback buffer. It's a char buffer because pushed-back XChar values are * converted back into char form. (Can't push back XChars because a char * might be parsed initially in non-copy mode, pushed back, and re-read in * copy mode. The character might be interpreted differently in the two * modes.) The input level at which characters are pushed back is remembered * to avoid returning them into the wrong input level. */ static int pushCount = 0; static char pushBuf[maxPushChar]; static char pushLevel[maxPushChar]; /* * inputLevel is the current input level; it's incremented whenever a new * input source begins, and decremented when the source terminates. The * value is the the level of the last char read, not the next char. Thus, * an input call returns the last character of a source, the value is that * source's level. It's not until the next call that EOF on the source is * detected and the level is decremented. */ static int inputLevel = 0; static int copyMode = 0; static int escStripped = 0; /* * Last character read by ChIn(). This is a hack needed by the conditional * processors, which have to push back the last character they read. (These * lines act like "lines with another line after the condition", so putting * the end of line character back on the input fakes input processing out * by making it act as though there was an end of line found for both lines.) * However, if the end of line is endOfInput, it's important not to push back * a newline or it will seem as though there is an extra blank line in the * input. (This can happen if you do 'push-string "some stuff"' with no * newline on the end of "some stuff".) lastCharRead allows endOfInput to * be pushed back if that was the end-of-line character. */ XChar lastCharRead = endOfInput; static void SetInputLineRegisters (Param lineNum) { StrSetRegisterValue (".c", lineNum); StrSetRegisterValue ("c.", lineNum); } /* * Turn copy mode on or off. Turning it on triggers some * horrendously complex shenanighans inside of ChIn(). */ void CopyMode (int onoff) { copyMode = onoff; /* non-zero to turn on */ } /* * Resume any pending input sources. This is called after an input source * has been pushed on the stack such that the "return fake eof" flag is * set. After the input source is exhausted, returnEof will be set and * ChIn() returns endOfInput until ResumeInput() is called. */ void ResumeInput (void) { returnEof = 0; } /* * Return input level, or zero if compatibility mode is enabled. * (When compat mode is on, parsing routines pay no attention to * input level, which is like standard troff. groff uses the input * level to avoid interpreting delimiters in strings, arguments, etc. * as terminating \w'xxx', .if 'x'y', etc. */ short ILevel (void) { return (compatMode ? 0 : inputLevel); } /* * Format a string containing the current input filename and line number. * Return value is the empty string if no input file is known, which is * the case, e.g., while the action files are being read. * * Since the current input source might not be a file, have to look back * through the input stack to find the most recent source that is a file. * * Returns a pointer to a static buffer; caller should make a copy if it * needs to hang on to the return value for a while. */ char * FileInfo (void) { static char buf[bufSiz]; Source *sp; buf[0] = '\0'; sp = curSrc; while (sp != (Source *) NULL) { if (sp->sType == fileSource) { sprintf (buf, "%s (line %ld): ", sp->sFile.fileName, sp->sFile.inputLine); break; } sp = sp->sPrev; } return (buf); } /* * Dump out information about the input stack. */ void DumpInputStack (void) { Source *sp = curSrc; MacArg *ma; int i; ETMMsg ("Input stack:"); if (sp == (Source *) NULL) { ETMMsg ("input stack is empty"); return; } while (sp != (Source *) NULL) { ETMMsg ("----"); switch (sp->sType) { default: ETMMsg ("unknown input type"); break; case fileSource: ETMMsg ("file: %s", sp->sFile.fileName); ETMMsg ("current line: %ld", sp->sFile.inputLine); break; case macroSource: ma = sp->sMacro.mArg; ETMMsg ("macro/string: %s", ma == (MacArg *) NULL ? "(no name)" : XStrToStr (ma->mName)); ETMMsg ("number of arguments: %d", ma == (MacArg *) NULL ? 0 : ma->mArgc); if (ma != (MacArg *) NULL) { for (i = 0; i < ma->mArgc; i++) { ETMMsg ("argument %d: <%s>", i, XStrToStr (ma->mArgv[i])); } } break; case anonStringSource: ETMMsg ("anonymous string"); break; } sp = sp->sPrev; } } static void PrintDebugChar (char type, XChar c) { if (c == endOfInput) ETMMsg ("%c %d ", type, inputLevel); else if (c == lf) ETMMsg ("%c %d ", type, inputLevel); else ETMMsg ("%c %d <%s>", type, inputLevel, XCharToStr (c)); } /* * Find the given file, looking in the directories named by the given * path list (colon-separated list of directories in which to look). * Returns a pointer to a full pathname where the file was found and * can be read, or NULL if the file is not found in any of the directories. * * If the file is an absolute pathname, look only for the file named by * that path. * * Return value is to static buffer. Caller should copy if it needs to * hang onto the value for a while. */ static char * FindFileByPathList (char *file, char *pathList) { static char path[bufSiz]; FILE *f = (FILE *) NULL; char *p; char dir[bufSiz]; int i; if (*file == '/') /* absolute pathname */ { if ((f = fopen (file, "r")) == (FILE *) NULL) return ((char *) NULL); (void) fclose (f); (void) strcpy (path, file); return (path); } if ((p = pathList) == (char *) NULL) return ((char *) NULL); while (*p != '\0') { i = 0; while (*p == ':') /* skip leading separators */ ++p; while (*p != ':' && *p != '\0') /* get next pathname */ dir[i++] = *p++; dir[i] = '\0'; /* terminate pathname */ if (i == 0) /* empty pathname */ continue; sprintf (path, "%s/%s", dir, file); f = fopen (path, "r"); if (f != (FILE *) NULL) /* opened successfully */ { (void) fclose (f); return (path); } } return ((char *) NULL); } /* * Locate a macro file by looking for it in the following places: * - Directories named in TROFFCVT_TMAC_PATH environment variable, if it's set. * This always takes precedence, to allow the user to specify where to find * the files. * - Directory named in TROFFCVT_LIB_DIR environment variable, if it's set. * - Current directory. * - The troffcvt library directory. (This allows you to override system * macro packages by placing more troffcvt-friendly versions in this directory. * - The directory named by the MACROLIBDIR configuration parameter. * * Return a pointer to the filename if it was found, NULL otherwise. * Return value is to static buffer. Caller should copy if it needs to * hang onto the value for a while. */ char * FindMacroFile (char *file) { extern char *getenv (); char *p; p = FindFileByPathList (file, getenv ("TROFFCVT_TMAC_PATH")); if (p == (char *) NULL) p = FindFileByPathList (file, getenv ("TROFFCVT_LIB_DIR")); if (p == (char *) NULL) p = FindFileByPathList (file, "."); if (p == (char *) NULL) p = FindFileByPathList (file, PROJLIBDIR); if (p == (char *) NULL) p = FindFileByPathList (file, MACROLIBDIR); return (p); } /* * Allocate a new input source structure, fill in the type, set * up the input function pointer, and switch the current source * pointer to it. The caller must fill in the union information. */ static void PushSource (short type, short fakeEof) { Source *sp = New (Source); switch (sp->sType = type) { case fileSource: sp->sChIn = FChIn; break; case macroSource: sp->sChIn = MChIn; break; case anonStringSource: sp->sChIn = AChIn; break; default: ETMPanic ("NewSource: unknown input source type"); } sp->sFakeEof = fakeEof; sp->sPrev = curSrc; /* link to head of source list */ curSrc = sp; ++inputLevel; } /* * Switch to another file without saving current file. If this * fails, the caller should cause an exit; no effort should be * made to continue processing. * * THIS REALLY NEEDS TO UNWIND ALL ACTIVE INPUT SOURCES. */ int SwitchFile (char *name) { if (Debug (bugInputStack)) { ETMMsg ("switch file <%s>", name == (char *) NULL ? "(stdin)" : name); } if (name == (char *) NULL) return (0); if (curSrc == (Source *) NULL) ETMPanic ("%sSwitchFile: no current source", FileInfo ()); if (curSrc->sType != fileSource) { ETMMsg ("%scannot switch file: current input source not file", FileInfo ()); return (0); } pushCount = 0; /* throw away any pushback */ if (freopen (name, "r", curSrc->sFile.filePtr) == (FILE *) NULL) return (0); /* * Replace filename in file information structure */ Free (curSrc->sFile.fileName); curSrc->sFile.fileName = StrAlloc (name); /* * Say previous char is end of line so we think we're at the * beginning of a line initially. */ curSrc->sFile.prevChar = lf; curSrc->sFile.inputLine = 0; SetInputLineRegisters ((Param) 0); return (1); } /* * Switch to a file and save the current input source on a stack. * * If name is NULL, switch to stdin (this trick is used by main() when * there are no named input files, but should not be used otherwise). */ int PushFile (char *name) { FILE *f; if (Debug (bugInputStack)) ETMMsg ("push file <%s>", name == (char *) NULL ? "(stdin)" : name); if (name == (char *) NULL) { f = stdin; name = "(stdin)"; } else if ((f = fopen (name, "r")) == (FILE *) NULL) return (0); PushSource (fileSource, 0); curSrc->sFile.fileName = StrAlloc (name); curSrc->sFile.filePtr = f; /* * Say previous char is end of line so we think we're at the * beginning of a line initially. */ curSrc->sFile.prevChar = lf; curSrc->sFile.inputLine = 0; SetInputLineRegisters ((Param) 0); return (1); } /* * Set up a MacArg structure containing copies of a macro's name and * arguments. Also initialize the structure's use count to one. */ static MacArg * SetUpArguments (XChar *name, int argc, XChar *argv[]) { MacArg *ma; int i; ma = New (MacArg); ma->mName = XStrAlloc (name); ma->mArgc = argc; for (i = 0; i < ma->mArgc; i++) ma->mArgv[i] = XStrAlloc (argv[i]); ma->mRefCount = 1; return (ma); } /* * Release a macro's argument structure. This decrements the use count * and returns if the count isn't zero (since that means some other * currently executing macro is using the structure). If the count is * zero, deallocate the structure. */ static void ReleaseArguments (MacArg *ma) { int i; if (ma == (MacArg *) NULL) return; if (--ma->mRefCount > 0) return; XStrFree (ma->mName); for (i = 0; i < ma->mArgc; i++) XStrFree (ma->mArgv[i]); Free ((char *) ma); } /* * Switch to a macro and save the current input source on a stack. * Sets register ".$" to the number of arguments provided to the macro. * Also save a pointer to the previous macro input source and update * curMacSrc to point to the new macro source. * * If a macro invokes another macro by interpolating it as a string * (\*x, \*(xx, \*[xxx]), then, as in groff, the arguments of the outer * macro are not hidden to the inner macro. This is implemented by * having the inner macro inherit the outer macro's argument information * structure (which includes \$0, the macro name). It's not sufficient * to simply copy the arguments because .shift in the inner macro affects * the outer macro's arguments. * * We know that a macro was invoked as a string if argc is -1. (See * EncodeEscape()). */ int PushMacro (XChar *name, int argc, XChar *argv[]) { Name *np; MacArg *ma; Object *op; int i; if ((np = LookupName (name, macDef)) == (Name *) NULL) return (0); if (Debug (bugInputStack)) { ETMMsg ("push macro <%s>", XStrToStr (name)); for (i = 0; i < argc; i++) ETMMsg ("argument %d: <%s>", i, XStrToStr (argv[i])); } if (argc > maxMacroArgs) { ETMMsg ("%smacro passed too many args (>%d), extra ignored", FileInfo (), maxMacroArgs); argc = maxMacroArgs; } if (argc >= 0) ma = SetUpArguments (name, argc, argv); else { /* * Pushing a string, or macro invoked as string. Get pointer * to argument structure from current macro so as to inherit * its arguments. (Make sure to set the pointer to NULL and * make the arg count zero if there isn't any current macro * or it doesn't have any argument information.) */ ma = (MacArg *) NULL; argc = 0; if (curMacSrc != (Source *) NULL) { ma = curMacSrc->sMacro.mArg; if (ma != (MacArg *) NULL) { argc = ma->mArgc; ++ma->mRefCount; } } } op = np->nObject; /* * The reference count of the macro's underlying object is incremented * for each invocation of the macro, but it's only an approximation of * recursion depth, since any aliases to the name increment the * reference count as well. But with a large value of maxMacRecursion, * this shouldn't be a problem. */ if (op->oRefCount >= maxMacRecursion) { ETMMsg ("%smacro or string <%s> possible infinite recursion refused", FileInfo (), XStrToStr (name)); return (0); } PushSource (macroSource, 0); GrabObject (op); curSrc->sMacro.objPtr = op; curSrc->sMacro.curPos = 0L; curSrc->sMacro.endPos = op->oMacro->macSiz; curSrc->sMacro.mArg = ma; curSrc->sMacro.prevMacSrc = curMacSrc; curMacSrc = curSrc; if (Debug (bugInputStack)) ETMMsg (".$ set to %d", argc); StrSetRegisterValue (".$", (Param) argc); return (1); } /* * Switch to an unnamed string (not a string register), obtained, e.g., * by macro argument or number register reference. * * Save the current input source on a stack. */ int PushAnonString (XChar *s, short pauseAfter) { if (Debug (bugInputStack)) ETMMsg ("push anon-string <%s>", XStrToStr (s)); PushSource (anonStringSource, pauseAfter); curSrc->sAnonString.anonStr = XStrAlloc (s); curSrc->sAnonString.curAPtr = curSrc->sAnonString.anonStr; return (1); } /* * Terminate current input source and resume the previous one if there is one. * * If the just-terminated was a macro, reset the .$ register to the value it * had before the macro was executed. * * If the just-terminated source was a macro, check whether or not it needs * to be deallocated. This will be the case if the macro was redefined or * removed while executing, since removal has to be deferred until it * terminates then. */ static void PopSource (void) { Source *sp; MacSrc *ms; Param nargs; if (Debug (bugInputStack)) ETMMsg ("pop input source"); if (curSrc == (Source *) NULL) ETMPanic ("%sPopSource: logic error", FileInfo ()); switch (curSrc->sType) { case fileSource: (void) fclose (curSrc->sFile.filePtr); Free (curSrc->sFile.fileName); break; case macroSource: ms = &curSrc->sMacro; /* * Release this use of the macro to decrement its reference * count (this also deallocates the macro object if the * reference count goes to zero, e.g., if the macro removed * itself). */ ReleaseObject (ms->objPtr); /* * Release the name and the arguments */ ReleaseArguments (ms->mArg); /* * Reset curMacSrc to the value it had before this macro * was shoved on the input stack, and update .$ to the * correct value for the previous macro. */ curMacSrc = ms->prevMacSrc; nargs = 0; if (curMacSrc != (Source *) NULL) { if (curMacSrc->sMacro.mArg != (MacArg *) NULL) nargs = curMacSrc->sMacro.mArg->mArgc; } StrSetRegisterValue (".$", nargs); break; case anonStringSource: XStrFree (curSrc->sAnonString.anonStr); break; default: ETMPanic ("PopSource: unknown input type"); } returnEof = curSrc->sFakeEof; sp = curSrc; curSrc = sp->sPrev; /* revert pointer to previous input source */ Free ((char *) sp); --inputLevel; if (curSrc != (Source *) NULL && curSrc->sType == fileSource) SetInputLineRegisters (curSrc->sFile.inputLine); } /* * Return a pointer to one of the current macro's arguments, or NULL if * the argument is out of range or there is no currently executing macro * from which arguments can be taken. * n is the argument number, but indexing is skewed: * n is in the range 1..99, but arg 1..99 is in margv[0..98]. * $0 is returned as the macro name, a la groff. * * Returns a pointer to a static area. */ static XChar * MacroArgument (int n) { MacArg *ma; XChar *p; if (curMacSrc == (Source *) NULL || (ma = curMacSrc->sMacro.mArg) == (MacArg *) NULL || n < 0 || n > ma->mArgc) { p = (XChar *) NULL; } else if (n == 0) /* macro name */ p = ma->mName; else /* regular macro argument */ p = ma->mArgv[n-1]; if (Debug (bugInputStack)) { ETMMsg ("macro arg %d is <%s>", n, p == (XChar *) NULL ? "(null)" : XStrToStr (p)); } return (p); } void ShiftMacroArguments (short n) { MacArg *ma; short i; if (curMacSrc == (Source *) NULL) /* not in macro */ return; ma = curMacSrc->sMacro.mArg; if (ma == (MacArg *) NULL) /* no argument information */ return; if (n <= 0) /* nothing to do */ return; if (n > ma->mArgc) /* don't shift too many */ n = ma->mArgc; /* * Deallocate the arguments that will be shifted off the arg array */ for (i = 0; i < n; i++) XStrFree (ma->mArgv[i]); /* * Shift the other arguments down */ for (i = n; i < ma->mArgc; i++) ma->mArgv[i-n] = ma->mArgv[i]; /* * Decrement argument count and reset .$ register */ ma->mArgc -= n; StrSetRegisterValue (".$", (Param) ma->mArgc); } static void WriteLineInfo (void) { char buf[bufSiz]; if (!writeLineInfo || curSrc->sType != fileSource) return; sprintf (buf, "line %s %ld", curSrc->sFile.fileName, curSrc->sFile.inputLine); ControlOut (buf); } /* * Return next character from file input. * * This routine also turns CR or CRLF into LF, so that text files * created on a Macintosh or MS-DOS machine can be read properly * without problem. The pushback here is done using stdio mechanism * instead of UnChIn(), since the latter's at too high a level of * abstraction. */ static XChar FChIn (void) { int c, c2; XChar xc; for (;;) { /* map CR and CRLF to LF */ if ((c = getc (curSrc->sFile.filePtr)) == cr) { /* have CR, look at next char, push back if not LF */ if ((c2 = getc (curSrc->sFile.filePtr)) != lf) ungetc (c2, curSrc->sFile.filePtr); c = lf; } if (c == EOF) break; /* filter nulls */ if (c != '\0') break; } if (curSrc->sFile.prevChar == lf) { ++curSrc->sFile.inputLine; SetInputLineRegisters (curSrc->sFile.inputLine); WriteLineInfo (); } curSrc->sFile.prevChar = c; /* save for next call */ /* * Convert stdio return value to XChar, taking care to map stdio * end-of-file value to internal end-of-file value. */ xc = (c == EOF ? endOfInput : c); if (Debug (bugFChIn)) PrintDebugChar ('F', xc); return (xc); } static XChar MChIn (void) { MacSrc *mp = &curSrc->sMacro; XChar c; if (mp->curPos < mp->endPos) c = mp->objPtr->oMacro->macBuf[mp->curPos++]; else c = endOfInput; if (Debug (bugMChIn)) PrintDebugChar ('M', c); return (c); } static XChar AChIn (void) { XChar c; if ((c = curSrc->sAnonString.curAPtr[0]) != (XChar) 0) ++(curSrc->sAnonString.curAPtr); else c = endOfInput; if (Debug (bugAChIn)) PrintDebugChar ('A', c); return (c); } /* * Return the next character from the current input source: * - If we're simulating EOF, return endOfInput * - If there is anything in the pushback queue for the current input * level, return next character from the queue. (Checking the input * level avoids problems if you've pushed back a character looking for * the end of a reference, and then push a string that the reference * results in onto the stack; without the level, you'd return the pushed * back character before the string you just pushed!) * - Call the input function for the current source. If current * source returns endOfInput, unwind to previous source and retry. */ static XChar ChIn0 (void) { XChar c = endOfInput; while (!returnEof && curSrc != (Source *) NULL) { if (pushCount > 0 && pushLevel[pushCount-1] == inputLevel) { c = (XChar) pushBuf[--pushCount]; break; } if ((c = (*(curSrc->sChIn)) ()) != endOfInput) break; PopSource (); /* resume reading previous source */ } if (Debug (bugChIn0)) PrintDebugChar ('0', c); return (c); } /* * Interpret a macro argument reference. $* and $@ are special and * produce the concatenation of all the arguments separated by spaces * ($@ in addition double-quotes earch argument). Otherwise the * reference must be $n, $(nn, or $[nnn], where n is a number. * * If there is no macro in the input stack from which arguments can be * taken, or the reference is malformed, the reference is simply ignored. */ static void MacroArgumentReference (void) { MacArg *ma; char buf[10], *bp; XChar c; XChar *p, *p2, *p3; int needQuote; int i, n, len; /* * Get pointer to macro argument structure, but then parse the * reference before checking whether the pointer is NULL. * Otherwise the stuff after the \$ will appear literally in * the output. */ ma = (MacArg *) NULL; if (curMacSrc != (Source *) NULL) ma = curMacSrc->sMacro.mArg; if ((c = ChPeek ()) == '*' || c == '@') { c = ChIn (); needQuote = (c == '@'); if (ma == (MacArg *) NULL) return; n = ma->mArgc; if (n == 0) /* no arguments */ return; /* * Construct a string that looks like: * \$1 \$2 ... \$n (for \$*) * or * "\$1" "\$2" ... "\$n" (for \$@) * and shove it on the input stack. This way, the string * itself is processed at a new input level, and when the * embedded argument references are encountered, they'll * be processed at a level above that of the string. * Assume 10 chars is enough to encode any arg reference. */ len = n * 10; p = (XChar *) VAlloc (len, sizeof (XChar)); p2 = p; for (i = 1; i <= n; i++) { if (i > 1) *p2++ = ' '; if (needQuote) *p2++ = '"'; *p2++ = escChar; *p2++ = '$'; if (i < 10) *p2++ = i + '0'; else { sprintf (buf, "%d", i); bp = buf; *p2++ = '['; while (*bp != '\0') *p2++ = *bp++; *p2++ = ']'; } if (needQuote) *p2++ = '"'; } *p2 = '\0'; if (p + len <= p2) ETMPanic ("MacroArgumentReference: logic error"); PushAnonString (p, 0); return; } n = -1; if ((p = ParseNameRef ()) != (XChar *) NULL) { p2 = p; /* save pointer so can free it later */ n = 0; while (*p2 != '\0') { if (Digit (*p2)) n = n * 10 + (*p2++ - '0'); else { ETMMsg ("%snon-numeric macro argument reference: <%s>", FileInfo (), XStrToStr (p)); n = -1; break; } } XStrFree (p); } if (n >= 0) { p = MacroArgument (n); if (p != (XChar *) NULL) PushAnonString (p, 0); } } /* * Process character following an escape. If the sequence is one * such that it causes a new input source to be pushed, return '\0'. * Otherwise map the character to an escape or special char code if * necessary and return the result. A '\0' return can also mean the * input sequence was malformed and ignored, so that the caller should * keep looking for input. * * Following are interpreted even in copy mode (see sec. 7.2): * * \n pushes input to string representing number register value * \* pushes input to string * \$ pushes input to macro argument (if a macro is executing) * \\ convert to single '\' * \t,\a convert to tab, leader character * \. convert to plain '.' * * Following are interpreted only when not in copy mode: * * \n same as in copy mode * \* same as in copy mode * \$ same as in copy mode * \(xx convert to special character code * \[xxx] convert to special character code * \w'str' calculate width of str and interpolate into input stream. * everything else converted to escape code for the character * * These actions perhaps are not especially obvious from the code below. */ static XChar EncodeEscape (XChar c) { Name *np; SpChar *scp; XChar *p; XChar buf[bufSiz]; int needQuote; int i, n, len; /* * The following characters are interpolated whether * or not copy mode is on. Process them first. */ switch (c) { case 'n': /* * This is pretty ugly because the value of the .z * register is the NAME of the current diversion, not * a number. Ditto for .ev, which is the name of the * current environment. */ if ((np = ParseRegisterRef ()) != (Name *) NULL) { if (strcmp (XStrToStr (np->nName), ".z") == 0) p = CurrentDiversion (); else if (strcmp (XStrToStr (np->nName), ".ev") == 0) p = CurrentEnvironmentName (); else p = FormatRegister (np->nRegister); } else { (void) XStrCpy (buf, StrToXStr ("0")); p = buf; } (void) PushAnonString (p, 0); return ('\0'); case '*': /* * String reference. * Strings and macros share the same data structure. * See the PushMacro() code for explanation of passing * an argc value of -1. */ if ((p = ParseNameRef ()) != (XChar *) NULL) { if (LookupMacro (p) != (Macro *) NULL) (void) PushMacro (p, -1, (XChar **) NULL); XStrFree (p); } return ('\0'); case '$': /* * Macro argument reference. */ MacroArgumentReference (); return ('\0'); } /* * There are a few more characters to be interpreted if copy mode * is on. If in copy mode and the character is NOT interpreted, * push it back so it'll be returned on the next input call, and * return the escape character that preceded it. */ if (copyMode) { escStripped = 1; /* * escChar must be tested separately; it's not a constant, * so it can't be one of the cases in the switch below. */ if (c == escChar) return (c); switch (c) { case 't': return ('\t'); case 'a': return (1); /* ASCII SOH */ case '.': return ('.'); } /* * The character following the escape isn't part of a * recognized escape sequence. Put the character back and * return a literal escape character. */ escStripped = 0; UnChIn (c); return (escChar); } /* * Not copy mode - return escape code for character except for * special characters, \w, \A */ if (c == '(' || (!compatMode && c == '[')) { UnChIn (c); if ((p = ParseNameRef ()) == (XChar *) NULL) return ('\0'); if (!AsciiStr (p)) { ETMMsg ("%swarning: illegal special character <%s>", FileInfo (), XStrToStr (p)); XStrFree (p); return ('\0'); } if ((scp = LookupSpCharByName (p)) == (SpChar *) NULL) { /* * If special char doesn't exist, print a warning * (unless processing an .if c request). Then * define the character with an empty value so no * more warnings will be generated. */ if (!inCharTest) { ETMMsg ("%swarning: special character <%s> not defined", FileInfo (), XStrToStr (p)); } buf[0] = '\0'; /* empty XChar string */ (void) NewSpChar (p, buf); scp = LookupSpCharByName (p); } XStrFree (p); return (scp->spCode); } else if (c == 'w') { ParseWidth (); return ('\0'); } else if (c == 'A') { ParseNameTest (); return ('\0'); } return (ToEsc (c)); } /* * Return next character from input stream, perhaps processing * escape sequence or pushing input first. Returns endOfInput when * there is no more input or if AExit() has been called. */ XChar ChIn (void) { static int eofCount = 0; XChar c; if (!allowInput) return (lastCharRead = endOfInput); escStripped = 0; for (;;) { if ((c = ChIn0 ()) == endOfInput) break; /* * If next char is not an escape, it's just a normal * character. */ if (c != escChar || !doEscapes) break; if ((c = ChIn0 ()) == endOfInput) /* malformed */ break; if (c == lf) /* embedded newline, discard */ continue; if (c == '"') /* comment, discard until newline */ { while (!Eol (ChIn0 ())) { /* gobble rest of line */ } c = lf; break; } /* * Encode the character following the escape if necessary. * The return value cases are: * '\0' - a new input source (\*, \$, \n) was countered * and pushed on the input stack. Loop to continue reading. * \} - an input conditional level end was found. Decrement * the conditional level and loop to continue reading. * Otherwise return the character */ if ((c = EncodeEscape (c)) != '\0') { if (c != ToEsc ('}')) /* check for \} */ break; --ifLevel; } } /* * This bit of ugliness helps track down errors in input logic * that results from some hunk of code running wild in a * ChIn()/UnChIn() loop. */ if (c == endOfInput) { if (eofCount++ > 100) ETMPanic ("Program terminated, input logic error"); } else eofCount = 0; if (Debug (bugChIn)) PrintDebugChar (' ', c); return (lastCharRead = c); } /* * Peek at next input character and return it, without removing it * from the input stream. */ XChar ChPeek (void) { XChar c; UnChIn (c = ChIn ()); return (c); } /* * Push a character back onto the current input source. * * endOfInput is allowed but is discarded. This is so that callers don't * have to check whether or not they're pushing a "real" character. * * Escape codes and special characters are converted back into their * original multiple-character input sequences. When these sequeuences are * reread, they'll be converted back into as appropriate. This unpacking is * NECESSARY, because an escaped character might first be seen in non-copy * mode, then pushed back and reread in copy mode. If the escape code * itself were pushed back, the character wouldn't be interpreted in * copy mode properly. */ void UnChIn (XChar c) { char *p; int len; if (c == endOfInput) { if (Debug (bugUnChIn)) ETMMsg ("push %d (discarded)", inputLevel); return; } p = XCharToStr (c); len = strlen (p); if (pushCount + len + (escStripped ? 1 : 0) > maxPushChar) ETMPanic ("UnChIn: character pushback limit exceeded"); while (len > 0) { pushLevel[pushCount] = inputLevel; pushBuf[pushCount++] = *(p + --len); } if (escStripped) { pushLevel[pushCount] = inputLevel; pushBuf[pushCount++] = '\\'; } escStripped = 0; if (Debug (bugUnChIn)) { char *s; s = (escStripped ? "\\" : ""); if (c == lf) ETMMsg ("push %d <%slf>", inputLevel, s); else ETMMsg ("push %d <%s%s>", inputLevel, s, p); } } (c = (*(curSrc->sChIn)) ()) != endOfInput) break; PopSource (); /* resume reading previous source */ } if (Debug (bugChIn0)) PrintDebugChar ('0', c); rettroffcvt-1.04/troffcvt/output.c010064400017710000151000000076250630076510400203710ustar00junkyarddatamgmt00000400000027/* * output.c - basic output operations */ #include #include "etm.h" #include "troffcvt.h" #define maxTransDepth 20 /* * Level 2 output routines */ static int inPara = 0; static int inOTextLine = 0; static XChar transTab[256]; /* transliteration table */ static int transDepth = 0; /* transliteration depth (loop detection) */ /* * Initialize transliteration table to "no transliteration", i.e., * transliteration(x) = x, for all x. */ void InitTransliterate (void) { int i; for (i = 0; i < 256; i++) transTab[i] = i; } void Transliterate (int in, XChar out) { if (in < 0 || in > 255) ETMMsg ("Transliterate: bad in value (%ld)", in); else transTab[in] = out; } /* * Shove out a break if necessary. Nothing is written if no paragraph * is active. * * A break flushes the current text output line, turns off any \c * continuation, and turns off the need for a space between successive * text lines. */ void Break (void) { inContinuation = 0; needSpace = 0; if (inPara) { FlushOText (); ControlOut ("break"); inPara = 0; fieldDelimCount = 0; } } void ControlOut (char *s) { FlushOText (); ChOut ('\\'); StrOut (s); ChOut (lf); } void CommentOut (char *s) { char buf[bufSiz]; sprintf (buf, "comment %s", s); ControlOut (buf); } /* * Write out a control word which is really part of paragraph * text (e.g., for a special character). Set inPara to note the * fact that a paragraph is now active. */ void SpecialTextOut (char *s) { FlushOText (); ChOut ('@'); StrOut (s); ChOut (lf); inPara = 1; } /* * Write out an extended-char paragraph text string. */ void TextXStrOut (XChar *s) { if (s != (XChar *) NULL) { while (*s != '\0') TextXChOut (*s++); } } /* * Write out an extended-char paragraph text character. */ void TextXChOut (XChar c) { char *cp; cp = CharToOutputStr (c); if (*cp == '@') SpecialTextOut (cp+1); else TextStrOut (cp); } /* * Write out a paragraph text string. No interpretation of * the string is done. */ void TextStrOut (char *s) { if (s != (char *) NULL) { while (*s != '\0') TextChOut (*s++); } } /* * Write out a paragraph text character. Set inPara to note the fact * that a paragraph is now active and that there is an output text line * in progress. * * A few characters are treated specially because they have special meaning * in troffcvt output syntax (e.g., @ and / are written as @at and * @backslash). */ void TextChOut (int c) { if (Special (c) || Esc (c)) ETMPanic ("%sTextChOut: logic error", FileInfo ()); /* * Perform transliteration. If the resulting character is * special or escaped, pass it back to a routine that can * write it out properly. However, there is the possibility * of introducing a transliteration loop here, so check for that. */ c = transTab[c]; if (Special (c) || Esc (c)) { if (++transDepth > maxTransDepth) ETMPanic ("%stransliteration loop", FileInfo ()); TextXChOut (c); --transDepth; return; } if (c == '\\') SpecialTextOut ("backslash"); else if (c == '@') SpecialTextOut ("at"); else if (c == '\t') SpecialTextOut ("tab"); else if (c == 1) SpecialTextOut ("leader"); else if (c == '\b') SpecialTextOut ("backspace"); else { ChOut (c); inPara = 1; inOTextLine = 1; } } /* * Flush any output text line that may be in progress. */ void FlushOText (void) { if (inOTextLine) { ChOut (lf); inOTextLine = 0; } } /* * Level 1 output routines * * StrOut () - write out a string. * ChOut () - write out a character. ALL output (except ETM messages) * comes through this routine. * AllowOutput () - allow or throttle output. */ static int oAllow = 1; void StrOut (char *s) { while (*s != '\0') ChOut (*s++); } void ChOut (int c) { if (oAllow && putc (c, stdout) == EOF) ETMPanic ("Write error, cannot continue"); } int AllowOutput (int yesno) { int prev = oAllow; oAllow = yesno; return (prev); } troffcvt-1.04/troffcvt/list.c010066400017710000151000000307360633770407400200160ustar00junkyarddatamgmt00000400000027/* * Name list operations */ #include #include "etm.h" #include "memmgr.h" #include "troffcvt.h" static void RetargetAliases (Object *opNew, Object *opOld); static void ReleaseName (Name *np, short idx); /* * Pointers to lists of request, macro/string, and register names. * Lookups are done so often on names that it's worthwhile to bust * the names up into separate little lists, which speeds things up * by a fair amount. */ #define maxNameList 64 static Name *nameList[maxNameList]; #define NameListIdx(namehash) ((namehash<0?-namehash:namehash)%maxNameList) /* * Pointers to list of * special characters. */ static SpChar *spCharList = (SpChar *) NULL; static long lookups = 0; static long tests = 0; static long compares = 0; static long fails = 0; void DumpNameInfo (void) { int i, j; Name *np; /* for (i = 0; i < maxNameList; i++) { j = 0; np = nameList[i]; while (np) { j++; np = np->nNext; } printf ("%d %d\n", i, j); } */ printf ("lookups %ld\ttests %ld\tcompares %ld\tfails %ld\n", lookups, tests, compares, fails); } /* * Compute hash value of an XChar string */ static long Hash (XChar *s) { long c; long val = 0; while ((c = *s++) != '\0') val += c; return (val); } /* * Create a new name structure and add it to the list of known names. * Removes any currently existing instance of the name. If an object * is passed in, point the name to it and increment the object's * reference count. If no object is passed in, allocate a new one, * point the name at it, set the type, and set the reference count to 1. * When no object is passed in, the caller must initialize the type-specific * fields on the allocated object when NewName() returns. * * The major problems here are: * - If the name already exists, it is being redefined and the name should * be detached from the existing underlying object. * - In addition, if other names also point to the existing object, they * need to be retargeted to the new object. (These will be aliases, and * redefining any of the aliased names redefines them all.) * - The old object can't just be deleted, because it may be a macro that's * currently executing. In that case, wait until the macro terminates * to remove it. */ Name * NewName (XChar *name, Object *op, short type) { Name *np, *npOld; Object *opOld; short typeMask; short aliasCount; short nlIdx = NameListIdx (Hash(name)); if (type == regDef) typeMask = regDef; else typeMask = reqDef|macDef; npOld = LookupName (name, typeMask); if (npOld == (Name *) NULL) /* no object with name exists */ aliasCount = 0; else /* object with name already exists */ { /* * Determine how many other aliases there are to this object, * other than the given name. Then release the object * (decrement the reference count, deallocate if the count * goes to zero and release the name structure (deallocate it). */ opOld = npOld->nObject; aliasCount = opOld->oRefCount - 1; ReleaseObject (opOld); ReleaseName (npOld, nlIdx); } np = New (Name); /* allocate new name struct */ np->nName = XStrAlloc (name); /* fill in name fields */ np->nHash = Hash (name); np->nNext = nameList[nlIdx]; /* attach name to name list */ nameList[nlIdx] = np; /* * If no object was passed in, create a new one, and set the type and * the reference count. (If an object was passed in, we're creating * an alias; just increment the count.) In all cases, point the name * to the object. */ if (op == (Object *) NULL) { op = New (Object); op->oType = type; op->oRefCount = 0; } GrabObject (op); np->nObject = op; /* * Retarget any aliases that used to point to the old object. * This will transfer names from old underlying object to new, and * remove old object. (It's possible for this to be called for * a macro with a single name if it's currently executing, since * invocations count in the reference count; in that case the call * won't retarget any other names, but it won't do any harm, either. */ if (aliasCount > 0) RetargetAliases (np->nObject, opOld); return (np); } /* * Look through the namelist for any names that currently point to opOld. * Make them point to opNew instead. This causes the reference count on * opOld to go to zero, which results in its being deleted. */ static void RetargetAliases (Object *opNew, Object *opOld) { Name *np; int i; for (i = 0; i < maxNameList; i++) { for (np = nameList[i]; np != (Name *) NULL; np = np->nNext) { if (np->nObject == opOld) { np->nObject = opNew; /* retarget name to new obj */ GrabObject (opNew); /* * Decrement the refcount; deallocate if the count * goes to zero. */ ReleaseObject (opOld); } } } } /* * Rename a name definition (request, macro, or string only), replacing both * the name and the hash value. This is implemented by creating the new name * as an alias to the existing name, then removing the existing name. This * leaves the underlying object alone. * * np = named object to be renamed * name = new name to assign to np * * If the old name and the new name are the same, do nothing. If something * already exists with the given name as its name, remove it first. */ void RenameName (Name *np, XChar *name) { if (XStrCmp (np->nName, name) != 0) { /* * Create new name as alias (removes anything it points to now) */ NewName (name, np->nObject, np->nObject->oType); /* * Release the old name */ ReleaseName (np, NameListIdx (Hash (np->nName))); } } /* * Allocate a new request. The action list isn't initialized because * the actions might not be known yet. */ Request * NewRequest (XChar *name) { Name *np; Request *rp; np = NewName (name, (Object *) NULL, reqDef); rp = np->nRequest = New (Request); rp->reqPActions = (Action *) NULL; rp->reqPPActions = (Action *) NULL; return (rp); } /* * Allocate a new macro. Allocate an initial block of space for the body * but set the body length to zero because nothing's been added to the * body yet. */ Macro * NewMacro (XChar *name) { Name *np; Macro *mp; np = NewName (name, (Object *) NULL, macDef); mp = np->nMacro = New (Macro); mp->macBuf = (XChar *) VAlloc (macroAllocSize, sizeof (XChar)); mp->macMaxSiz = macroAllocSize; mp->macSiz = 0; return (mp); } /* * Allocate a new register and initialize its values. The hard part * is determining the format type. The default is numeric, with width * zero (which means "as wide as necessary"). Width is only consulted * for numeric format. If the format isn't recognized, numeric is used. */ Register * NewRegister (XChar *name, Param initial, Param increment, XChar *format, short readonly) { Name *np; Register *rp; np = NewName (name, (Object *) NULL, regDef); rp = np->nRegister = New (Register); rp->regValue = initial; rp->regIncrement = increment; rp->regReadOnly = readonly; SetRegisterFormat (rp, format); return (rp); } /* * Version of NewRegister() that can be used when you KNOW the register * name and format types are straight ASCII. */ Register * StrNewRegister (char *name, Param initial, Param increment, char *format, short readonly) { XChar nbuf[bufSiz]; XChar fbuf[bufSiz]; (void) XStrCpy (nbuf, StrToXStr (name)); (void) XStrCpy (fbuf, StrToXStr (format)); return (NewRegister (nbuf, initial, increment, fbuf, readonly)); } /* * Look up a name that has one of the given types. "typeMask" is a bitmask * of all the types that are acceptable. */ Name * LookupName (XChar *name, short typeMask) { Name *np; long hash = Hash (name); short nlIdx = NameListIdx (hash); lookups++; for (np = nameList[nlIdx]; np != (Name *) NULL; np = np->nNext) { tests++; /* if ((np->nObject->oType & typeMask) && np->nHash == hash && XStrCmp (np->nName, name) == 0) return (np); */ if ((np->nObject->oType & typeMask) && np->nHash == hash) { compares++; if (XStrCmp (np->nName, name) == 0) return (np); } } fails++; return ((Name *) NULL); } Request * LookupRequest (XChar *name) { Name *np; if ((np = LookupName (name, reqDef)) == (Name *) NULL) return ((Request *) NULL); return (np->nRequest); } Macro * LookupMacro (XChar *name) { Name *np; if ((np = LookupName (name, macDef)) == (Name *) NULL) return ((Macro *) NULL); return (np->nMacro); } Register * LookupRegister (XChar *name) { Name *np; if ((np = LookupName (name, regDef)) == (Name *) NULL) return ((Register *) NULL); return (np->nRegister); } /* * Remove a name from the name list and the underlying object to which * the name points. numReg is true if the name to be removed refers * to a number register, false if it is a request, macro or string. * Request, register, macro, and string names are all maintained in * a single list, but registers are considered to lie in a different * namespace than the others. (Thus, there can be two entries on the * list with the same name but different types.) */ void RemoveNamedObject (XChar *name, short typeMask) { Name *np; Macro *mp; long hash = Hash (name); short nlIdx = NameListIdx (hash); for (np = nameList[nlIdx]; np != (Name *) NULL; np = np->nNext) { if ((np->nObject->oType & typeMask) && np->nHash == hash && XStrCmp (np->nName, name) == 0) break; } if (np != (Name *) NULL) { ReleaseObject (np->nObject); ReleaseName (np, nlIdx); } } /* * Put a "grab" on an object by incrementing its use count to indicate * the object is in use. This is called when a name is made to point * to the object or when the object becomes an input source (e.g., when * a request or macro is executed). */ void GrabObject (Object *op) { ++op->oRefCount; } /* * Release a use of an object by decrementing its reference count. * If the reference count goes to zero, deallocate the storage devoted * to the object. * * For macro objects, the reference count includes not only the names * that point to the object but also any current invocations of the macro. * This means a macro will never be deallocated while it's executing (this * is A Good Thing). */ void ReleaseObject (Object *op) { if (--op->oRefCount > 0) return; if (op->oRefCount < 0) ETMPanic ("ReleaseObject: logic error 1"); switch (op->oType) /* deallocate name-type specific stuff */ { case reqDef: FreeActions (op->oRequest->reqPActions); FreeActions (op->oRequest->reqPPActions); Free ((char *) op->oRequest); break; case macDef: Free ((char *) op->oMacro->macBuf); Free ((char *) op->oMacro); break; case regDef: Free ((char *) op->oRegister); break; default: ETMPanic ("ReleaseObject: logic error 2"); } Free ((char *) op); } /* * Release a given name from the given name list */ static void ReleaseName (Name *np, short idx) { Name *np2; /* * Remove np from name list and free it */ if (nameList[idx] == np) /* first element in list */ nameList[idx] = np->nNext; /* skip to next */ else /* remove from middle of list */ { np2 = nameList[idx]; while (np2->nNext != (Name *) NULL) { if (np2->nNext == np) { np2->nNext = np->nNext; break; } np2 = np2->nNext; } } XStrFree (np->nName); Free ((char *) np); } /* * Define a special character. If the character is already defined, * just replace the value. Otherwise add it to the list. */ SpChar * NewSpChar (XChar *name, XChar *value) { static XChar code = spCharBase; /* special chars start at spCharBase */ SpChar *sp; char *p; if (!AsciiStr (name)) ETMPanic ("special character name (%s) is not plain text", XStrToStr (name)); p = StrAlloc (XStrToStr (value)); if (!AsciiStr (value)) ETMPanic ("special character value (%s) is not plain text", p); if ((sp = LookupSpCharByName (name)) != (SpChar *) NULL) { Free (sp->spValue); /* replace value in existing struct */ sp->spValue = p; } else /* create new struct */ { sp = New (SpChar); sp->spName = XStrAlloc (name); sp->spHash = Hash (name); sp->spCode = code++; sp->spValue = p; sp->spNext = spCharList; spCharList = sp; } return (sp); } /* * Look up a special character definition by its name */ SpChar * LookupSpCharByName (XChar *name) { SpChar *sp; long hash; hash = Hash (name); for (sp = spCharList; sp != (SpChar *) NULL; sp = sp->spNext) { if (hash == sp->spHash && XStrCmp (name, sp->spName) == 0) break; } return (sp); /* NULL if not found */ } /* * Look up a special character definition by code */ SpChar * LookupSpCharByCode (XChar code) { SpChar *sp; for (sp = spCharList; sp != (SpChar *) NULL; sp = sp->spNext) { if (sp->spCode == code) break; } return (sp); /* NULL if not found */ } troffcvt-1.04/troffcvt/parse.c010064400017710000151000001135040633770517400201500ustar00junkyarddatamgmt00000400000027/* * Should arg parsers take argument indicating whether not to fail * if no argument is present? Or should they ALWAYS return 1, even if * the thing they're looking for isn't present or is malformed? * * parse.c * * Routines to parse request name from request line, several * different styles of request-argument parsing, and escape * sequence parsing. * * Argument parsers should skip whitespace before trying to parse * the argument(s). * * The action list for a request should specify the "eol" action * after all arguments have been parsed, in order to skip to the * end of the input line. * * All argument parsing routines leave their result in rargc/rargv. * However, the argument initialization stuff is done in * ParseRequestName(), since that must always be called before * any argument parsing is done anyway. Better to call it once * than have to remember it in each parsing routine. * * Escape sequence parsers are called after the escape and the * character following have been read. * * All parsers must be careful not to run past the end of the input * line, and have to push back the linefeed if they read it. */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "portlib.h" #include "etm.h" #include "memmgr.h" #include "troffcvt.h" #define maxReqArgs (maxMacroArgs+1) /* req. name + 99 arguments */ #define opEq 1 #define opNe 2 #define opLess 3 #define opLessEq 4 #define opGreater 5 #define opGreaterEq 6 #define opPlus 7 #define opMinus 8 #define opMultiply 9 #define opDivide 10 #define opMod 11 #define opAnd 12 #define opOr 13 typedef struct ParamMap ParamMap; struct ParamMap { char *pName; Param *pAddr; }; static void InitArgs (void); static void AddArgChar (XChar c); static void EndArg (void); static void ProcessRequest2 (short jiggerCompat); static int ParseRequestName (void); static void ParseNumberArg (int defUnit, int relAllowed, Param curVal); static Param ParseExpr (int defUnit); static Param ParseExprTerm (int defUnit); static int LooksLikeExpr (void); static int ParseCondition (void); static int ParseStrCondition (void); static void ProcessCondition (void); static void SkipCondition (void); /* * Argument count and pointer vector (the request name is rargv[0]). * The arguments are pointers into a single buffer and should NOT be * written into by anything but InitArg()/AddArgChar()/EndArg(). * InitArgs() is called only by ProcessRequest2(), and the other two * functions should be called only by argument parsing routines. */ static int rargc = 0; /* argument count */ static XChar *rargv[maxReqArgs]; /* argument pointers */ static XChar rargBuf[bufSiz]; /* argument buffer */ static XChar *rpCur; /* current argument being collected */ static int rpIdx; /* index past rpCur */ static int rleft = 0; /* chars left in buffer */ /* * These are the parameters which can be set relatively, and for * which there must be a way to refer to them symbolically. This * map links the parameter symbolic name with the address of the * variable holding the parameter value. */ static ParamMap paramMap [] = { "point-size", &curSize, "spacing", &curVSize, "line-spacing", &curLineSpacing, "indent", &curIndent, "line-length", &curLineLen, "page-length", &curPageLen, "title-length", &curTitleLen, "offset", &curOffset, "page-number", &curPageNum, (char *) NULL, (Param *) NULL }; /* * Read request line, parse request name and arguments, and execute any * actions associated the request. Actually, all the work is done by * ProcessRequest2(). All that ProcessRequest() does is save any existing * request arguments before calling ProcessRequest2() and then restore * them afterward. This prevents inner levels of recursive request * processing from destroying the arguments of outer levels. * * jiggerCompat is a hack for the groff .do request; it indicates whether * compatibility mode needs to be disabled before parsing the command * and reenabled after parsing it (but before executing it). */ void ProcessRequest (short jiggerCompat) { int _rargc; XChar *_rargv[maxReqArgs]; XChar _rargBuf[bufSiz]; _rargc = rargc; BCopy (rargv, _rargv, sizeof (rargv)); BCopy (rargBuf, _rargBuf, sizeof (rargBuf)); ProcessRequest2 (jiggerCompat); rargc = _rargc; BCopy (_rargv, rargv, sizeof (rargv)); BCopy (_rargBuf, rargBuf, sizeof (rargBuf)); } static void ProcessRequest2 (short jiggerCompat) { Name *np; Object *op; Request *rp; XChar *p; Param prevCompat; int i; if (jiggerCompat) /* disable compat mode, save previous value */ prevCompat = SetCompatMode (0); InitArgs (); /* * Read and save the first character in a global variable; some * requests need to know whether it was the break or no-break * control character (e.g., . or `). */ curCtrlChar = ChIn (); if (!ParseRequestName ()) /* put request name in rargv[0] */ { SkipToEol (); if (jiggerCompat) /* restore previous compat mode */ (void) SetCompatMode (prevCompat); return; } /* * First see if request is a macro invocation. If so, push macro * onto input stack so that it will be executed. */ if (LookupMacro (rargv[0]) != (Macro *) NULL) { AParseMacroArgs (0, (XChar **) NULL); SkipToEol (); if (jiggerCompat) /* restore previous compat mode */ (void) SetCompatMode (prevCompat); (void) PushMacro (rargv[0], rargc-1, &rargv[1]); return; } if (Debug (bugReqProcess)) ETMMsg ("Request: <%s>", XStrToStr (rargv[0])); if ((np = LookupName (rargv[0], reqDef)) == (Name *) NULL) /*if ((rp = LookupRequest (rargv[0])) == (Request *) NULL)*/ { /* request not found; gobble rest of line and ignore */ if (Debug (bugReqProcess)) ETMMsg ("request <%s> not found", XStrToStr (rargv[0])); if (dumpBadReq) { FlushOText (); StrOut ("\\comment bad-req: "); StrOut (XCharToStr (curCtrlChar)); for (p = rargv[0]; *p != '\0'; p++) StrOut (XCharToStr (*p)); while (!Eol (ChPeek ())) StrOut (XCharToStr (ChIn ())); ChOut (lf); } SkipToEol (); if (jiggerCompat) /* restore previous compat mode */ (void) SetCompatMode (prevCompat); return; } if (Debug (bugReqProcess)) ETMMsg ("processing <%s>", XStrToStr (rargv[0])); /* * Perform actions necessary to parse the rest of the line. * Skip to the end of the line to make sure it's gobbled from the * input (in case parsing actions fail and quit reading the line * early). If parsing was successful, perform any actions that * should be executed to carry out the request. * * There is a pitfall lurking here in that the parsing action list * or the post-parsing action list might remove the request. To * prevent a request's action list from removing the request's data * structure right out from under itself while it's executing, the * reference count is incremented while the actions are being * processed. Have to get the object pointer here and work with * that. Can't work with the name pointer since the name might * get blasted by the actions! */ op = np->nObject; GrabObject (op); rp = op->oRequest; i = ProcessActionList (rp->reqPActions); SkipToEol (); if (jiggerCompat) /* restore previous compat mode */ (void) SetCompatMode (prevCompat); if (i) (void) ProcessActionList (rp->reqPPActions); ReleaseObject (op); } /* * Initialize rargc to zero and set up pointers for stuffing * arguments in the argument buffer. */ static void InitArgs (void) { rargc = 0; rpCur = rargBuf; rpIdx = 0; rleft = sizeof (rargBuf) / sizeof (XChar); } /* * Add a character to the end of the current argument. This * call does nothing if the maximum number of arguments has already * been parsed, or if there isn't enough room to add the character * and a trailing null byte. */ static void AddArgChar (XChar c) { if (rargc < maxReqArgs && rleft > 0) { rpCur[rpIdx++] = c; --rleft; } } /* * Call this function when the end of an argument has been seen. It * bumps the arg count rargc and initializes the pointer to it in the * rargv array. Print a message if argument buffer overflow occurred. */ static void EndArg (void) { /* make sure there's still room for trailing null */ if (rargc < maxReqArgs && rleft > 0) { rpCur[rpIdx++] = '\0'; /* terminate current argument */ rargv[rargc++] = rpCur; /* save pointer to beginning of it */ rpCur += rpIdx; /* advance current argument pointer */ rpIdx = 0; } else if (rargc == 0) /* couldn't even parse first argument - yow! */ ETMPanic ("arg buffer overflow while parsing request name!"); else { ETMMsg ("request <%s>, arg buffer overflow, excess ignored", XStrToStr (rargv[0])); } } /* * Skip whitespace up to the request (or macro) name, and read one or two * characters to get the name. Also initialize the argument buffer. * * The linefeed at the end of the line is NOT eaten by this function, * no matter what the return value. * * Request name can be up to four characters, if both request characters * are special chars (each is unpacked into two bytes). The name can be * arbitrary length if long names are allowed (i.e., if compatibility mode * is not turned on). */ static int ParseRequestName (void) { XChar c; int i = 0; SkipWhite (); /* ctrl char might have white after */ if (Eol (ChPeek ())) return (0); /* no request named */ AddArgChar (ChIn ()); if (!WhiteOrEol (ChPeek ())) /* 2- or multi-character request */ { AddArgChar (ChIn ()); if (compatMode) { if (!WhiteOrEol (ChPeek())) { ETMMsg ("%swarning: ambiguous request name", FileInfo ()); } } else /* multi-character */ { while (!WhiteOrEol (ChPeek ())) AddArgChar (ChIn ()); } } EndArg (); return (1); } /* * Parse macro arguments, each consisting of strings of non-white * characters. Terminated by end of line. An argument that begins * with a double quote is parsed in quote mode until a closing quote. * Quoted arguments may contain whitespace. * * Quotes in arguments are handled as follows: * - If not in quote mode, just treat the quote as part of the argument. * - If in quote mode and the quote is doubled, it becomes one quote * character. If the next character is not a quote, the quote is the * closing quote of a quoted argument. * - If not in compatibility mode, only a quote at the same input level * can terminate a quoted argument (thus, something like "\*[xx]", where * xx contains a quote, will be parsed correctly). * * If an escape occurs in an argument, grab the next character, too * (even if it's whitespace). */ int AParseMacroArgs (argc, argv) int argc; XChar **argv; { XChar c; int quote; short iLevel; CopyMode (1); /* turn on copy mode */ for (;;) { quote = 0; SkipWhite (); if (Eol (ChPeek ())) break; if (ChPeek () == '"') /* quoted argument */ { quote = 1; (void) ChIn (); } iLevel = ILevel (); while (!Eol (ChPeek ())) { c = ChIn (); if (c == '"' && iLevel == ILevel ()) { /* * If quote is true, we're in a quoted * argument. If the next char is another * quote, it's a doubled quote, which * turns into one quote. If the next * char isn't a quote, the terminating * quote for the argument has been found. * If quote isn't true, this is a quote in * the middle of an unquoted argument and * becomes part of the argument unchanged. */ if (quote) { if (ChPeek () == '"' && iLevel == ILevel ()) c = ChIn (); /* "" -> " */ else break; /* end of quoted arg */ } } else if (c == escChar) { AddArgChar(c); /* add escape */ c = ChIn (); /* grab next char */ } else if (!quote && White (c)) /* found word break */ break; AddArgChar (c); } EndArg (); } CopyMode (0); /* turn off copy mode */ return (1); } /* * Look for a filename argument: skip any whitespace, then find * a sequence of non-white characters. Reads through the end of * line character. */ int AParseFileName (int argc, XChar **argv) { SkipWhite (); if (!Eol (ChPeek ())) { while (!WhiteOrEol (ChPeek ())) AddArgChar (ChIn ()); } EndArg (); return (1); } /* * Look for a (register, string, macro) name. The name can be only one or * two characters in compatibility mode, longer otherwise. */ int AParseName (int argc, XChar **argv) { XChar c; SkipWhite (); if (!Eol (ChPeek ())) { AddArgChar (ChIn ()); /* first char */ if (!WhiteOrEol (ChPeek ())) { AddArgChar (ChIn ()); /* second char */ if (!compatMode) /* allow third, etc. */ { while (!WhiteOrEol (c = ChIn ())) AddArgChar (c); UnChIn (c); } } } EndArg (); return (1); } int AParseNames (int argc, XChar **argv) { for (;;) { SkipWhite (); if (Eol (ChPeek ())) break; AParseName (0, (XChar **) NULL); } return (1); } /* * Multiple-name equivalent of AParseName */ /* * Skip whitespace, then parse a string to the end of the input * line in copy mode. The argument is 'y' if a leading double * quote should be recognized and stripped (as for .ds) or not * (as for .tm and .ab). */ int AParseStringValue (int argc, XChar **argv) { SkipWhite (); if (argv[0][0] == 'y' && ChPeek () == '"') (void) ChIn (); CopyMode (1); /* turn on copy mode */ while (!Eol (ChPeek ())) AddArgChar (ChIn ()); EndArg (); CopyMode (0); /* turn off copy mode */ return (1); } /* * Parse one of those three-part title things: three title parts, * delimited by the first non-white character following the request * name. Any part may be empty/missing. Stop on end of line. The * three parts go into rargv as usual. rargc will indicate the number * of parts actually found. */ int AParseTitle (int argc, XChar **argv) { int i; XChar delim, c; short iLevel; SkipWhite (); if (!Eol (ChPeek ())) { delim = ChIn (); iLevel = ILevel (); for (i = 0; i < 3; i++) { while (1) { c = ChIn (); if (Eol (c)) { UnChIn (c); break; } if (c == delim && iLevel == ILevel ()) break; AddArgChar (c); } EndArg (); if (Eol (ChPeek ())) break; } } return (1); } /* * Parse a single-character argument. */ int AParseChar (int argc, XChar **argv) { SkipWhite (); if (!Eol (ChPeek ())) { AddArgChar (ChIn ()); EndArg (); } return (1); } /* * Parse number as an absolute quantity and convert back to string * form for placement in the argument vector. * * argv[0] is default units indicator. */ int AParseNumber (int argc, XChar **argv) { SkipWhite (); ParseNumberArg ((int) argv[0][0], 0, (Param) 0); return (1); } /* * Parse number as an absolute or relative quantity and convert back * to string form for placement in the argument vector. * * argv[0] is default units indicator, argv[1] is the value against * which relative values should be taken (zero if they must be absolute). * argv[1] may be a symbolic name to represent the current setting * for some parameter, a literal number, or, if it begins with \, * the name of a number register (use the register value). The latter * is for use with .nr, where the initial value argument can be relative * to the register's current value. */ int AParseARNumber (int argc, XChar **argv) { ParamMap *pm; Param current; char buf[bufSiz]; (void) strcpy (buf, XStrToStr (argv[1])); if (argv[1][0] == '\\') current = GetRegisterValue (&argv[1][1]); else if (!AsciiStr (argv[1])) { ETMMsg ("%sAParseARNumber: non-ASCII argument <%s>", FileInfo (), buf); } else { for (pm = paramMap; pm->pName != (char *) NULL; pm++) { if (strcmp (pm->pName, buf) == 0) break; } /* probably should test that it's really all digits... */ if (pm->pName == (char *) NULL) current = (Param) StrToLong (buf); else current = *(pm->pAddr); } SkipWhite (); ParseNumberArg ((int) argv[0][0], 1, current); return (1); } /* * Parse number and put it into the current argument, in basic units * if need be. First argument is the default units, the second is * non-zero if the number can be a relative quantity, zero if it must * be absolute. If it can be relative, the third argument is the * current value, which is adjusted by the value of the number parsed. * * If the input doesn't look like it could be a number, the argument * is left empty. */ static void ParseNumberArg (int defUnit, int relAllowed, Param curVal) { char buf[bufSiz], *p; Param val; if (ParseNumber (defUnit, relAllowed, curVal, &val)) { sprintf (buf, "%ld", val); for (p = buf; *p != '\0'; p++) AddArgChar (*p); } EndArg (); } /* * Parse number and return it, in basic units if need be. Return value * is zero if no number is found, else non-zero and the number value is * placed in val. * * First argument is the default units, the second is non-zero if the * number can be a relative quantity, zero if it must be absolute. * If it can be relative, the third argument is the current value, * which is adjusted by the value of the number parsed. * * Expressions that specify distance to an absolute position ("|N") * evaluate to zero, since the current position is unknown. */ int ParseNumber (int defUnit, int relAllowed, Param curVal, Param *val) { XChar inc = 0; int dist = 0; if (!LooksLikeExpr ()) return (0); if (relAllowed && Sign (ChPeek ())) inc = ChIn (); else if (ChPeek () == '|') { (void) ChIn (); dist = 1; } *val = ParseExpr (defUnit); /* inc is 0 if !relAllowed... */ if (inc == '+') *val = curVal + *val; else if (inc == '-') *val = curVal - *val; if (dist) *val = 0; return (1); } /* * Parse a numeric expression: term { op term { op term ... } }. * Evaluation is left to right, except as overridden by parens. */ static Param ParseExpr (int defUnit) { Param val, val2; int op; XChar c; val = ParseExprTerm (defUnit); /* * Look for op expr now */ for (;;) { switch (c = ChIn ()) { default: /* no operator; end of expr */ UnChIn (c); return (val); case '+': op = opPlus; break; case '-': op = opMinus; break; case '/': op = opDivide; break; case '*': op = opMultiply; break; case '%': op = opMod; break; case '&': op = opAnd; break; case ':': op = opOr; break; case '<': /* < or <= */ if (ChPeek () != '=') op = opLess; else { (void) ChIn (); op = opLessEq; } break; case '>': /* > or >= */ if (ChPeek () != '=') op = opGreater; else { (void) ChIn (); op = opGreaterEq; } break; case '=': /* = or == */ if (ChPeek () == '=') (void) ChIn (); op = opEq; break; } val2 = ParseExprTerm (defUnit); switch (op) { default: ETMPanic ("%sParseExpr: logic error, op = %d", FileInfo (), op); case opPlus: val += val2; break; case opMinus: val -= val2; break; case opDivide: if (val2 == 0) { ETMMsg ("%sdivide by zero detected", FileInfo ()); val = 0; } else val /= val2; break; case opMultiply: val *= val2; break; case opMod: val %= val2; break; case opAnd: val = (val && val2); break; case opOr: val = (val || val2); break; case opLess: val = (val < val2); break; case opLessEq: val = (val <= val2); break; case opGreater: val = (val > val2); break; case opGreaterEq: val = (val >= val2); break; case opEq: val = (val == val2); break; } } } /* * Parse a single term of an expression, either a number or "(expr)" */ static Param ParseExprTerm (int defUnit) { double val = 0.0, mult; int sign = 1; int unit; if (ChPeek () == '(') /* ( expr ) - recurse */ { (void) ChIn (); val = ParseExpr (defUnit); if (ChPeek () == ')') /* ')' should be there, but */ (void) ChIn (); /* don't be too fussy :-) */ return (Units (val, 'u')); } while (Sign (ChPeek ())) sign *= (ChIn () == '+' ? 1 : -1); while (Digit (ChPeek ())) val = val * 10 + ChIn () - '0'; if (ChPeek () == '.') { (void) ChIn (); mult = .1; while (Digit (ChPeek ())) { val += (ChIn () - '0') * mult; mult /= 10.0; } } unit = (UnitChar (ChPeek ()) ? ChIn () : defUnit); if (defUnit == 'x') unit = 'x'; return (Units (val, unit) * sign); } /* * Look at the next character to see whether it looks like it * could begin a numeric expression. */ static int LooksLikeExpr (void) { XChar c = ChPeek (); return (Digit (c) || Sign (c) || c == '.' || c == '(' || c == '|'); } /* * Parse tab stops. This writes out the results as it parses; * the stops are not maintained internally at all. */ int AParseTabStops (int argc, XChar **argv) { Param pos[maxTabStops]; char type[maxTabStops]; int i; Param prev = 0; for (i = 0; i < maxTabStops; i++) { SkipWhite (); if (!ParseNumber ('m', 1, prev, &pos[i])) break; type[i] = 'l'; switch (ChPeek ()) { case 'C': type[i] = 'c'; (void) ChIn (); break; case 'R': type[i] = 'r'; (void) ChIn (); break; } prev = pos[i]; } SetTabStops ((Param) i, pos, type); return (1); } /* * Parse "if" condition. argv[0][0] is 'y' if an .el should * be expected afterward. */ int AParseCondition (int argc, XChar **argv) { int result = 0; if ((result = ParseCondition ()) <= 0) /* malformed or false */ SkipCondition (); else if (result > 0) /* condition true */ ProcessCondition (); /* * It's necessary to put the last (end-of-line) char back into the * input since the request processor is going to look for eol * after calling the argument processing actions for the current * .if/.ie request. Without this, the next input line would be * lost. A subterfuge. (Push back lastCharRead since the last * char can be either a newline or endOfInput; pushing back newline * if the char was really endOfInput would result in the appearance * of an extra blank line in the input.) */ UnChIn (lastCharRead); /* * Save result for following .el if this was .ie request. * result < 0 and result > 0 are both considered successes. * This causes the .el to be skipped both if the test was * malformed, or true. If this was an .if (not .ie), then * set the result true so that any (illegal) following .el * gets skipped. */ if (argv[0][0] == 'n') /* was .if, not .ie */ ifResult = 1; else if (result != 0) /* .ie succeeded */ ifResult = 1; else /* .ie failed */ ifResult = 0; return (1); } /* * Parse the condition in preparation for processing the * stuff contingent on the condition. Some tests are impossible * to do, e.g., whether the current page is even or odd. In * such cases, assume true. * * Return value: * 1 condition true * 0 condition false * -1 error (malformed conditional) */ static int ParseCondition (void) { XChar buf[bufSiz], *p; XChar c; SpChar *sp; int reverse = 0; int result = 0; int type; SkipWhite (); if (ChPeek () == '!') { (void) ChIn (); reverse = 1; } if (WhiteOrEol (ChPeek ())) return (-1); c = ChIn (); if (c == 't') result = troff; else if (c == 'n') result = !troff; else if (c == 'e' || c == 'o') /* can't tell - yucko */ result = 1; else if (c == 'c') { inCharTest = 1; /* suppress normal warning message */ SkipWhite (); if (Eol (ChPeek ())) result = -1; else { /* * The character will exist unless it's a special * character reference for which the value is empty. * That signifies a special character that was * referenced but was never defined in an action file. */ result = 1; c = ChIn (); if (Special (c)) { sp = LookupSpCharByCode (c); if (sp->spValue[0] == '\0') result = 0; } } inCharTest = 0; } else if (c == 'd' || c == 'r') { type = (c == 'd' ? reqDef|macDef : regDef); SkipWhite (); p = buf; while (!WhiteOrEol (ChPeek ())) *p++ = ChIn (); *p = '\0'; result = (LookupName (buf, type) != (Name *) NULL); } else { UnChIn (c); if (LooksLikeExpr ()) result = (ParseExpr ('u') > 0); else result = ParseStrCondition (); } if (result < 0) return (-1); return (reverse ? !result : result); } /* * Parse a string-valued conditional * * Return value: * 1 condition true * 0 condition false * -1 error (malformed conditional) */ static int ParseStrCondition (void) { XChar delim, c; XChar buf[bufSiz], *p; short iLevel; delim = ChIn (); iLevel = ILevel (); p = buf; while (!Eol (c = ChIn ())) /* find first string */ { if (c == delim && iLevel == ILevel ()) break; *p++ = c; } if (Eol (c)) /* no terminating delim - malformed */ { UnChIn (c); return (-1); } *p = '\0'; p = buf; while (!Eol (c = ChIn ())) /* find second string */ { if (c == delim && iLevel == ILevel ()) /* end of second */ return (*p == '\0'); /* end of first? */ if (c != *p++) /* mismatch */ break; } /* * At this point, have either seen end of line without * terminating delimiter (malformed condition) or a * mismatch in the strings and need to look for closing * delimiter of second string. */ if (Eol (c)) /* no terminating delim - malformed */ { UnChIn (c); return (-1); } while (!Eol (c = ChIn ())) { if (c == delim && iLevel == ILevel ()) return (0); } UnChIn (c); return (-1); } /* * This is used for .el clauses. Look at the result of the last * .ie to see whether to process or skip the clause. If it's * processed, set ifResult so that any further .el's without an * intervening .ie (shouldn't happen, but you never know) are * skipped. */ int AProcessCondition (int argc, XChar **argv) { if (Debug (bugConditional)) ETMMsg ("el: %s condition", ifResult ? "skip" : "process"); if (ifResult) /* .ie succeeded, skip .el */ SkipCondition (); else /* .ie failed, accept .el */ { ProcessCondition (); ifResult = 1; } UnChIn (lastCharRead); /* <--see AParseCondition() for explanation */ return (1); } static void ProcessCondition () { int level; if (Debug (bugConditional)) ETMMsg ("process condition"); SkipWhite (); if (ChPeek () != ToEsc ('{')) /* single line */ { if (Debug (bugConditional)) ETMMsg ("process single-line condition"); (void) ProcessLine (); } else /* \{ ... \} */ { if (Debug (bugConditional)) ETMMsg ("process multiple-line condition"); (void) ChIn (); level = ifLevel++; while (level < ifLevel) { if (Debug (bugConditional)) ETMMsg ("current level %d, seeking %d", ifLevel, level); if (!ProcessLine ()) { ETMPanic ("%sEOF looking for conditional end", FileInfo ()); } } if (Debug (bugConditional)) ETMMsg ("found level %d", level); } if (Debug (bugConditional)) ETMMsg ("done processing"); } static void SkipCondition (void) { int ifBeg = ToEsc ('{'); int level; XChar c; if (Debug (bugConditional)) ETMMsg ("skip condition"); while (!Eol (c = ChIn ()) && c != ifBeg) { /* spin wheels */ } if (Eol (c)) { if (Debug (bugConditional)) ETMMsg ("skip single-line condition"); return; } if (Debug (bugConditional)) ETMMsg ("skip multiple-line condition"); level = ifLevel++; while (level < ifLevel) { if (Debug (bugConditional) && Eol (c)) ETMMsg ("current level %d, seeking %d", ifLevel, level); /* * Must check level *again* here because ChIn() might * change it! If last line of input has closing \}, it * ends the loop, even if it's missing a newline. */ if ((c = ChIn ()) == endOfInput && level < ifLevel) { ETMPanic ("%sEOF looking for conditional end", FileInfo ()); } if (c == ifBeg) ++ifLevel; } if (Debug (bugConditional)) ETMMsg ("found level %d", level); while (!Eol (c)) c = ChIn (); if (Debug (bugConditional)) ETMMsg ("done skipping"); } /* * This is a hack for .bd request, which can be in two formats, * ".bd F N" or ".bd S F N". */ int AParseEmbolden (int argc, XChar **argv) { SkipWhite (); while (!WhiteOrEol (ChPeek ())) /* parse first argument */ AddArgChar (ChIn ()); EndArg (); /* * If first argument is "S", the request is ".bd S F N", otherwise * it's ".bd F N". */ if (strcmp ("S", XStrToStr (rargv[rargc-1])) == 0) { SkipWhite (); while (!WhiteOrEol (ChPeek ())) AddArgChar (ChIn ()); EndArg (); } SkipWhite (); ParseNumberArg ('x', 0, 0); /* parse smear value */ return (1); } /* * Parse transliteration list. */ int AParseTransList (int argc, XChar **argv) { SkipWhite (); while (!Eol (ChPeek ())) AddArgChar (ChIn ()); EndArg (); return (1); } /* * Handle the .do request: * - Skip whitespace * - "Unread" a control character; ".do xxx" doesn't expect one before the * "xxx" part, but ProcessRequest() needs one. Putting a fake control * character into the input fools ProcessRequest(). Use the character * that was read before the "do", so that "'do" can be used to pass the * no-break control character to the request. * - Call ProcessRequest(), telling it to disable compatibility mode while * parsing the request. * - Shove the last input character read back on the input (see * AParseCondition() for explanation, it's the same reason here). */ int AProcessDo (int argc, XChar **argv) { SkipWhite (); if (Eol (ChPeek ())) /* there's no request to process */ return (1); UnChIn (ctrlChar); ProcessRequest (1); UnChIn (lastCharRead); /* <--see AParseCondition() for explanation */ return (1); } /* * Interpret an action argument. Returns a pointer into a static * area, which should be copied out if the caller needs to hang onto * it for a while. * * Instances of $n (n=1..9) are replaced by the appropriate request * argument. $$ is replaced by the number of request arguments. $* * is replaced by all the arguments, concatenated and space-separated. * $@ is replaced by all the arguments, double-quotes, concatenated, * and space-separated. \n and \t are replaced by linefeed and tab, * respectively. Other backslash sequences just have the initial * backslash stripped. (This means that to include a backslash, * you should double it.) * * The request name is in rargv[0], but doesn't count as an argument, * so $$ is really rargc-1, and $n is rargv[n]. */ XChar * InterpretActionArg (XChar *p) { static XChar xbuf[bufSiz]; XChar *xp = xbuf; char cbuf[bufSiz]; char *cp; XChar c; int needQuote; int i; if (p == NULL) ETMPanic ("%sInterpretActionArg: logic error", FileInfo ()); while ((c = *p++) != 0) { if (c == '$') /* substitute request argument */ { if ((c = *p++) == '\0') break; /* malformed */ if (c == '$') { sprintf (cbuf, "%d", rargc-1); cp = cbuf; while (*cp != '\0') *xp++ = *cp++; } else if (Digit (c)) { if ((i = c - '0') > 0 && i < rargc) { (void) XStrCpy (xp, rargv[i]); xp += XStrLen (xp); } } else if (c == '*' || c == '@') { needQuote = (c == '@'); for (i = 1; i < rargc; i++) { if (i > 0) *xp++ = ' '; if (needQuote) *xp++ = '"'; (void) XStrCpy (xp, rargv[i]); xp += XStrLen (xp); if (needQuote) *xp++ = '"'; } } continue; } if (c == '\\') /* strip escape, process next char */ { if ((c = *p++) == '\0') break; /* malformed */ switch (c) { case 'n': c = lf; break; case 't': c = '\t'; break; /* otherwise leave alone */ } } *xp++ = c; } *xp = '\0'; return (xbuf); } /* -------------------------------------------------- */ /* Escape sequence interpreters */ /* -------------------------------------------------- */ /* * Look for sequence following \s. Anything illegal is treated * like \s0 (e.g., \sx) * * \s0 revert to previous * \s-n decrease current by 1-9 (n = single digit) * \s+n increase current by 1-9 (n = single digit) * \sn set to 1-9 (n = single digit) * \snn set to 10..36, where nn is two digits * * That last line require comment: * \s can be followed by a two-digit number <= 36; the number is * interpreted as an absolute change. (Original C/A/T phototypesetter * had sizes up to 36. Original troff would take \s36 as .ps 36 and * \s37 as .ps 3 followed by "7". What a pain.) * * The \s'nnn' and \s[nnn] constructions allowed by groff are not accepted, * because those refer to scaled points, and troffcvt has no notion of * scaled points. */ Param ParseSizeRef (void) { XChar c; double inc = 0.0; /* 0 = abs, -1 = rel. dec., +1 = rel. inc. */ Param val; c = ChPeek (); if (c == '0') /* restore previous */ { (void) ChIn (); return (prevSize); } if (Sign (c)) /* relative change */ { (void) ChIn (); inc = (c == '+' ? 1.0 : -1.0); if (!Digit (ChPeek ())) /* malformed */ return (prevSize); /* fails on FreeBSD unless the (double) is there... weird */ return (curSize + Units (((double) (ChIn () - '0')) * inc, 'x')); } /* one- or two-digit absolute setting */ if (!Digit (c)) /* malformed */ return (prevSize); val = ChIn () - '0'; if (!Digit (c = ChPeek ())) /* one-digit */ return (Units (val, 'x')); /* two-digit, but don't eat second unless <= 36 */ c -= '0'; if (val < 3 || (val == 3 && c <= 6)) { val = val * 10 + c; (void) ChIn (); } return (Units (val, 'x')); } /* * Parse a register reference following \n. Return pointer to * name definition structure if it was found, NULL on malformed * reference. (Returns a pointer to name definition rather than * to register structure, because the caller needs to get at the * name.) * * \nx * \n(xx * \n+x,\n+(xx, \n+[xxx] * \n-x,\n-(xx, \n-[xxx] */ Name * ParseRegisterRef (void) { Name *np; Register *rp; XChar *p; int inc = 0; XChar c; c = ChPeek (); if (Eol (c)) return ((Name *) NULL); if (Sign (c)) /* auto inc/dec */ { (void) ChIn (); /* skip inc/dec char */ inc = (c == '+' ? 1 : -1); } /* now positioned at x or (xx or [xxx] */ if ((p = ParseNameRef ()) == (XChar *) NULL) return ((Name *) NULL); if ((np = LookupName (p, regDef)) != (Name *) NULL) { rp = np->nRegister; /* auto inc/dec if necessary */ if (inc && rp->regReadOnly) ETMMsg ("%sattempt to set readonly register <%s> ignored", FileInfo (), XStrToStr (p)); else rp->regValue += (inc * rp->regIncrement); } XStrFree (p); return (np); } /* * Look for a single, double, or multiple character reference. Used * for references to fonts ("\f"), strings ("\*"), number registers ("\n"), * macro references ("\$"), and special characters ("\("). * * The name can be a single character, two characters preceded by "(", * or, if compatibility mode is not on, multiple characters surrounded * by "[" and "]". Long ([...] names are used by groff and possibly * other extended versions of troff. * * This HAS to allocate memory and can't use a static buffer because * it can be called recursively via ChIn() (e.g., .nr \(ts\(ts ....). * Caller MUST free return value when done with it. */ XChar * ParseNameRef (void) { XChar regName[bufSiz]; XChar c; short iLevel = ILevel (); int i = 0; if (WhiteOrEol (ChPeek ())) /* malformed */ return ((XChar *) NULL); c = ChIn (); if (!compatMode && c == '[') /* multiple-character name */ { for (;;) { c = ChIn(); /* * Look for trailing ] that terminates the name, but * silently accept whitespace or eol as the end of * the name, even if the closing ] hasn't been seen. */ if ((c == ']' && iLevel == ILevel ()) || WhiteOrEol (c)) { if (i == 0) /* empty name; malformed */ return ((XChar *) NULL); regName[i] = '\0'; return (XStrAlloc (regName)); } regName[i++] = c; } /*NOTREACHED*/ } else if (c == '(') /* double-character name */ { /* read next two characters */ if (WhiteOrEol (ChPeek ())) /* malformed */ return ((XChar *) NULL); regName[i++] = ChIn (); /* allow one-character name even though looking for two... */ if (!WhiteOrEol (ChPeek ())) regName[i++] = ChIn (); regName[i] = '\0'; return (XStrAlloc (regName)); } else /* single-character name */ { regName[i++] = c; regName[i] = '\0'; return (XStrAlloc (regName)); } } /* * Parse a sequence of the form \w'string', calculate the width * of the string, convert that number to string form and switch * the input to it. The \w will already have been seen. * * The width is crudely approximated as the number of characters * in the string times the width of an en. * * Size and font changes are recognized but skipped. * * The width string is put into the input pushback to avoid problems * with the order in which any trailing peeked-at character and the * width string will be returned later. */ void ParseWidth (void) { char buf[bufSiz], *p; XChar *xp; XChar c, delim; Param wid = 0; short iLevel; delim = ChIn (); iLevel = ILevel (); if (Eol (delim)) /* malformed */ UnChIn (delim); else while (1) { c = ChIn (); if (Eol (c)) /* malformed */ { UnChIn (c); break; } if (c == delim && iLevel == ILevel ()) break; if (c == ToEsc ('s')) /* size change */ (void) ParseSizeRef (); else if (c == ToEsc ('f')) /* font change */ XStrFree (ParseNameRef ()); /* gobble/ignore ref */ else ++wid; } /* figure width in ens, convert to string, push back onto input */ sprintf (buf, "%ld", Units (wid, 'n')); xp = XStrAlloc (StrToXStr (buf)); PushAnonString (xp, 0); XStrFree (xp); } /* * Parse a sequence of the form \A'string' and shove 1 or 0 on the * input depending on whether or not string is a value register, macro, * font, etc. name. * * This is a groff construct. */ void ParseNameTest (void) { char buf[bufSiz], *p = buf; XChar c, delim, result[2]; short len = 0, valid = 1; short iLevel; /* * Start out by assuming the name will be valid, but mark it invalid * if an illegal character is found in the name. Also mark the name * invalid if it turns out to be zero-length. */ delim = ChIn (); iLevel = ILevel (); if (Eol (delim)) /* malformed */ UnChIn (delim); else while (1) { c = ChIn (); if (Eol (c)) /* malformed */ { UnChIn (c); break; } if (c == delim && iLevel == ILevel ()) break; ++len; /* I dunno why groff allows \, but it does... */ if (c != ToEsc ('\\') && (White (c) || Esc(c) || Special (c))) valid = 0; } if (len == 0) valid = 0; UnChIn (valid ? '1' : '0'); } /* * Skip-character functions. */ void SkipWhite (void) { while (White (ChPeek ())) (void) ChIn (); } void SkipToEol (void) { while (!Eol (ChIn ())) { /* loop */ } } ear value */ return (1); } /* * Parse transliteration list. */ int AParseTransList (int argc, XChar **argv) { SkipWhite (); while (!Eol (ChPeek ())) AddArgChar (ChIn ()); EndArgtroffcvt-1.04/troffcvt/action.c010064400017710000151000000266520630716560700203200ustar00junkyarddatamgmt00000400000027/* * action.c - action table stuff * * When requests are defined, any previous definition is * deleted. This can occur when multiple action files * are read. * * Syntax: * * imm immediate-action-list * req req-name parsing-action-list eol non-parsing-action-list */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "etm.h" #include "tokenscan.h" #include "memmgr.h" #include "tcgen.h" #include "troffcvt.h" /* * flag values are: * * 1 allow in argument parsing part of request action list * 2 allow in non-parsing part of request action list * 4 allow in immediate action list */ typedef struct ActInfo ActInfo; struct ActInfo { int aiFlags; char *aiName; int (*aiFunc) (); int aiArgs; }; static int ParsingActions (Action **apList); static int OtherActions (Action **apList, int flags); static int ParseActionArgs (Action *ap, int args); static Action *AddAction (Action *apList, Action *ap); static char *NextToken (void); static int GetLine (char *buf, int size, FILE *f); static FILE *f; /* action file pointer and input buffer */ static char buf[bufSiz]; static ActInfo aiTab[] = { { 1, "parse-absrel-num", AParseARNumber, 2 }, { 1, "parse-char", AParseChar, 0 }, { 1, "parse-condition", AParseCondition, 1 }, { 1, "parse-filename", AParseFileName, 0 }, { 1, "parse-macro-args", AParseMacroArgs, 0 }, { 1, "parse-name", AParseName, 0 }, { 1, "parse-names", AParseNames, 0 }, { 1, "parse-num", AParseNumber, 1 }, { 1, "parse-embolden", AParseEmbolden, 0 }, { 1, "parse-string-value", AParseStringValue, 1 }, { 1, "parse-tab-stops", AParseTabStops, 0 }, { 1, "parse-title", AParseTitle, 0 }, { 1, "parse-transliteration", AParseTransList, 0 }, { 1, "process-condition", AProcessCondition, 0 }, { 1, "process-do", AProcessDo, 0 }, { 6, "point-size", APointSize, 1 }, { 6, "space-size", ASpaceSize, 1 }, { 6, "constant-width", AConstantWidth, 3 }, { 6, "embolden", AEmbolden, 3 }, { 6, "font", AFont, 1 }, { 6, "font-position", AFontPosition, 2 }, { 6, "page-length", APageLength, 1 }, { 6, "begin-page", ABeginPage, 1 }, { 6, "page-number", APageNumber, 1 }, { 6, "offset", AOffset, 1 }, { 6, "need", ANeed, 1 }, { 6, "no-space", ANoSpace, 1 }, { 6, "flush", AFlush, 0 }, { 6, "break", ABreak, 0 }, { 6, "fill", AFill, 0 }, { 6, "nofill", ANofill, 0 }, { 6, "adjust", AAdjust, 1 }, { 6, "noadjust", ANoAdjust, 0 }, { 6, "center", ACenter, 1 }, { 6, "spacing", ASpacing, 1 }, { 6, "line-spacing", ALineSpacing, 1 }, { 6, "space", ASpace, 1 }, { 6, "line-length", ALineLength, 1 }, { 6, "indent", AIndent, 1 }, { 6, "temp-indent", ATempIndent, 1 }, { 2, "define-macro", ADefineMacro, 2 }, { 2, "append-macro", AAppendMacro, 2 }, { 6, "define-string", ADefineString, 2 }, { 6, "append-string", AAppendString, 2 }, { 6, "rename", ARenameName, 2 }, { 6, "remove-name", ARemoveNames, 2 }, { 6, "remove-names", ARemoveNames, 10 }, { 2, "diversion-begin", ADiversion, 1 }, { 2, "diversion-append", AAppendDiversion, 1 }, { 6, "end-macro", AEndMacro, 1 }, { 6, "input-trap", AInputTrap, 2 }, { 6, "define-register", ADefineRegister, 3 }, { 6, "register-format", ARegisterFormat, 2 }, { 6, "alias-macro", AAliasMacro, 2 }, { 6, "alias-register", AAliasRegister, 2 }, { 6, "set-tab", ASetTabChar, 1 }, { 6, "set-leader", ASetLeaderChar, 1 }, { 6, "set-field", ASetFieldChars, 2 }, { 6, "set-escape", ASetEscape, 1 }, { 6, "noescape", ANoEscape, 0 }, { 6, "underline", AUnderline, 1 }, { 6, "continuous-underline", ACUnderline, 1 }, { 6, "underline-font", AUnderlineFont, 1 }, { 6, "set-control", ASetControl, 1 }, { 6, "set-control2", ASetControl2, 1 }, { 6, "transliterate", ATransliterate, 1 }, { 6, "hyphenate", AHyphenation, 1 }, { 6, "hyphen-char", ASetHyphenChar, 1 }, { 6, "title", ATitle, 3 }, { 6, "page-num-char", APageNumChar, 1 }, { 6, "title-length", ATitleLength, 1 }, { 6, "environment", AEnvironment, 1 }, { 6, "end-input", AExit, 0 }, { 6, "abort", AAbort, 1 }, { 6, "push-file", APushFile, 1 }, { 6, "push-macro-file", APushMacroFile, 1 }, { 2, "switch-file", ASwitchFile, 1 }, { 6, "set-compatibility", ASetCompatibility, 1 }, { 2, "shift-args", AShiftArguments, 1 }, /* echo is special - for .tm, but also can be useful elsewhere */ { 7, "echo", AEcho, 1 }, { 6, "ignore", AIgnore, 1 }, { 6, "special-char", ASpecialChar, 2 }, { 6, "push-string", APushStr, 1 }, { 2, "eol", AEol, 0 }, { 6, "output-control", AWriteControl, 1 }, { 6, "output-text", AWriteText, 1 }, { 6, "output-special", AWriteSpecial, 1 }, { 7, "debug-flag", ADebugFlag, 1 }, { 7, "dump-macro", ADumpMacro, 1 }, { 6, "dump-bad-requests", ADumpBadRequests, 1 }, { 6, "dump-input-stack", ADumpInputStack, 0 }, { 0, (char *) NULL, 0, 0 } }; /* * Read an action file. Compatibility mode is always forced off when * reading such files. */ int ReadActionFile (char *filename) { TSScanner scanner; char *scanEscape; char *type, *name; Request *rp; Action *pap, *oap; XChar xbuf[bufSiz]; char buf[bufSiz]; Param compat; short out; compat = SetCompatMode (0); out = AllowOutput (1); sprintf (buf, "processing action file %s", filename); CommentOut (buf); (void) AllowOutput (out); if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) { (void) SetCompatMode (compat); return (0); } /* * Turn off backslash escape mechanism while parsing * action file. Restore it later. */ TSGetScanner (&scanner); scanEscape = scanner.scanEscape; scanner.scanEscape = ""; TSSetScanner (&scanner); while (GetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') /* comment */ continue; TSScanInit (buf); if ((type = NextToken ()) == (char *) NULL) /* empty line */ continue; if (strcmp (type, "req") == 0) { /* request definition */ if ((name = NextToken ()) == (char *) NULL) continue; /* malformed */ (void) XStrCpy (xbuf, StrToXStr (name)); rp = NewRequest (xbuf); if (Debug (bugActionParse)) ETMMsg ("parsing action for request \"%s\"", name); if (ParsingActions (&pap) && OtherActions (&oap, 6)) { rp->reqPActions = pap; rp->reqPPActions = oap; } else { ETMMsg ("action %s definition malformed", name); (void) XStrCpy (xbuf, StrToXStr (name)); RemoveNamedObject (xbuf, 0); } } else if (strcmp (type, "imm") == 0) { /* immediate execution action list */ if (OtherActions (&pap, 4)) { ProcessActionList (pap); FreeActions (pap); } else ETMMsg ("immediate action list malformed"); } else { ETMMsg ("action line malformed, first token: %s", type); } } (void) fclose (f); scanner.scanEscape = scanEscape; TSSetScanner (&scanner); (void) SetCompatMode (compat); return (1); } /* * Read current line for parsing actions. List must be terminated * by "eol" action, which is not added to list (it's implicit). * * Returns non-zero for success and stuffs head of list into * argument. Returns zero if list is malformed. */ static int ParsingActions (Action **apList) { ActInfo *ai; Action *ap = (Action *) NULL, *apCur; char *p; int result = 0; /* assume MALFORMED until eol found */ while ((p = NextToken ()) != (char *) NULL) { if (Debug (bugActionParse)) ETMMsg ("parsing action name is \"%s\"", p); if (strcmp (p, "eol") == 0) { result = 1; break; } for (ai = aiTab; ai->aiName != (char *) NULL; ai++) { if ((ai->aiFlags & 1) && strcmp (ai->aiName, p) == 0) break; } if (ai->aiName == (char *) NULL) { ETMMsg ("non-parsing action %s in parsing action list", p); break; } apCur = New (Action); apCur->actName = ai->aiName; apCur->actFunc = ai->aiFunc; apCur->actNext = (Action *) NULL; ap = AddAction (ap, apCur); if (!ParseActionArgs (apCur, ai->aiArgs)) break; } if (result) *apList = ap; else FreeActions (ap); return (result); } /* * Read current line for "other" actions. flags is either 4 * (immediate actions only allowed) or 6 (immediate or non-parsing * actions allow). * * Returns non-zero for success and stuffs head of list into * argument. Return zero if list is malformed. */ static int OtherActions (Action **apList, int flags) { ActInfo *ai; Action *ap = (Action *) NULL, *apCur; char *p; int result = 1; /* assume NOT malformed unless error found */ while ((p = NextToken ()) != (char *) NULL) { if (Debug (bugActionParse)) ETMMsg ("action name is \"%s\"", p); for (ai = aiTab; ai->aiName != (char *) NULL; ai++) { if ((ai->aiFlags & flags) && strcmp (ai->aiName, p) == 0) break; } if (ai->aiName == (char *) NULL) { ETMMsg ("disallowed action %s in action list", p); result = 0; break; } apCur = New (Action); apCur->actName = ai->aiName; apCur->actFunc = ai->aiFunc; apCur->actNext = (Action *) NULL; ap = AddAction (ap, apCur); if (!ParseActionArgs (apCur, ai->aiArgs)) break; } if (result) *apList = ap; else FreeActions (ap); return (result); } /* * Arguments are converted from char * strings into XChar * strings so that * their type is consistent with what the rest of the program uses to * represent characters internally. */ static int ParseActionArgs (Action *ap, int args) { char *p; int i; /* * If this error occurs, it's a program error, not a * request file error. Bump up maxActionArgs and recompile. */ if (args > maxActionArgs - 1) ETMPanic ("action %s requires too many args (%d, max is %d)", ap->actName, args, maxActionArgs - 1); ap->actArgc = 0; for (i = 0; i < args; i++) { if ((p = NextToken ()) == (char *) NULL) { ETMMsg ("action %s not given enough args", ap->actName); return (0); } ap->actArgv[i] = XStrAlloc (StrToXStr (p)); } /* put a null pointer after all the non-null arguments */ ap->actArgc = i; ap->actArgv[i] = (XChar *) NULL; return (1); } /* * Add an action to the end of a list. Pass head of list (NULL * if empty) and the action to be added. */ static Action * AddAction (Action *apList, Action *ap) { Action *ap2; if (apList == (Action *) NULL) return (ap); ap2 = apList; while (ap2->actNext != (Action *) NULL) ap2 = ap2->actNext; ap2->actNext = ap; return (apList); } void FreeActions (Action *ap) { Action *apNext; int i; while (ap != (Action *) NULL) { apNext = ap->actNext; for (i = 0; i < ap->actArgc; i++) XStrFree (ap->actArgv[i]); Free ((char *) ap); ap = apNext; } } /* * Read next token from current line and return pointer to it. * If token is "\" at end of line, read next line as continuation. * Return NULL when no more tokens. * * The use to which TSGetScanPos() is put implies that GetLine() * removes trailing newline fluff from lines it reads. */ static char * NextToken (void) { char *p; while ((p = TSScan ()) != (char *) NULL) { if (strcmp (p, "\\") != 0) return (p); if (*TSGetScanPos () != '\0') return (p); /* \ at end of line found */ if (!GetLine (buf, (int) sizeof (buf), f)) break; TSScanInit (buf); } return ((char *) NULL); } /* * Read a line from a file, strip any cr, lf or crlf from the * end. Return zero for EOF, non-zero otherwise. */ static int GetLine (char *buf, int size, FILE *f) { int len; if (fgets (buf, size, f) == (char *) NULL) return (0); if ((len = strlen (buf)) > 0 && buf[len-1] == lf) buf[len-1] = '\0'; if ((len = strlen (buf)) > 0 && buf[len-1] == cr) buf[len-1] = '\0'; return (1); } troffcvt-1.04/troffcvt/chartype.c010064400017710000151000000060610633770511400206460ustar00junkyarddatamgmt00000400000027/* * chartype.c - character-type checking and conversion routines */ #include #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "etm.h" #include "troffcvt.h" /* * Convert a character following escChar into the equivalent * escape-char code, or convert an escape-char code to the regular * character that would follow escChar. * * The escape code for an escaped character c is the same as the ASCII * or 8-bit value of c, but with bit 9 turned on. This makes escape codes * distinct from the regular ASCII range (0..127), 8-bit range (128-255), and * endOfInput. * * The character cannot be a special character code. */ XChar ToEsc (XChar c) { if (Special (c)) ETMPanic ("ToEsc: logic error"); return (c | escBase); /* set escape-code bit */ } XChar FromEsc (XChar c) { /* if (Special (c)) return (c); */ if (Special (c)) ETMPanic ("FromEsc: logic error"); return (c &= ~escBase); /* clear escape-code bit */ } /* * Character type testers. * * Esc(c) Whether c is an escape+char code. * Special(c) Whether c is a special char code. * White(c) Whether c is whitespace (isspace(c) doesn't work). * Eol(c) Whether c ends a line. EOF is considered to end * a line, since a file need not end with a linefeed- * terminated line. * WhiteOrEol(c) Obvious. * UnitChar(c) Whether c is a unit indicator char. */ int Esc (XChar c) { return (!Special (c) && (c & escBase) != 0); } int Special (XChar c) { return (c >= spCharBase); /* greater than ASCII or escape codes */ } int Sign (XChar c) { return (c == '+' || c == '-'); } int White (XChar c) { return (c == ' ' || c == '\t'); } int Eol (XChar c) { return (c == lf || c == endOfInput); } int WhiteOrEol (XChar c) { return (c == ' ' || c == '\t' || c == lf || c == endOfInput); } int UnitChar (XChar c) { return (c == 'x' || c == 'u' || c == 'v' || c == 'n' || c == 'm' || c == 'P' || c == 'p' || c == 'c' || c == 'i'); } /* * Version of isdigit() suitable for XChar values. (Don't want to pass * specials to native isdigit().) * * May not work on non-ASCII machines. */ int Digit (XChar c) { return (c >= '0' && c <= '9'); } /* * Test whether an argument is empty (all white is considered empty) * or numeric. * * The numeric-arg tester allows for a unit indicator at the end. */ int EmptyArg (XChar *arg) { while (*arg != (XChar) '\0') { if (!White (*arg++)) return (0); } return (1); } int NumericArg (XChar *arg) { if (Sign (*arg)) ++arg; if (*arg == (XChar) '\0') return (0); while (Digit (*arg)) ++arg; if (*arg == '.') { ++arg; while (Digit (*arg)) ++arg; } if (UnitChar (*arg)) ++arg; return (*arg == (XChar) '\0'); } /* * Return non-zero if string is composed completely of plain * characters in the ASCII range (values < 128), zero otherwise. */ int AsciiStr (XChar *s) { XChar c; while ((c = *s++) != (XChar) '\0') { /*if (c >= escBase)*/ /* if (Esc (c) || Special (c)) return (0); */ if (c > 127) /* faster check! */ return (0); } return (1); } troffcvt-1.04/troffcvt/text.c010064400017710000151000000251110634111544000200000ustar00junkyarddatamgmt00000400000027/* * Process input text line (non-request line). */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "etm.h" #include "memmgr.h" #include "troffcvt.h" static void ReadTextLine (void); static void CheckInputLineTrap (void); static void EscapedText (XChar ec); /* * Structure for mapping simple escape sequences to their resulting * output string. * * A "simple" escape sequence is one where the \ is followed by * a single character that requires nothing after it, such as \$. * Sequences such as \n or \* that require a register or string * name are not simple sequences. */ typedef struct EscMap EscMap; struct EscMap { char emChar; char *emStr; }; static EscMap escMap[] = { { '\\', "backslash" }, { '&', "zerospace" }, { '^', "twelfthspace" }, { '|', "sixthspace" }, { '0', "digitspace" }, { ' ', "hardspace" }, { '-', "minus" }, { '\'', "acute" }, { '`', "grave" }, { 'a', "leader" }, { 't', "tab" }, { '\0', (char *) NULL } }; /* * This has to take some care not to read past the end of the input line... * * Process a single text line. After it has been processed and flushed, * determine whether to issue a break, whether to decrement counters * (centered lines, underlined lines, etc.) and whether a space will be * necessary in front of the next text line. None of these things will * be necessary if continuation is in effect (\c found in the curent line) * since the next line should be considered logically part of this one. * * Actually, \c doesn't seem to have that effect for .ul/.cu or .it * input line counting, only for .ce - so that's what's done below. * I don't understand why, but that's what troff versions I've looked * at do... */ void ProcessText (void) { inContinuation = 0; ReadTextLine (); if (inContinuation) { SetUnderline (ulCount - 1, cUlCount - 1); CheckInputLineTrap (); return; } /* break if in nofill mode or currently centering lines */ if (fillMode == nofill || centerCount > 0) Break (); /* * Need a space at beginning of next text line if in fill * mode and mode isn't being temporarily overridden by * centering being in effect. */ if (fillMode == fill && centerCount == 0) needSpace = 1; /* * Turn centering off if it was on and this was the last * line to be centered. Filling/adjustment setting in effect * at time centering was turned on now go back into effect. */ SetCFA (centerCount - 1, fillMode, adjust, adjMode); SetUnderline (ulCount - 1, cUlCount - 1); CheckInputLineTrap (); } /* * Do the following things, besides dumping out text. * - If line begins with space, do a break. * - If the line is *completely* blank (empty or all spaces), it's * equivalent to .sp 1. * - If a space is needed between this line and the previous one, * put out a space before the first character from this line is * written. */ static void ReadTextLine (void) { XChar c; int sCount, lineIsBlank = 1; SpChar *sp; char buf[bufSiz]; XChar xbuf[bufSiz]; if (ChPeek () == ' ') /* if line begins with space, do break */ Break (); /* * While reading, keep track of sequences of spaces. If they * occur at the end of the line, forget about them. If the * line is completely blank, it's equivalent to .sp 1. */ for (;;) { sCount = 0; while ((c = ChIn ()) == ' ') ++sCount; if (Eol (c)) break; while (sCount-- > 0) /* dump spaces if any */ TextChOut (' '); /* occurred before c */ lineIsBlank = 0; /* known not to be blank now */ if (needSpace) { TextChOut (' '); needSpace = 0; } /* * Check character to see if it's one of several special * characters. Check these characters before checking for * \(xy special characters or \x escaped characters: these * characters can themselves be special or escaped characters, * but they must be given different treatment than special * or escaped characters are usually given. */ if (c == fieldDelimChar) { SpecialTextOut ((fieldDelimCount % 2) == 0 ? "fieldbegin" : "fieldend"); ++fieldDelimCount; } else if (c == fieldPadChar) /* recognize, but only if */ { /* currently inside field */ if (fieldDelimCount % 2) SpecialTextOut ("fieldpad"); } else if (c == optHyphenChar) SpecialTextOut ("opthyphen"); else if (Special (c)) { if ((sp = LookupSpCharByCode (c)) != (SpChar *) NULL) { if (sp->spValue[0] == '@') SpecialTextOut (sp->spValue + 1); else TextStrOut (sp->spValue); } } else if (Esc (c)) EscapedText (c); else if (c == '`') { if (ChPeek () == '`') { (void) ChIn (); SpecialTextOut ("quotedblleft"); } else SpecialTextOut ("quoteleft"); } else if (c == '\'') { if (ChPeek () == '\'') { (void) ChIn (); SpecialTextOut ("quotedblright"); } else SpecialTextOut ("quoteright"); } else /* it's just plain text */ TextChOut (c); } if (lineIsBlank) /* line was blank; treated like .sp 1 */ { sprintf (buf, "%csp 1\n", ctrlChar); (void) XStrCpy (xbuf, StrToXStr (buf)); PushAnonString (xbuf, 0); } else FlushOText (); } /* * If input line trap should be sprung, push it onto the * input stack and remove the trap. */ static void CheckInputLineTrap (void) { if (itMacro != (XChar *) NULL && --itCount <= 0) { (void) PushMacro (itMacro, 0, (XChar **) NULL); XStrFree (itMacro); itMacro = (XChar *) NULL; } } static void EscapedText (XChar ec) { EscMap *em; XChar *xp; char *cp; Param val; int delim, unit, c, repChar; short iLevel; char buf[bufSiz]; /* convert escaped character to un-escaped form */ ec = FromEsc (ec); /* see if this is a simple single-char escape */ for (em = escMap; em->emChar != '\0'; em++) { if (em->emChar == ec) { SpecialTextOut (em->emStr); return; } } /* * Anything not found in the escape map above requires extra stuff * to follow the escaped character. Exceptions are \n, \$, \*, which * should all already have been recognized in ChIn() and had input * switched* accordingly (thus making the escape sequence disappear). * \w will have been recognized when not in copy mode, and * ProcessText() isn't called in copy mode, so the \w should not be * seen here. */ switch (ec) { default: TextChOut (ec); break; case 'n': case '$': case '*': case '}': case '(': case 'w': case '{': ETMMsg ("%sEscapedText: logic error, wayward <\\%c>", FileInfo (), ec); break; case '.': TextChOut ('.'); break; case 'b': /* \b'stuff' */ case 'o': /* \o'stuff' */ delim = ChIn (); iLevel = ILevel (); if (Eol (delim)) /* malformed */ { UnChIn (delim); break; } ControlOut (ec == 'b' ? "bracket-begin" : "overstrike-begin"); while (1) { c = ChIn (); if (Eol (c)) { UnChIn (c); break; } if (c == delim && iLevel == ILevel ()) break; cp = CharToOutputStr (c); if (*cp == '@') SpecialTextOut (cp+1); else TextStrOut (cp); } ControlOut (ec == 'b' ? "bracket-end" : "overstrike-end"); break; case 'c': /* * \c is recognized anywhere in line. troff manual indicates * what to do only when the \c is at the end of the line * (sec. 4.2), but recognizing it anywhere matches the behavior * I observe in the troff's to which I have access. */ inContinuation = 1; break; case 'd': sprintf (buf, "motion %ld v", Units (.5, 'm')); ControlOut (buf); break; case 'r': sprintf (buf, "motion %ld v", Units (-1, 'm')); ControlOut (buf); break; case 'u': sprintf (buf, "motion %ld v", Units (-.5, 'm')); ControlOut (buf); break; case 'e': TextChOut (escChar); /* print current escape char */ break; case 'f': if ((xp = ParseNameRef ()) != (XChar *) NULL) { SetFont (xp); XStrFree (xp); } break; case 'h': /* \h'expr' */ case 'v': /* \v'expr' */ case 'x': /* \x'expr' */ delim = ChIn (); iLevel = ILevel (); if (Eol (delim)) /* malformed */ { UnChIn (delim); break; } unit = (ec == 'h' ? 'm' : 'v'); if (!ParseNumber (unit, 0, (Param) 0, &val)) val = 0; while (1) { c = ChIn (); if (Eol (c)) { UnChIn (c); break; } if (c == delim && iLevel == ILevel ()) break; } switch (ec) { case 'h': case 'v': sprintf (buf, "motion %ld %c", val, ec); break; case 'x': sprintf (buf, "extra-space %ld", val); break; } ControlOut (buf); break; case 'k': /* gobble mark char, ignore sequence */ if (!Eol (ChPeek ())) (void) ChIn (); break; case 'l': case 'L': /* * Get delim, parse expr, parse possible \&c, get * delim, and write \line. */ delim = ChIn (); iLevel = ILevel (); if (Eol (delim)) /* malformed */ { UnChIn (delim); break; } unit = (ec == 'l' ? 'm' : 'v'); repChar = '\0'; if (!ParseNumber (unit, 0, (Param) 0, &val)) val = 0; if (ChPeek () == Esc ('&')) (void) ChIn (); if (!Eol (c = ChPeek ()) && !(c == delim && iLevel == ILevel())) repChar = ChIn (); while (1) { c = ChIn (); if (Eol (c)) { UnChIn (c); break; } if (c == delim && iLevel == ILevel ()) break; } /* note that the repChar isn't written... */ c = (ec == 'l' ? 'h' : 'v'); if (repChar == '\0') sprintf (buf, "line %ld %c", val, c); else sprintf (buf, "line %ld %c %s", val, c, CharToOutputStr (repChar)); ControlOut (buf); break; case 'p': ControlOut ("break-spread"); break; case 's': /* 0, n, +/-n, or nothing */ SetSize (ParseSizeRef ()); break; case 'z': if (!Eol (ChPeek ())) { sprintf (buf, "zero-width %s", CharToOutputStr (ChIn ())); ControlOut (buf); } break; } } /* * Convert a character code to a printable output string. Escaped * characters are converted to unescaped characters, if they're * not known in the escape map (which is possibly wrong in some cases). * Specials are converted to @-form. * * Returns a pointer to a static buffer. Return value should be copied * if caller needs to hang onto it for a while. * * Fails for things like space, \e, quotes, some others. * Oh, well. */ char * CharToOutputStr (XChar c) { SpChar *sp; EscMap *em; static char buf[bufSiz]; if (Esc (c)) { c = FromEsc (c); /* see if this is a simple single-char escape */ for (em = escMap; em->emChar != '\0'; em++) { if (em->emChar == c) { sprintf (buf, "@%s", em->emStr); break; } } if (em->emChar == '\0') /* not in map */ { buf[0] = c; buf[1] = '\0'; } } else if (!Special (c)) { buf[0] = c; buf[1] = '\0'; } else if ((sp = LookupSpCharByCode (c)) != (SpChar *) NULL) (void) strcpy (buf, sp->spValue); else ETMPanic ("CharToOutputStr: logic error"); return (buf); } cialTextOut ("quotedblleft"); } else SpecialTextOut ("quoteleft"); } else if (c == '\'') { if (ChPeek () == '\'') { (void) ChIn (); SpecialTextOut ("quotedblright"); } else SpecialTextOut ("quoteright"); } else /* it's just plain text */ TextChOut (c); } if (lineIsBlank) /* line was blank; treated like .sp 1 */ { sprintf (buf, "%csp 1\n", ctrlChar); (void) XStrCpy (xbuf, StrToXStr troffcvt-1.04/troffcvt/req.c010064400017710000151000001000320634065352100176050ustar00junkyarddatamgmt00000400000027/* * Request action processors. * * The Axxx() routines all take the liberty of assuming that they're * called with the correct number of arguments (as defined in action.c), * although they check when need be to see whether arguments are empty * or numeric. */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "portlib.h" #include "etm.h" #include "memmgr.h" #include "troffcvt.h" #define maxDiversions 10 static void ScanMacroBody (Macro *mp, XChar *name, XChar *endMarker); static void AddCharToMacro (Macro *mp, XChar c); static void AddStrToMacro (Macro *mp, XChar *s); static void PushDiversion (XChar *name, int append); static void PopDiversion (void); static void DumpChar (char *name, XChar c); static void DumpTitlePart (int position, XChar *str); static XChar *diStack[maxDiversions]; static int nDiversions = 0; /* ------------------------------------------------------------- */ /* * Font and character size control */ int APointSize (int argc, XChar **argv) { SetSize (InterpretParam (argv[0], prevSize)); return (1); } /* * Set space size to N/36 em. Note that what is written out * is simply N; since the current space size is expressed in * terms of ems (and hence depends on current point size), any * postprocessor needs to tie actual space size to instantaneous * value of 1m. */ int ASpaceSize (int argc, XChar **argv) { Param val; if (EmptyArg (argv[0])) /* ignore if no argument */ return (0); val = InterpretParam (argv[0], (Param) 0); if (val < 0) val = 0; /*val = Units (val, 'm') / 36;*/ SetSpaceSize (val); return (1); } /* * This writes out only the name of the font that should be constant-spaced. * It doesn't write the font width value. */ int AConstantWidth (int argc, XChar **argv) { XChar buf[bufSiz]; XChar *font; char cbuf[bufSiz]; if ((font = GetFontName (argv[0])) == (XChar *) NULL) return (0); /* missing arguments are non-numeric, so this test catches those */ if (NumericArg (argv[1])) sprintf (cbuf, "constant-width %s", font); else sprintf (cbuf, "noconstant-width %s", font); ControlOut (cbuf); return (1); } /* * The argument vector can have 2 or 3 arguments, depending on whether * the original request format was * ".bd F N" or ".bd S F N". * * If N is missing/empty, turn emboldening off. */ int AEmbolden (int argc, XChar **argv) { char buf[bufSiz]; XChar *font; char *special = ""; Param smear; if (strcmp ("S", XStrToStr (argv[0])) == 0) /* .bd S F N */ { special= "-special"; --argc; ++argv; } if ((font = GetFontName (argv[0])) == (XChar *) NULL) return (0); smear = InterpretParam (argv[1], (Param) 0); sprintf (buf, "embolden%s %s %ld", special, XStrToStr (font), smear); ControlOut (buf); StrSetRegisterValue (".b", smear); return (1); } int AFont (int argc, XChar **argv) { if (!AsciiStr (argv[0])) { ETMMsg ("%snon-ASCII font name <%s>", FileInfo (), XStrToStr (argv[0])); return (0); } if (EmptyArg (argv[0])) SetFont (prevFont); else SetFont (argv[0]); return (1); } int AFontPosition (int argc, XChar **argv) { if (!AsciiStr (argv[0])) { ETMMsg ("%snon-ASCII font name <%s>", FileInfo (), XStrToStr (argv[0])); return (0); } if (!NumericArg (argv[0]) || EmptyArg (argv[1])) return (0); SetFontNameBySlot ((Param) StrToLong (XStrToStr (argv[0])), argv[1]); return (1); } /* ------------------------------------------------------------- */ /* * Page control */ int APageLength (int argc, XChar **argv) { SetPageLength (InterpretParam (argv[0], Units (11, 'i'))); return (1); } /* * begin-page and page-number are broken, because relative changes * aren't properly done - there isn't any way to know the current * page number! * * (A lame excuse; this should write out information the postprocessor * could use to determine that the change is relative.) */ int ABeginPage (int argc, XChar **argv) { char buf[bufSiz]; if (!NumericArg (argv[0])) ControlOut ("begin-page"); else { SetPageNumber ((Param) StrToLong (XStrToStr (argv[0]))); sprintf (buf, "begin-page %s", XStrToStr (argv[0])); ControlOut (buf); } return (1); } int APageNumber (int argc, XChar **argv) { if (NumericArg (argv[0])) SetPageNumber ((Param) StrToLong (XStrToStr (argv[0]))); return (1); } int AOffset (int argc, XChar **argv) { SetOffset (InterpretParam (argv[0], prevOffset)); return (1); } int ANeed (int argc, XChar **argv) { Param val; char buf[bufSiz]; val = InterpretParam (argv[0], Units (1, 'v')); sprintf (buf, "need %ld", val); ControlOut (buf); return (1); } /* ------------------------------------------------------------- */ /* * Text filling, adjusting and centering */ /* * Issue a break -- maybe. This checks whether a break should be * issued or not by checking whether the request was given with the * normal or no-break control character. * * "break" should be specified in the action list for any request * that normally causes a break. */ int ABreak (int argc, XChar **argv) { if (curCtrlChar == ctrlChar) Break (); return (1); } /* * Flush current output line if there is anything on it. This is like * break, but doesn't write \break, doesn't affect \c continuation, * and doesn't remove need for space character between lines. * (Basically, it's used to allow you to write \pass xxx output with * a guarantee that xxx will appear at the beginning of a new line.) */ int AFlush (int argc, XChar **argv) { FlushOText (); return (1); } /* * Turn filling on or off */ int AFill (int argc, XChar **argv) { SetCFA (centerCount, (Param) fill, adjust, adjMode); return (1); } int ANofill (int argc, XChar **argv) { SetCFA (centerCount, (Param) nofill, adjust, adjMode); return (1); } /* * Set adjustment type. If no type is given, use whatever the * value was before. Thus, ".ad" after ".na" will restore adjustment * and set it to what it was before being suppressed with ".na". * * Use of the .j register value as an argument is supported, but * its correct operation depends on adj{Center,Left,Right,Full} * values being single-digit and non-negative, since the .ad request * argument is probably parsed with the "parse-char" action. */ int AAdjust (int argc, XChar **argv) { Param mode = adjMode, adj = 1; if (Digit (argv[0][0])) /* probably had ".ad \n(.j" */ { adj = 0; if ((mode = (Param) (argv[0][0] - '0')) > 4) { adj = 1; mode -= 4; } } else switch (argv[0][0]) { case 'c': mode = adjCenter; break; case 'l': mode = adjLeft; break; case 'r': mode = adjRight; break; case 'b': case 'n': mode = adjFull; break; } SetCFA (centerCount, fillMode, adj, mode); return (1); } int ANoAdjust (int argc, XChar **argv) { SetCFA (centerCount, fillMode, (Param) 0, adjMode); return (1); } /* * Somewhat similar to .ad c but causes a break, takes a line count, * suppresses filling and adjusting, and turns off after a certain * number of input lines. * * If the count is missing, use 1. If the count is 0 (or negative!) * turn off centering, if it isn't already off. If count is positive, * turn centering on, if it isn't already on. */ int ACenter (int argc, XChar **argv) { Param count; if (!NumericArg (argv[0])) count = 1; else count = StrToLong (XStrToStr (argv[0])); if (count < 0) count = 0; SetCFA (count, fillMode, adjust, adjMode); return (1); } /* ------------------------------------------------------------- */ /* * Vertical spacing */ int ASpacing (int argc, XChar **argv) { SetSpacing (InterpretParam (argv[0], prevVSize)); return (1); } /* * Fractional values (e.g., .ls 1.5) are processed as just that, * even though troff truncates to integer values. */ int ALineSpacing (int argc, XChar **argv) { SetLineSpacing (InterpretParam (argv[0], prevLineSpacing)); return (1); } int ASpace (int argc, XChar **argv) { Param val; char buf[bufSiz]; val = InterpretParam (argv[0], Units (1, 'v')); sprintf (buf, "space %ld", val); ControlOut (buf); return (1); } /* * Argument is 'y if no-space mode should be turned on, 'n' if it * should be turned off. * * Actually: not implemented. */ int ANoSpace (int argc, XChar **argv) { return (0); } /* ------------------------------------------------------------- */ /* * Line length and indenting */ int ALineLength (int argc, XChar **argv) { SetLineLength (InterpretParam (argv[0], prevLineLen)); return (1); } int AIndent (int argc, XChar **argv) { SetIndent (InterpretParam (argv[0], prevIndent)); return (1); } int ATempIndent (int argc, XChar **argv) { if (EmptyArg (argv[0])) /* ignore if no argument */ return (0); SetTempIndent (InterpretParam (argv[0], (Param) 0)); return (1); } /* ------------------------------------------------------------- */ /* * Macro and string definitions */ /* * Define macro. Begin with a buffer of macroAllocSize XChars for holding the * macro body (may need to allocate more later). */ int ADefineMacro (int argc, XChar **argv) { Macro *mp; if (EmptyArg (argv[0])) /* no macro name */ return (0); if (Debug (bugMacroDef)) ETMMsg ("New macro %s", XStrToStr (argv[0])); mp = NewMacro (argv[0]); ScanMacroBody (mp, argv[0], argv[1]); return (1); } /* * Append to a macro (create it if it doesn't exist). */ int AAppendMacro (int argc, XChar **argv) { Macro *mp; if (EmptyArg (argv[0])) /* no macro name */ return (0); if ((mp = LookupMacro (argv[0])) == (Macro *) NULL) return (ADefineMacro (argc, argv)); ScanMacroBody (mp, argv[0], argv[1]); return (1); } /* * Scan current macro body. This is also used by .ig, in which * case mp is NULL. endMarker is non-empty if an explicit endMarker * was given, and is taken to be the name of a macro to invoke * after collecting the macro body. * * Note the ambiguity of ".de XX ." as opposed to ".de XX"; in both * cases the ending line is "..", but in the first case the macro "." * should be invoked after collecting the macro. (Wonder if that * was Ossanna's intent?) */ static void ScanMacroBody (Macro *mp, XChar *name, XChar *endMarker) { XChar defEndMarker[2] = { '.', 0 }; /* default is "." */ XChar *endMacro = (XChar *) NULL, *ep, *p; XChar c, cPrev; char *macroName; /* get name for debugging */ if (name != (XChar *) NULL) macroName = StrAlloc (XStrToStr (name)); else macroName = StrAlloc ("[ignore]"); if (EmptyArg (endMarker)) /* no explicit end marker */ endMarker = defEndMarker; else endMacro = endMarker; if (Debug (bugMacroDef)) { ETMMsg ("ScanMacroBody(%s): until <%s>", macroName, XStrToStr (endMarker)); } cPrev = lf; if (mp != (Macro *) NULL) p = mp->macBuf; CopyMode (1); for (;;) { if ((c = ChIn ()) == endOfInput) { ETMPanic ("%sEOF while scanning macro <%s> body", FileInfo (), macroName); } AddCharToMacro (mp, c); if (c == ctrlChar && Eol (cPrev)) { if (mp != (Macro *) NULL) p = &mp->macBuf[mp->macSiz-1]; for (ep = endMarker; *ep != '\0'; ep++) { if (Debug (bugMacroDef)) ETMMsg ("SMB: look for %s", XCharToStr (*ep)); if ((c = ChIn ()) == endOfInput) { ETMPanic ("%sEOF while scanning macro <%s> body", FileInfo (), macroName); } AddCharToMacro (mp, c); if (*ep != c) break; } if (*ep == 0 && Eol (ChPeek ())) /* found match */ { if (mp != (Macro *) NULL) mp->macSiz = (p - mp->macBuf); break; } } cPrev = c; } CopyMode (0); SkipToEol (); if (Debug (bugMacroDef)) { ETMMsg ("ScanMacroBody(%s) : found <%s>", macroName, XStrToStr (endMarker)); } if (endMacro != (XChar *) NULL) (void) PushMacro (endMacro, 0, NULL); Free (macroName); } /* * Add a character to a macro body. If it won't fit, reallocate * to get macroAllocSize XChars more space. * * mp is NULL if this is called during .ig. In this case the character * is simply discarded. */ static void AddCharToMacro (Macro *mp, XChar c) { XChar *p; int i; if (mp == (Macro *) NULL) return; if (mp->macSiz >= mp->macMaxSiz) { /* * Allocate bigger buffer, copy existing buffer into * it, then free the old buffer and install the new * one. Reset the max size indicator. */ p = (XChar *) VAlloc (mp->macMaxSiz + macroAllocSize, sizeof (XChar)); for (i = 0; i < mp->macSiz; i++) p[i] = mp->macBuf[i]; Free ((char *) mp->macBuf); mp->macBuf = p; mp->macMaxSiz += macroAllocSize; } mp->macBuf[mp->macSiz++] = c; } /* * Add a string to a macro body. */ static void AddStrToMacro (Macro *mp, XChar *s) { while (*s != '\0') AddCharToMacro (mp, *s++); } /* * Define a string. This really defines a macro, because a strings are * treated as macros without arguments. * * The first and second arguments are the name and value of the string. */ int ADefineString (int argc, XChar **argv) { Macro *mp; if (EmptyArg (argv[0])) return (0); mp = NewMacro (argv[0]); AddStrToMacro (mp, argv[1]); /*(void) NewString (argv[0], argv[1]);*/ return (1); } /* * Append to an existing string (create it if it doesn't exist). */ int AAppendString (int argc, XChar **argv) { Macro *mp; if ((mp = LookupMacro (argv[0])) == (Macro *) NULL) return (ADefineString (argc, argv)); AddStrToMacro (mp, argv[1]); return (1); } /* * Rename request, macro or string name */ int ARenameName (int argc, XChar **argv) { Name *np; if (EmptyArg (argv[0]) || EmptyArg (argv[1])) return (0); if ((np = LookupName (argv[0], reqDef|macDef)) == (Name *) NULL) return (0); RenameName (np, argv[1]); return (1); } /* * Remove a list of names. If argv[0][0] is 'y', remove number registers, * otherwise remove string, request, macro names. * * Used for .rm and .rr. troff manual doesn't say it, but these * requests can be given multiple arguments. Since the troffcvt mechanism * for passing arguments to post-parsing action functions requires a fixed * number of arguments, the post-parsing actions for those requests call * this function a number of times with different ranges of arguments from * the parsing section, to make sure all the names get passed. Most of * them will be empty most of the time, so this ignores empty arguments. */ int ARemoveNames (int argc, XChar **argv) { Register *rp; XChar *p; int i; int isNumReg; if (argc < 1) ETMPanic ("ARemoveNames: insufficient arguments"); isNumReg = (argv[0][0] == 'y'); /* 1 if number, 0 if not */ for (i = 1; i < argc; i++) { p = argv[i]; if (EmptyArg (p)) continue; if (isNumReg && (rp = LookupRegister (p)) != (Register *) NULL) { if (rp->regReadOnly) { ETMMsg ("%scannot remove readonly register <%s>", FileInfo (), XStrToStr (p)); continue; } } RemoveNamedObject (p, isNumReg ? regDef : reqDef|macDef); } return (1); } int AEndMacro (int argc, XChar **argv) { XStrFree (endMacro); if (LookupMacro (argv[0]) == (Macro *) NULL) { ETMMsg ("%sunknown end macro: %s", FileInfo (), XStrToStr (argv[0])); } endMacro = XStrAlloc (argv[0]); return (1); } int AInputTrap (int argc, XChar **argv) { XStrFree (itMacro); itCount = 0; if (NumericArg (argv[0]) && !EmptyArg (argv[1])) { if (LookupMacro (argv[1]) == (Macro *) NULL) { ETMMsg ("%sunknown input trap macro: %s", FileInfo (), XStrToStr (argv[1])); } itMacro = XStrAlloc (argv[1]); itCount = InterpretParam (argv[0], (Param) 0); } return (1); } int ADiversion (int argc, XChar **argv) { if (EmptyArg (argv[0])) /* terminate current diversion */ PopDiversion (); else /* begin new diversion */ PushDiversion (argv[0], 0); return (1); } int AAppendDiversion (int argc, XChar **argv) { if (EmptyArg (argv[0])) /* terminate current diversion */ PopDiversion (); else /* append to existing diversion */ PushDiversion (argv[0], 1); return (1); } XChar * CurrentDiversion (void) { static XChar nullDiversionName[1] = { 0 }; if (nDiversions < 1) return (nullDiversionName); return (diStack[nDiversions-1]); } /* * Copy diversion name into stack and indicate start (or continuation) * of diversion. * * Diversion names can be written directly to output, so they must be * plain ASCII names. That constraint is enforced here. */ static void PushDiversion (XChar *name, int append) { char buf[bufSiz]; if (!AsciiStr (name)) { ETMMsg ("%snon-ASCII diversion name <%s>", FileInfo (), XStrToStr (name)); return; } if (nDiversions >= maxDiversions) ETMPanic ("%sPushDiversion: diversion stack overflow", FileInfo ()); diStack[nDiversions++] = XStrAlloc (name); sprintf (buf, "diversion-%s %s", append ? "append" : "begin", XStrToStr (name)); ControlOut (buf); } /* * Indicate end of diversion, free storage for name. */ static void PopDiversion (void) { char buf[bufSiz]; if (nDiversions > 0) { sprintf (buf, "diversion-end %s", XStrToStr (diStack[--nDiversions])); ControlOut (buf); XStrFree (diStack[nDiversions]); } } /* ------------------------------------------------------------- */ /* * Define a number register. If the register existed before, * use previous increment and format if corresponding arguments * are empty. (Actually, old format is ignored, since formats * are pretty well broken anyway.) */ int ADefineRegister (int argc, XChar **argv) { Register *rp; Param value = 0, oldValue = 0, oldIncr = 0; Param increment = 0; char *p; if (EmptyArg (argv[0])) return (0); if ((rp = LookupRegister (argv[0])) != (Register *) NULL) { oldValue = rp->regValue; oldIncr = rp->regIncrement; if (rp->regReadOnly) { ETMMsg ("attempt to set readonly register <%s> ignored", XStrToStr (argv[0])); return (0); } } value = InterpretParam (argv[1], oldValue); increment = InterpretParam (argv[2], oldIncr); p = StrAlloc (XStrToStr (argv[0])); rp = StrNewRegister (p, value, increment, "1", 0); Free (p); return (1); } int ARegisterFormat (int argc, XChar **argv) { Register *rp; if (EmptyArg (argv[1])) return (0); if ((rp = LookupRegister (argv[0])) == (Register *) NULL) return (0); SetRegisterFormat (rp, argv[1]); return (1); } /* ------------------------------------------------------------- */ int ASetTabChar (int argc, XChar **argv) { tabChar = InterpretCharParam (argv[0], '\0'); DumpChar ("tab-char", tabChar); return (1); } int ASetLeaderChar (int argc, XChar **argv) { leaderChar = InterpretCharParam (argv[0], '\0'); DumpChar ("leader-char", leaderChar); return (1); } /* * Dump a character name control word and optionally the character's * value. */ static void DumpChar (char *name, XChar c) { char buf[bufSiz]; if (c == 0) ControlOut (name); else if (c == '"' || c == '\\') { sprintf (buf, "%s \"\\%c\"", name, c); ControlOut (buf); } else { sprintf (buf, "%s %s", name, CharToOutputStr (c)); ControlOut (buf); } } int ASetFieldChars (int argc, XChar **argv) { if (EmptyArg (argv[0]) && EmptyArg (argv[1])) { fieldDelimChar = '\0'; /* turn field mechanism off */ fieldPadChar = '\0'; } else { fieldDelimChar = InterpretCharParam (argv[0], '\0'); fieldPadChar = InterpretCharParam (argv[1], ' '); } return (1); } /* ------------------------------------------------------------- */ /* * Escape character cannot be an escaped character \x or special * character \(xx since then it would be recursive. */ int ASetEscape (int argc, XChar **argv) { if (EmptyArg (argv[0])) escChar = defEscChar; else if (AsciiStr (argv[0])) escChar = argv[0][0]; else ETMMsg ("illegal escape character: <%s>", XStrToStr (argv[0])); doEscapes = 1; return (1); } int ANoEscape (int argc, XChar **argv) { doEscapes = 0; return (1); } /* ------------------------------------------------------------- */ int AUnderline (int argc, XChar **argv) { Param count; count = InterpretParam (argv[0], (Param) 1); if (count < 0) count = 0; SetUnderline (count, 0); return (1); } int ACUnderline (int argc, XChar **argv) { Param count; count = InterpretParam (argv[0], (Param) 1); if (count < 0) count = 0; SetUnderline (0, count); return (1); } int AUnderlineFont (int argc, XChar **argv) { char buf[bufSiz]; XChar *font; if (!AsciiStr (argv[0])) { ETMMsg ("%snon-ASCII font name <%s>", FileInfo (), XStrToStr (argv[0])); return (0); } if ((font = GetFontName (argv[0])) == (XChar *) NULL) return (0); sprintf (buf, "underline-font %s", XStrToStr (font)); ControlOut (buf); return (1); } /* ------------------------------------------------------------- */ /* * Control character operations */ int ASetControl (int argc, XChar **argv) { ctrlChar = InterpretCharParam (argv[0], defCtrlChar); return (1); } int ASetControl2 (int argc, XChar **argv) { ctrlChar = InterpretCharParam (argv[0], defNbCtrlChar); return (1); } /* ------------------------------------------------------------- */ /* * Transliteration */ int ATransliterate (int argc, XChar **argv) { XChar *p = argv[0]; int c1, c2; while ((c1 = *p) != '\0') { if (*++p != '\0') c2 = *p++; else c2 = ' '; Transliterate (c1, c2); } return (1); } /* ------------------------------------------------------------- */ /* * Hyphenation */ /* * Turn hyphenation on or off. 0 = off, empty defaults to 1. * Values are as described in troff manual. */ int AHyphenation (int argc, XChar **argv) { SetHyphenation (InterpretParam (argv[0], (Param) 1)); return (1); } /* * Set the optional-hyphenation character. */ int ASetHyphenChar (int argc, XChar **argv) { optHyphenChar = InterpretCharParam (argv[0], ToEsc ('%')); return (1); } /* ------------------------------------------------------------- */ /* * Titles */ /* * Dump all parts of a three-part title. If a part is empty or missing, * dump an empty part. */ int ATitle (int argc, XChar **argv) { DumpTitlePart ('l', argc >= 1 ? argv[0] : (XChar *) NULL); DumpTitlePart ('m', argc >= 2 ? argv[1] : (XChar *) NULL); DumpTitlePart ('r', argc >= 3 ? argv[2] : (XChar *) NULL); return (1); } static void DumpTitlePart (int position, XChar *str) { char buf[bufSiz]; sprintf (buf, "title-begin %c", position); /* l, m, or r */ ControlOut (buf); TextXStrOut (str); ControlOut ("title-end"); } /* * Set, or remove, page number character */ int APageNumChar (int argc, XChar **argv) { pageNumChar = InterpretCharParam (argv[0], '\0'); return (1); } /* * Set title length */ int ATitleLength (int argc, XChar **argv) { SetTitleLength (InterpretParam (argv[0], prevTitleLen)); return (1); } /* ------------------------------------------------------------- */ /* * Environments */ int AEnvironment (int argc, XChar **argv) { if (EmptyArg (argv[0])) /* revert to previous environment*/ PopEnvironment (); else /* enter new environment */ PushEnvironment (argv[0]); return (1); } /* ------------------------------------------------------------- */ int AExit (int argc, XChar **argv) { allowInput = 0; return (1); } int AAbort (int argc, XChar **argv) { char *p = "User abort"; if (!EmptyArg (argv[0])) p = XStrToStr (argv[0]); ETMPanic ("%s", p); return (1); } /* * Push a file on the input stack. search is non-zero if DoPushFile() * should look for the file the way it looks for macro files. */ static int DoPushFile (int argc, XChar **argv, short search) { char buf[bufSiz], *p; /* on error, say something but don't exit */ if (EmptyArg (argv[0])) { ETMMsg ("%sMissing filename for push-%sfile", FileInfo (), search ? "macro-" : ""); } else if (!AsciiStr (argv[0])) { ETMMsg ("%snon-ASCII filename for push-%sfile <%s>", FileInfo (), search ? "macro-" : "", XStrToStr (argv[0])); } else { /* PushFile() takes a char* string */ (void) strcpy (buf, XStrToStr (argv[0])); p = (char *) NULL; if (search) p = FindMacroFile (buf); /* * The following sets p to buf if: (i) searching isn't on, or * (ii) searching is on but the file wasn't found. Setting p * to buf in the latter case is safe; PushFile() will fail * and the error message will be printed. */ if (p == (char *) NULL) p = buf; if (PushFile (p)) return (1); ETMMsg ("%scannot open \"%s\" for push-%sfile", FileInfo (), buf, search ? "macro-" : ""); } return (0); } int APushFile (int argc, XChar **argv) { return (DoPushFile (argc, argv, 0)); } int APushMacroFile (int argc, XChar **argv) { return (DoPushFile (argc, argv, 1)); } /* * Shift macro arguments by n positions if numeric argument is given, * by 1 if no argument is given. Ignore if non-numeric argument given, * or n is negative. */ int AShiftArguments (int argc, XChar **argv) { short shift; if (EmptyArg (argv[0])) shift = 1; else if (NumericArg (argv[0])) { shift = StrToShort (argv[0]); if (shift < 0) { ETMMsg ("%snegative argument shift amount: %hd", FileInfo (), shift); return (0); } } ShiftMacroArguments (shift); return (1); } int ASwitchFile (int argc, XChar **argv) { char buf[bufSiz]; /* SwitchFile() takes a char* string */ (void) strcpy (buf, XStrToStr (argv[0])); /* on error, say something and exit */ if (EmptyArg (argv[0])) { ETMPanic ("%sMissing filename for switch-file", FileInfo ()); } if (!AsciiStr (argv[0])) { ETMMsg ("%snon-ASCII filename for switch-file <%s>", FileInfo (), buf); } else if (!SwitchFile (buf)) { ETMPanic ("%scannot open \"%s\" for switch-file", FileInfo (), buf); } return (1); } /* ------------------------------------------------------------- */ /* * Read rest of request line and echo to stderr. Used for .tm, * but can be useful for debugging argument parsing, too. */ int AEcho (int argc, XChar **argv) { ETMMsg ("%s", XStrToStr (argv[0])); return (1); } /* * Ignore input for a while */ int AIgnore (int argc, XChar **argv) { ScanMacroBody ((Macro *) NULL, (XChar *) NULL, argv[0]); return (1); } /* ------------------------------------------------------------- */ /* * Set compatibility mode. (Sets compatMode variable, .C register) * * If the argument is missing/non-numeric or non-zero, enable compatibility * mode. If the argument is zero, disable compatibility mode. Long names * are not recognized when the mode is enabled. */ int ASetCompatibility (int argc, XChar **argv) { Param newCompat = 1; /* default if argument missing or non-numeric */ if (NumericArg (argv[0])) /* present and numeric */ newCompat = (StrToLong (XStrToStr (argv[0])) != 0); (void) SetCompatMode (newCompat); return (1); } /* ------------------------------------------------------------- */ /* * Alias stuff */ /* * Alias a macro (or string or request). */ int AAliasMacro (int argc, XChar **argv) { Name *np; if (argc < 2) return (0); if (XStrCmp (argv[0], argv[1]) == 0) { ETMMsg ("%syou cannot alias <%s> to itself", FileInfo (), XStrToStr (argv[0])); return (0); } np = LookupName (argv[1], reqDef|macDef); if (np == (Name *) NULL) { ETMMsg ("%syou cannot alias to non-existing name <%s>", FileInfo (), XStrToStr (argv[1])); return (0); } switch (np->nObject->oType) { default: ETMPanic ("AAliasMacro: logic error"); case reqDef: case macDef: NewName (argv[0], np->nObject, np->nObject->oType); break; } return (1); } /* * Alias a register. */ int AAliasRegister (int argc, XChar **argv) { Name *np; if (argc < 2) return (0); if (XStrCmp (argv[0], argv[1]) == 0) { ETMMsg ("%syou cannot alias <%s> to itself", FileInfo (), XStrToStr (argv[0])); return (0); } np = LookupName (argv[1], regDef); if (np == (Name *) NULL) { ETMMsg ("%syou cannot alias to non-existing register <%s>", FileInfo (), XStrToStr (argv[1])); return (0); } NewName (argv[0], np->nObject, np->nObject->oType); return (1); } /* ------------------------------------------------------------- */ /* * Miscellaneous actions that don't really correspond to * any particular request. */ /* * Define a special character. This isn't a troff request, but * it allows the list of known special characters to be specified in * an action file at run time. * * First arg is the special char name, second is the string to * output when character is referenced. The output string cannot * be empty (this is to allow the .if c test to tell whether a * special character was ever defined by checking whether or not * the value is empty.) * * If the character is already defined, just replace the value. * Otherwise add it to the list. */ int ASpecialChar (int argc, XChar **argv) { if (EmptyArg (argv[0])) { ETMMsg ("%sspecial char name is empty", FileInfo ()); return (0); } if (EmptyArg (argv[1])) { ETMMsg ("%svalue of special char <%s> is empty", FileInfo (), XStrToStr (argv[0])); return (0); } (void) NewSpChar (argv[0], argv[1]); return (1); } /* * Push a string onto the input stack to interpolate it into * the input stream. Force it to be processed immediately * until the string is exhausted. Then restart whatever was * already on the input stack and return. */ int APushStr (int argc, XChar **argv) { PushAnonString (argv[0], 1); ReadInput (); ResumeInput (); return (1); } /* * Skip to the end of the current line */ int AEol (int argc, XChar **argv) { SkipToEol (); return (1); } /* * AWrite{Control,Text,Special} should not contain escaped or * special characters... */ int AWriteControl (int argc, XChar **argv) { char *p; p = StrAlloc (XStrToStr (argv[0])); if (!AsciiStr (argv[0])) ETMMsg ("AWriteControl: warning: non-ASCII string <%s>", p); ControlOut (p); Free (p); return (1); } int AWriteText (int argc, XChar **argv) { XChar *p; p = argv[0]; if (!AsciiStr (p)) ETMMsg ("AWriteText: warning: non-ASCII string <%s>", XStrToStr (p)); while (*p != '\0') TextChOut (*p++); return (1); } int AWriteSpecial (int argc, XChar **argv) { char *p; p = StrAlloc (XStrToStr (argv[0])); if (!AsciiStr (argv[0])) ETMMsg ("AWriteSpecial: warning: non-ASCII string <%s>", p); SpecialTextOut (p); Free (p); return (1); } int ADebugFlag (int argc, XChar **argv) { Param val; /* missing arguments are non-numeric, so this test catches those */ if (!NumericArg (argv[0])) debug = 0xffffffff; else if ((val = InterpretParam (argv[0], (Param) 0)) < 0) debug = 0; else debug |= 1L<: not found", XStrToStr (argv[0])); else { ETMMsg ("Macro <%s> body:", XStrToStr (argv[0])); if ((p = mp->macBuf) != (XChar *) NULL) { for (i = 0; i < mp->macSiz; i++) { cp = XCharToStr (*p++); fwrite (cp, 1, strlen (cp), stderr); } } ETMMsg ("-------"); } return (1); } /* * Turn dumping of bad requests on \other lines on or off. The * argument should be 1 or 0. A missing argument is interpreted * as 0. */ int ADumpBadRequests (int argc, XChar **argv) { dumpBadReq = (InterpretParam (argv[0], (Param) 0) != 0); return (1); } /* * Dump out information about the input stack. */ int ADumpInputStack (int argc, XChar **argv) { DumpInputStack (); } /* ------------------------------------------------------------- */ /* * Look at a string, return its value. String should be empty or * represent a number. If empty, return default value. If represents * a number, look at last char to see if it's a units indicator. If * it is, use it to convert number to basic units. */ Param InterpretParam (XChar *s, Param defValue) { char buf[bufSiz]; int unit; int len; /* missing arguments are non-numeric, so this test catches those */ if (!NumericArg (s)) return (defValue); /* * If it's a numeric argument, it's also an ASCII string, so convert * to a char* string and work with that. */ (void) strcpy (buf, XStrToStr (s)); if ((len = strlen (buf)) > 0 && UnitChar (unit = buf[len-1])) buf[len-1] = '\0'; /* chop off the units character */ else unit = 'u'; return (Units (StrToDouble (buf), unit)); } /* * Interpret s to find the value of some sort of single-character parameter * (e.g., the tab or field character, or the control char). If s is * an empty argument, use the default value. */ int InterpretCharParam (XChar *s, int defValue) { if (EmptyArg (s)) return (defValue); return (s[0]); } turn (1); } /* * Set title length */ int ATitleLength (int argc, XChar **argv) { SetTitleLength (InterpretParam (argv[0], prevTitleLen)); return (1); } /* ------------------------------------------------------------- */ /* * Environments */ int AEnvironment (int argc, XChar **argv) { if (EmptyArg (argv[0])) /* revert to previous environment*/ PopEnvironment (); else /* enter new environment */ PushEnvironment (argv[0]); return (1); } /* -------------------troffcvt-1.04/troffcvt/setget.c010064400017710000151000000310340633512124300203110ustar00junkyarddatamgmt00000400000027/* * Underline setting isn't really correct yet. * * Routines for setting various processing parameters and writing out * their values if they've changed. */ #include #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "etm.h" #include "troffcvt.h" #define Max(a,b) (a > b ? a : b) static void SpitSetting (char *name, Param cur, Param new, Param lower); static Param GetFontNumber (XChar *p); void SetPageLength (Param val) { char buf[bufSiz]; if (val != curPageLen) { sprintf (buf, "page-length %ld", val); ControlOut (buf); curPageLen = val; StrSetRegisterValue (".p", curPageLen); } } /* * Set centering, filling, adjusting stuff. Test the various modes, * from lowest priority to highest, to figure out which control to * write out. At the end, compare it with the one last written to * determine whether it really needs to be written. * * This has the property of setting all four state variables properly * and keeping them up to date internally, while writing only the * current setting explicitly so postprocessors don't have to mess * with interactions between them. */ void SetCFA (Param nCenter, Param nFill, Param nAdjust, Param nAdjMode) { static char *lastSetting = ""; char *p = ""; switch (adjMode = nAdjMode) { case adjLeft: p = "adjust-left"; break; case adjRight: p = "adjust-right"; break; case adjFull: p = "adjust-full"; break; case adjCenter: p = "adjust-center"; break; } if ((adjust = nAdjust) == 0) p = "adjust-left"; if ((fillMode = nFill) == nofill) p = "nofill"; if (nCenter < 0) /* fix first if necessary */ nCenter = 0; if ((centerCount = nCenter) > 0) p = "center"; if (strcmp (p, lastSetting) != 0) /* setting's changed */ ControlOut (lastSetting = p); StrSetRegisterValue (".u", (Param) (fillMode == fill)); StrSetRegisterValue (".j", (Param) (adjMode + (adjust ? 4 : 0))); } /* * Set the underlining properly, turning it on or off depending * on the current state and the new state. If both are positive * regular ul takes precedence over continuous ul. * * Default is to assume it's off, and turn on if find out otherwise. */ void SetUnderline (Param ul, Param cul) { static char *lastSetting = ""; char *p = "nounderline"; if (ul < 0) ul = 0; if (cul < 0) cul = 0; if ((cUlCount = cul) > 0) /* turn cul on */ p = "cunderline"; if ((ulCount = ul) > 0) /* turn ul on */ p = "underline"; if (strcmp (p, lastSetting) != 0) /* setting's changed */ ControlOut (lastSetting = p); } /* * .ft 0 and \f0 are equivalent; they refer to last named but never * mounted font. * * It is necessary that new be a copy of the argument passed in if * the argument isn't a number, otherwise SetFont(prevFont) would * set curFont, but not cycle curFont into prevFont. */ void SetFont (XChar *name) { XChar new[maxFontNameLen], *p; char buf[bufSiz]; Param number; if (name == (XChar *) NULL || XStrLen (name) >= maxFontNameLen) return; if (!AsciiStr (name)) { ETMMsg ("%snon-ASCII font name", FileInfo (), XStrToStr (name)); return; } new[0] = '\0'; /* empty font name */ if (name[0] == 'P' && name[1] == '\0') /* revert to previous */ (void) XStrCpy (new, prevFont); else if ((p = GetFontName (name)) != (XChar *) NULL) (void) XStrCpy (new, p); if (new[0] == '\0') /* didn't find it */ return; if (XStrCmp (new, curFont) != 0) { sprintf (buf, "font %s", XStrToStr (new)); ControlOut (buf); } (void) XStrCpy (prevFont, curFont); (void) XStrCpy (curFont, new); if ((number = GetFontNumber (curFont)) < 0) { number = 0; SetFontNameBySlot (number, curFont); } StrSetRegisterValue (".f", number); } /* * Given a font reference as a number or name, return the name * or NULL if the reference is bad. */ XChar * GetFontName (XChar *p) { if (p != (XChar *) NULL && Digit (*p)) { if (*(p+1) != 0) /* only one digit allowed */ return ((XChar *) NULL); /* this will be NULL if bad */ p = GetFontNameBySlot ((Param) (*p - '0')); } if (p == (XChar *) NULL || *p == 0) /* null or empty? */ return ((XChar *) NULL); return (p); } static Param GetFontNumber (XChar *p) { Param i; for (i = 0; i < maxFonts; i++) { if (fontTab[i] != (XChar *) NULL && XStrCmp (fontTab[i], p) == 0) return (i); } return ((Param) -1); } /* * The zeroth font table entry is reserved. troff uses position 0 * for the hidden font (the last named, but unmounted font) */ XChar * GetFontNameBySlot (Param pos) { if (pos < 0 || pos >= maxFonts) return ((XChar *) NULL); return (fontTab[pos]); } void SetFontNameBySlot (Param pos, XChar *name) { int len; if (pos < 0 || pos >= maxFonts) return; if (name == (XChar *) NULL || (len = XStrLen (name)) == 0 || len >= maxFontNameLen) return; if (!AsciiStr (name)) { ETMMsg ("%snon-ASCII font name <%s>", FileInfo (), XStrToStr (name)); return; } (void) XStrCpy (fontTab[pos], name); } /* * If format isn't recognized, defaults are used. */ void SetRegisterFormat (Register *rp, XChar *format) { int fmt = numFmt, fmtWidth = 0; /* * I suppose this should really check that ALL characters * are numeric, but then what does it mean if they're not? */ if (Digit (*format)) { if (XStrLen (format) > 1) /* else leave at 0 */ fmtWidth = XStrLen (format); } else switch (*format) { case 'i': fmt = lRomanFmt; break; case 'I': fmt = uRomanFmt; break; case 'a': fmt = lAlphaFmt; break; case 'A': fmt = uAlphaFmt; break; } rp->regFormat = fmt; rp->regFmtWidth = fmtWidth; } /* * Format a register value and return a pointer to the (static) * string result. Registers with i, I, a or A format are number * formatted if the value is less than 1. * * Roman and Alphabetic are broken. The former isn't even attempted, * and the algorithm for the latter doesn't always work. I'm too * lazy to fix it right now. */ XChar * FormatRegister (Register *rp) { static XChar xbuf[bufSiz]; char buf[bufSiz]; char *p = buf; Param value = rp->regValue; int format = rp->regFormat; int wid = rp->regFmtWidth; int i, n; if (1 /* format == numFmt || value < 1 */ ) { if (wid == 0) sprintf (buf, "%ld", value); else sprintf (buf, "%0*ld", wid, value); } else if (format == lAlphaFmt || format == uAlphaFmt) { n = 1; while (n <= value) { n *= 26; if (n < 0) /* uh-oh...underflow */ ETMPanic ("FormatRegister: numeric underflow"); } while (n > 1) { n /= 26; i = 0; *p = 'a'; while (value > n) { value -= n; (*p)++; } ++p; } *p = '\0'; } else /* format is roman */ { sprintf (buf, "%ld", value); /* wimp out for now */ } /* now uppercase the string if necessary */ if (format == uAlphaFmt || format == uRomanFmt) { for (p = buf; *p != '\0'; p++) { if (islower (*p)) *p = toupper (*p); } } (void) XStrCpy (xbuf, StrToXStr (buf)); return (xbuf); } Param GetRegisterValue (XChar *name) { Register *rp; if ((rp = LookupRegister (name)) == (Register *) NULL) return ((Param) 0); return (rp->regValue); } /* * Perhaps this should auto-create registers? */ void SetRegisterValue (XChar *name, Param val) { Register *rp; if ((rp = LookupRegister (name)) == (Register *) NULL) { ETMMsg ("%sattempt to set non-existent register <%s>", FileInfo (), XStrToStr (name)); } else rp->regValue = val; } /* * Versions of {Get,Set}RegisterValue() that can be used when you KNOW * you have a register name that can be expressed with ASCII characters. */ Param StrGetRegisterValue (char *name) { Register *rp; XChar xname[bufSiz]; (void) XStrCpy (xname, StrToXStr (name)); return (GetRegisterValue (xname)); } void StrSetRegisterValue (char *name, Param val) { Register *rp; XChar xname[bufSiz]; (void) XStrCpy (xname, StrToXStr (name)); SetRegisterValue (xname, val); } /* * The following SetXXX() routines maintain the asked-for value * internally, to maintain the integrity of matching relative * changes (e.g., .xx -N followed by .xx +N), but won't write out * ridiculous values. Instead they write out a lower-limit value * instead. * * Some parameters need to be clipped, however (e.g., indent, line * length). For those, cur should be clipped before calling * SpitSetting(). */ static void SpitSetting (char *name, Param cur, Param new, Param lower) { char buf[bufSiz]; if (cur != new) { sprintf (buf, "%s %ld", name, Max (lower, new)); ControlOut (buf); } } /* * Point size is maintained in points, not units. */ void SetSize (Param val) { SpitSetting ("point-size", curSize, val, Units (1, 'x')); prevSize = curSize; curSize = val; StrSetRegisterValue (".s", curSize); } void SetSpaceSize (Param val) { SpitSetting ("space-size", curSpaceSize, val, Units (0, 'x')); curSpaceSize = val; } /* * groff allows page offset to be set negative, but no other * troff/nroff/*roff I've found does so, so value is clipped * to zero here. */ void SetOffset (Param val) { val = Max (val, Units (0, 'i')); /* can't set negative */ SpitSetting ("offset", curOffset, val, Units (0, 'i')); prevOffset = curOffset; curOffset = val; StrSetRegisterValue (".o", curOffset); } void SetSpacing (Param val) { SpitSetting ("spacing", curVSize, val, Units (1, 'p')); prevVSize = curVSize; curVSize = val; StrSetRegisterValue (".v", curVSize); } void SetLineSpacing (Param val) { val = Max (val, Units (1, 'x')); /* can't set < 1 */ SpitSetting ("line-spacing", curLineSpacing, val, Units (1, 'x')); prevLineSpacing = curLineSpacing; curLineSpacing = val; StrSetRegisterValue (".L", curLineSpacing); } void SetLineLength (Param val) { val = Max (val, Units (0.1, 'i')); /* can't set < .1i */ SpitSetting ("line-length", curLineLen, val, Units (0.1, 'i')); prevLineLen = curLineLen; curLineLen = val; StrSetRegisterValue (".l", curLineLen); } /* * Write indentation value. Cannot indent left to a negative value. * * Pass val+1 for "current" value because it's possible that, although the * indent may not actually have changed, the temp indent was set. If so, * the indent has to be forced out to override that. So force it to print * on every occurrence. */ void SetIndent (Param val) { val = Max (val, Units (0, 'i')); /* can't set negative */ SpitSetting ("indent", val + 1, val, Units (0, 'i')); prevIndent = curIndent; curIndent = val; StrSetRegisterValue (".i", curIndent); } /* * Set temporary indent. This is written out as \temp-indent n, where * n is an absolute value. When .ti is given a relative argument, the * resulting indent is calculated relative to current indent, not the * current temp indent (this happens by specifying the indent amount * in the actions file as the value to use for relative settings). * * Successive temp-indents before next output line don't cascade; each * overrides the previous one. * * If a "regular" indent is set after a temp indent and before the next * text, the regular indent cancels the temp indent. * * Cannot temp-indent left to a negative value. * * Pass val+1 for "current" value because this parameter has * an effect only transiently and we can't tell whether it's * still in effect or not. So force it to print on every * occurrence. */ void SetTempIndent (Param val) { SpitSetting ("temp-indent", val + 1, val, Units (0, 'i')); curTempIndent = val; } void SetHyphenation (Param val) { char buf[bufSiz]; if (val != curHyphenMode) { sprintf (buf, "hyphenate %ld", val); ControlOut (buf); } curHyphenMode = val; } void SetTitleLength (Param val) { val = Max (val, Units (0, 'i')); /* can't set negative */ SpitSetting ("title-length", curTitleLen, val, Units (0, 'i')); prevTitleLen = curTitleLen; curTitleLen = val; } void SetPageNumber (Param val) { SpitSetting ("page-number", curPageNum, val, Units (-99999, 'x')); StrSetRegisterValue ("%", curPageNum = val); } void SetTabStops (Param n, Param *pos, char *type) { char buf[bufSiz]; int same = 1; /* assume all same until know otherwise */ int i; if (n != curTabCount) same = 0; else for (i = 0; i < curTabCount; i++) { if (pos[i] != tabPos[i] || type[i] != tabType[i]) { same = 0; break; } } if (same) return; /* no output necessary */ if ((curTabCount = n) == 0) ControlOut ("reset-tabs"); else for (i = 0; i < curTabCount; i++) { tabPos[i] = pos[i]; tabType[i] = type[i]; sprintf (buf, "%s-tab %ld %c", i == 0 ? "first" : "next", tabPos[i], tabType[i]); ControlOut (buf); } } /* * Set compatibility mode, returning previous value */ Param SetCompatMode (Param newCompat) { Param prevCompat = compatMode; compatMode = newCompat; StrSetRegisterValue (".C", compatMode); return (prevCompat); } \f0 are equivalent; they refer to last named but never * mounted font. * * It is necessary that new be a copy of the argument passed in if * the argument isn't a number, otherwise SetFont(prevFont) would * set curFont, but not cycle curFont into prevFont. */ void SetFont (XChar *name) { XChar new[maxFontNameLen], *p; char buf[bufSiz]; Param number; if (name == (XChar *) NULL || XStrLen (name) >= maxFontNameLen) return; if (!AsciiStr (name)) { ETMMsg ("%snon-ASCII ftroffcvt-1.04/troffcvt/units.c010064400017710000151000000040030626662670400201730ustar00junkyarddatamgmt00000400000027/* * Unit conversion and formatting stuff. * * The basis for this comes from the troff manual, section 1.3, * although the basic resolution may be different. * * 1 point = 1/72 in. * 1 Pica = 1/6 in. * * Unit indicator 'x' means "ignore explicit unit indicators". */ #include #include #include "etm.h" #include "troffcvt.h" /* * Convert a number into basic units */ Param ToBU (double n, int u) { Param param; switch (u) { case 'x': /* ignore unit indicator */ case 'u': param = (Param) n; break; case 'v': param = (Param) (n * curVSize); break; case 'p': /* p = 1/72 in. */ param = (Param) ((n * resolution) / 72.0); break; case 'n': param = (Param) ((n * resolution * curSize) / 144.0); break; case 'm': param = (Param) ((n * resolution * curSize) / 72.0); break; case 'P': /* P = 1/6 in. */ param = (Param) ((n * resolution) / 6.0); break; case 'c': param = (Param) ((n * resolution * 50.0)/127.0); break; case 'i': param = (Param) (n * resolution); break; default: ETMPanic ("ToBU: bad units indicator <%c>", u); } return (param); } /* * Convert a number from basic units into some other unit. */ double FromBU (Param n, int u) { double v; switch (u) { case 'x': /* x = ignore unit indicator */ case 'u': /* u = already in basic units */ v = (double) n; break; case 'v': v = ((double) n / (double) curVSize); break; case 'p': v = ((double) (n * 72.0) / (double) resolution); break; case 'n': v = (Param) ((n * 144.0) / (double) (resolution * curSize)); /*v = ((double) (n * 2.0) / (double) curSize);*/ break; case 'm': v = (Param) ((n * 72.0) / (double) (resolution * curSize)); /*v = ((double) n / (double) curSize);*/ break; case 'P': v = ((double) (n * 6.0) / (double) resolution); break; case 'c': v = ((double) (n * 127.0) / ((double) (resolution * 50.0))); break; case 'i': v = ((double) n / (double) resolution); break; default: ETMPanic ("FromBU: bad units indicator <%c>", u); } return (v); } troffcvt-1.04/troffcvt/environ.c010064400017710000151000000124740630076532400205130ustar00junkyarddatamgmt00000400000027/* * Environment-switching stuff. */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "etm.h" #include "memmgr.h" #include "troffcvt.h" #define maxEStack 10 /* more than necessary? */ static void SaveEnvironment (Environ *ep); static void RestoreEnvironment (Environ *ep); static Environ *FindEnvironment (XChar *name); /* * envList is a list of the currently known environments * eStack is a stack of the currently in-use environments */ static Environ *envList = (Environ *) NULL; static Environ *eStack[maxEStack]; static int esTop = -1; /* * Initialize environments with the names "0", "1", and "2" to the * current defaults (creating the environments as necessary). This is * called once before reading any action files to set the environments * to the built-in defaults. It's called again if the default action * file is read, to reinitialize the environments to the values in force * after the file is read (in case the action file caused a change in * the defaults to be used). This allows the default action file to * reset the normal troff defaults (e.g., for legal size paper), and * have those values propagate into the three initial environments. */ void InitEnvironments (void) { Environ *ep; XChar buf[2]; int i; for (i = 2; i >= 0; i--) { buf[0] = '0' + i; buf[1] = '\0'; ep = FindEnvironment (buf); SaveEnvironment (ep); } esTop = 0; eStack[esTop] = ep; /* initially in environment named "0" */ } void PushEnvironment (XChar *name) { Environ *ep; if (esTop + 1 >= maxEStack) ETMPanic ("PushEnvironment: environment stack overflow"); ep = FindEnvironment (name); SaveEnvironment (eStack[esTop]); eStack[++esTop] = ep; RestoreEnvironment (eStack[esTop]); } void PopEnvironment (void) { if (esTop <= 0) { ETMMsg ("PopEnvironment: environment stack underflow"); return; } SaveEnvironment (eStack[esTop]); --esTop; RestoreEnvironment (eStack[esTop]); } /* * Save current parameters to a given environment structure */ static void SaveEnvironment (Environ *ep) { int i; ep->eSize = curSize; ep->ePrevSize = prevSize; ep->eSpaceSize = curSpaceSize; (void) XStrCpy (ep->eFont, curFont); (void) XStrCpy (ep->ePrevFont, prevFont); ep->eFillMode = fillMode; ep->eAdjust = adjust; ep->eAdjMode = adjMode; ep->eCenterCount, ep->eVSize = curVSize; ep->ePrevVSize = prevVSize; ep->eLineSpacing = curLineSpacing; ep->ePrevLineSpacing = prevLineSpacing; ep->eLineLen = curLineLen; ep->ePrevLineLen = prevLineLen; ep->eIndent = curIndent; ep->ePrevIndent = prevIndent; ep->eTempIndent = curTempIndent; XStrFree (ep->eItMacro); if (itMacro == (XChar *) NULL) ep->eItMacro = (XChar *) NULL; else ep->eItMacro = XStrAlloc (itMacro); ep->eItCount = itCount; ep->eTabCount = curTabCount; for (i = 0; i < maxTabStops; i++) { ep->eTabPos[i] = tabPos[i]; ep->eTabType[i] = tabType[i]; } ep->eTabChar = tabChar; ep->eLeaderChar = leaderChar; ep->eUlCount = ulCount; ep->eCUlCount = cUlCount; ep->eCtrlChar = ctrlChar; ep->eNbCtrlChar = nbCtrlChar; ep->eHyphenMode = curHyphenMode; ep->eHyphenChar = optHyphenChar; ep->eTitleLen = curTitleLen; ep->ePrevTitleLen = prevTitleLen; } /* * Restore current parameters from a given environment structure */ static void RestoreEnvironment (Environ *ep) { SetSize (ep->eSize); prevSize = ep->ePrevSize; SetSpaceSize (ep->eSpaceSize); SetFont (ep->eFont); (void) XStrCpy (prevFont, ep->ePrevFont); SetCFA (ep->eCenterCount, ep->eFillMode, ep->eAdjust, ep->eAdjMode); SetSpacing (ep->eVSize); prevVSize = ep->ePrevVSize; SetLineSpacing (ep->eLineSpacing); prevLineSpacing = ep->ePrevLineSpacing; SetLineLength (ep->eLineLen); prevLineLen = ep->ePrevLineLen; SetIndent (ep->eIndent); prevIndent = ep->ePrevIndent; SetTempIndent (ep->eTempIndent); Free ((char *) itMacro); if (ep->eItMacro == (XChar *) NULL) itMacro = (XChar *) NULL; else itMacro = XStrAlloc (ep->eItMacro); itCount = ep->eItCount; SetTabStops (ep->eTabCount, ep->eTabPos, ep->eTabType); tabChar = ep->eTabChar; leaderChar = ep->eLeaderChar; SetUnderline (ep->eUlCount, ep->eCUlCount); ctrlChar = ep->eCtrlChar; nbCtrlChar = ep->eNbCtrlChar; SetHyphenation (ep->eHyphenMode); optHyphenChar = ep->eHyphenChar; SetTitleLength (ep->eTitleLen); prevTitleLen = ep->ePrevTitleLen; } /* * Find an environment, given its name. If no environment exists with * the given name, create one and initialize it to the current environment * settings. */ Environ * FindEnvironment (XChar *name) { Environ *ep; for (ep = envList; ep != (Environ *) NULL; ep = ep->eNext) { if (XStrCmp (name, ep->eName) == 0) /* found it */ break; } if (ep == (Environ *) NULL) /* didn't find it */ { /* * Didn't find the named environment. Create it, initialize * the structure members that are pointer-valued and attach * to the list of known environments. Then initialize to * the current environment values. */ ep = New (Environ); ep->eName = XStrAlloc (name); ep->eItMacro = (XChar *) NULL; ep->eNext = envList; envList = ep; SaveEnvironment (ep); } return (ep); } /* * Return name of current environment. Used to implement .ev register, * which has a string value. CANNOT be called before InitEnvironments() * has been called. */ XChar * CurrentEnvironmentName (void) { return (eStack[esTop]->eName); } (Environ *ep); static Environ *FindEnvironment (XChar *name); /* * envList is a list of the currently known environments * eStack is a stack of the currently in-use environments */ static Entroffcvt-1.04/troffcvt/Makefile010066400017710000151000000432750634136770600203430ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./troffcvt # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # troffcvt Makefile # any special -D's or other flags for compiling DEFINES = \ -D'PROJLIBDIR="$(PROJLIBDIR)"' \ -D'MACROLIBDIR="$(MACROLIBDIR)"' \ -D'MACROFILEPREFIX="$(MACROFILEPREFIX)"' # any special -I's for compiling INCLUDES = # any special libraries needed for linking LIBS = $(TCUNIXLIB) $(TCGENLIB) $(MEMMGRLIB) $(TSLIB) \ $(ETMLIB) $(PORTLIB) DEPLIBS = $(DEPTCUNIXLIB) $(DEPTCGENLIB) $(DEPMEMMGRLIB) $(DEPTSLIB) \ $(DEPETMLIB) $(DEPPORTLIB) SRCS = main.c input.c output.c list.c \ parse.c action.c chartype.c text.c req.c setget.c \ units.c environ.c macfile.c xchar.c OBJS = main.o input.o output.o list.o \ parse.o action.o chartype.o text.o req.o setget.o \ units.o environ.o macfile.o xchar.o all:: troffcvt help_aux:: @echo "'make "troffcvt"' to "build troffcvt troffcvt: $(OBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(OBJS) $(LDOPTS) $(LIBS) $(EXTRA_LDLIBS) clean:: $(RM) troffcvt lint:: lint.troffcvt lint.troffcvt: $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.troffcvt"' to "lint sources for troffcvt install:: i.troffcvt help_aux:: @echo "'make "i.troffcvt"' to "install troffcvt i.troffcvt:: troffcvt @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTPROGFLAGS) troffcvt $(LOCALBINDIR)/troffcvt install:: i.actions help_aux:: @echo "'make "i.actions"' to "install actions i.actions:: actions @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) actions $(LIBDIR)/actions install:: i.actions-html help_aux:: @echo "'make "i.actions-html"' to "install actions-html i.actions-html:: actions-html @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) actions-html $(LIBDIR)/actions-html install:: i.tc.man help_aux:: @echo "'make "i.tc.man"' to "install tc.man i.tc.man:: tc.man @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.man $(LIBDIR)/tc.man install:: i.tc.man-html help_aux:: @echo "'make "i.tc.man-html"' to "install tc.man-html i.tc.man-html:: tc.man-html @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.man-html $(LIBDIR)/tc.man-html install:: i.tc.me help_aux:: @echo "'make "i.tc.me"' to "install tc.me i.tc.me:: tc.me @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.me $(LIBDIR)/tc.me install:: i.tc.me-html help_aux:: @echo "'make "i.tc.me-html"' to "install tc.me-html i.tc.me-html:: tc.me-html @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.me-html $(LIBDIR)/tc.me-html install:: i.tc.mm help_aux:: @echo "'make "i.tc.mm"' to "install tc.mm i.tc.mm:: tc.mm @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.mm $(LIBDIR)/tc.mm install:: i.tc.mm-html help_aux:: @echo "'make "i.tc.mm-html"' to "install tc.mm-html i.tc.mm-html:: tc.mm-html @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.mm-html $(LIBDIR)/tc.mm-html install:: i.tc.ms help_aux:: @echo "'make "i.tc.ms"' to "install tc.ms i.tc.ms:: tc.ms @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.ms $(LIBDIR)/tc.ms install:: i.tc.ms-html help_aux:: @echo "'make "i.tc.ms-html"' to "install tc.ms-html i.tc.ms-html:: tc.ms-html @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.ms-html $(LIBDIR)/tc.ms-html install:: i.tc.mdoc help_aux:: @echo "'make "i.tc.mdoc"' to "install tc.mdoc i.tc.mdoc:: tc.mdoc @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.mdoc $(LIBDIR)/tc.mdoc install:: i.tc.mdoc-html help_aux:: @echo "'make "i.tc.mdoc-html"' to "install tc.mdoc-html i.tc.mdoc-html:: tc.mdoc-html @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tc.mdoc-html $(LIBDIR)/tc.mdoc-html # runtest is used in the tests directory all:: runtest runtest:: runtest.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) runtest.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) runtest help_aux:: @echo "'make "runtest"' to "build the runtest script install:: i.runtest i.runtest:: @echo runtest is not installed anywhere. depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE main.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h main.o: /usr/include/ctype.h /usr/include/sys/types.h main.o: /usr/include/sys/isa_defs.h /usr/include/sys/machtypes.h main.o: /usr/include/sys/select.h /usr/include/sys/time.h /usr/include/time.h main.o: /usr/include/string.h /usr/local/include/portlib.h main.o: /usr/local/include/etm.h /usr/local/include/memmgr.h .././h/tcgen.h main.o: .././h/tcunix.h .././h/troffcvt.h input.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h input.o: /usr/include/string.h /usr/local/include/etm.h input.o: /usr/local/include/memmgr.h .././h/troffcvt.h output.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h output.o: /usr/local/include/etm.h .././h/troffcvt.h list.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h list.o: /usr/local/include/etm.h /usr/local/include/memmgr.h list.o: .././h/troffcvt.h parse.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h parse.o: /usr/include/string.h /usr/local/include/portlib.h parse.o: /usr/local/include/etm.h /usr/local/include/memmgr.h parse.o: .././h/troffcvt.h action.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h action.o: /usr/include/string.h /usr/local/include/etm.h action.o: /usr/local/include/tokenscan.h /usr/local/include/memmgr.h action.o: .././h/tcgen.h .././h/troffcvt.h chartype.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h chartype.o: /usr/include/ctype.h /usr/include/string.h chartype.o: /usr/local/include/etm.h .././h/troffcvt.h text.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h text.o: /usr/include/string.h /usr/local/include/etm.h text.o: /usr/local/include/memmgr.h .././h/troffcvt.h req.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h req.o: /usr/include/string.h /usr/local/include/portlib.h req.o: /usr/local/include/etm.h /usr/local/include/memmgr.h .././h/troffcvt.h setget.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h setget.o: /usr/include/ctype.h /usr/include/string.h /usr/local/include/etm.h setget.o: .././h/troffcvt.h units.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h units.o: /usr/include/ctype.h /usr/local/include/etm.h .././h/troffcvt.h environ.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h environ.o: /usr/include/string.h /usr/local/include/etm.h environ.o: /usr/local/include/memmgr.h .././h/troffcvt.h macfile.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h macfile.o: .././h/troffcvt.h xchar.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h xchar.o: /usr/local/include/etm.h /usr/local/include/memmgr.h xchar.o: .././h/troffcvt.h SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_Ctroffcvt-1.04/troffcvt/Imakefile010064400017710000151000000026240631314334100204650ustar00junkyarddatamgmt00000400000027XCOMM troffcvt Makefile XCOMM any special -D's or other flags for compiling DEFINES = \ -D'PROJLIBDIR="$(PROJLIBDIR)"' \ -D'MACROLIBDIR="$(MACROLIBDIR)"' \ -D'MACROFILEPREFIX="$(MACROFILEPREFIX)"' XCOMM any special -I's for compiling INCLUDES = XCOMM any special libraries needed for linking LIBS = $(TCUNIXLIB) $(TCGENLIB) $(MEMMGRLIB) $(TSLIB) \ $(ETMLIB) $(PORTLIB) DEPLIBS = $(DEPTCUNIXLIB) $(DEPTCGENLIB) $(DEPMEMMGRLIB) $(DEPTSLIB) \ $(DEPETMLIB) $(DEPPORTLIB) SRCS = main.c input.c output.c list.c \ parse.c action.c chartype.c text.c req.c setget.c \ units.c environ.c macfile.c xchar.c OBJS = main.o input.o output.o list.o \ parse.o action.o chartype.o text.o req.o setget.o \ units.o environ.o macfile.o xchar.o BuildProgram(troffcvt,$(SRCS),$(OBJS),$(LIBS),$(DEPLIBS)) InstallProgram(troffcvt,$(LOCALBINDIR)) InstallDataFile(actions,$(LIBDIR)) InstallDataFile(actions-html,$(LIBDIR)) InstallDataFile(tc.man,$(LIBDIR)) InstallDataFile(tc.man-html,$(LIBDIR)) InstallDataFile(tc.me,$(LIBDIR)) InstallDataFile(tc.me-html,$(LIBDIR)) InstallDataFile(tc.mm,$(LIBDIR)) InstallDataFile(tc.mm-html,$(LIBDIR)) InstallDataFile(tc.ms,$(LIBDIR)) InstallDataFile(tc.ms-html,$(LIBDIR)) InstallDataFile(tc.mdoc,$(LIBDIR)) InstallDataFile(tc.mdoc-html,$(LIBDIR)) XCOMM runtest is used in the tests directory ScriptFromMsubTemplate($(PERLPATH),runtest,runtest.pl,NullArg) FakeInstallFile(runtest) DependTarget() troffcvt-1.04/troffcvt/tc.me010064400017710000151000000005600630145006500176030ustar00junkyarddatamgmt00000400000027# -me-specific stuff. # -me .ip puts out the tag and then tries to generate horizontal motion. # writing a tab instead usually works better because troffcvt has no way # of computing amount of motion correctly. imm remove-name n ip req ip parse-macro-args eol \ push-string ".if $$<=1 .@p .5i\n.if $$<=1 .ti -.5i\n.if $$>1 .@p $2\n.if $$>1 .ti -$2\n\\&$1\t\\c\n" troffcvt-1.04/troffcvt/tc.mm010064400017710000151000000001540630145013700176120ustar00junkyarddatamgmt00000400000027# -mm-specific stuff. # Remap .P so it does something. req P parse-macro-args eol push-string ".sp .5v\n" troffcvt-1.04/troffcvt/tc.ms-html010064400017710000151000000065170631144023600205730ustar00junkyarddatamgmt00000400000027# -ms-specific stuff for tc2html # this helps to map -ms macros onto tc2hmtl concepts # When a name is redefined below, it's first removed. This is because groff # aliases many of the macros to an error macro until .TL is seen. Unless # a given name is removed before being redefined, redefining it would also # redefine all the other names that are aliases for it! # define an internal-use-only request to reset the paragraph state req reset*para*params eol \ break font R fill adjust b \ point-size 10 spacing 12 line-spacing 1 imm remove-name n TL req TL parse-macro-args eol \ push-string ".reset*para*params\n" \ adjust c \ push-string ".H*title\n" font "R" imm remove-name n AU req AU parse-macro-args eol \ push-string ".reset*para*params\n" \ adjust c nofill \ push-string ".H*para\n" font "I" imm remove-name n AI req AI parse-macro-args eol \ push-string ".reset*para*params\n" \ adjust c nofill \ push-string ".H*para\n" font "R" imm remove-name n AB req AB parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".if !'$1'no' \\{\\\n.H*para\n.ce\n\\fIABSTRACT\\fR\n.sp\n.\\}\n" \ push-string ".H*bq" font "R" imm remove-name n AE req AE parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*bq*end" font "R" imm remove-name n LP req LP parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*para\n" font "R" # write indented paragraphs as a definition list imm remove-name n IP req IP parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*dterm\n" font "R" \ push-string "$1\n" \ push-string ".H*ddesc\n" imm remove-name n DS req DS parse-macro-args eol \ push-string ".reset*para*params\n" \ nofill \ push-string ".H*disp*indent 3" \ push-string ".H*disp" font "R" imm remove-name n DE req DE parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*disp*end" font "R" imm remove-name n RS req RS parse-macro-args eol \ break \ push-string ".H*shift*right\n" imm remove-name n RE req RE parse-macro-args eol \ break \ push-string ".H*shift*left\n" imm remove-name n SH req SH parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*atoc 1\n" \ push-string ".H*header 2\n" \ input-trap 1 H*header*capture # if the argument is missing, use "1". Then generate, for argument # N, a level-N TOC entry and a level-(N+1) header using the line # following the .NH request. Note that this doesn't handle the # optional second argument to .NH, and thus botches it if that argument # is present... imm remove-name n NH req NH parse-num x eol \ push-string ".reset*para*params\n" \ push-string ".if '$1'' .nr H*NH*level 1 1\n" \ push-string ".if !'$1'' .nr H*NH*level $1 1\n" \ push-string ".H*atoc \\n[H*NH*level]\n" \ push-string ".H*header \\n+[H*NH*level]\n" \ input-trap 1 H*header*capture # have to define H*header*capture this way because the input-trap macro # must really be a macro, not a troffcvt request. imm push-string ".de H*header*capture\n.H*header*end\n.H*aend\n..\n" # Footnote support. All these versions of .FS/.FE do is bracket the # footnote text with "[[footnote:" and "]]" so that at least the # footnote can be recognized for what it is. imm remove-name n FS req FS eol push-string "[[footnote:\n" imm remove-name n FE req FE eol push-string "]]\n" troffcvt-1.04/troffcvt/tc.man-html010064400017710000151000000040760633042351200207240ustar00junkyarddatamgmt00000400000027# -man-specific stuff for tc2html # this helps to map -man macros onto tc2hmtl concepts # Names are removed before being redefined. Some of these names are # aliased (by groff), and redefining them would also redefine the aliases. imm remove-name n TH req TH parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*title\n" \ font "R" push-string "$1 manual page\n" \ push-string '.H*toc*title "Table of Contents" x\n' imm remove-name n SH req SH parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*header 2\n" \ push-string ".H*atoc 1\n" \ font "R" push-string "$*" \ push-string ".H*aend\n" \ push-string ".H*header*end\n" imm remove-name n SS req SS parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*header 3\n" \ font "R" push-string "$*" \ push-string ".H*header*end\n" imm remove-name n LP req LP parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*para\n" \ font "R" imm remove-name n PP req PP parse-macro-args eol \ push-string ".LP\n" # write indented paragraphs as a definition list imm remove-name n IP req IP parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*dterm\n" font "R" \ push-string "$1\n" \ push-string ".H*ddesc\n" imm remove-name n TP req TP eol \ break center 0 fill adjust b \ push-string ".H*dterm\n" font "R" \ input-trap 1 H*TP*capture # have to define H*TP*capture this way because the input-trap macro must # really be a macro, not a troffcvt request. imm push-string ".de H*TP*capture\n.H*ddesc\n..\n" # Be careful. Not all -man implementations seem to support .DS/.DE... imm remove-name n DS req DS parse-macro-args eol \ break nofill \ push-string ".H*disp\n" \ push-string ".H*disp*indent 3\n" \ font "R" imm remove-name n DE req DE parse-macro-args eol \ break center 0 fill \ push-string ".H*disp*end\n" \ font "R" imm remove-name n RS req RS parse-macro-args eol \ break \ push-string ".H*shift*right\n" imm remove-name n RE req RE parse-macro-args eol \ break \ push-string ".H*shift*left\n" troffcvt-1.04/troffcvt/actions010066400017710000151000000442370634113377100202560ustar00junkyarddatamgmt00000400000027# Requests begin with an argument parsing action section # (possibly empty), then eol (mandatory), then a non-parsing # action section (possibly empty). Immediates have only a # non-parsing action section. # If you list immediate actions, be aware that most parameters are # uninitialized. You should set spacing to initialize how big v's # are, and point-size to initialize how big m's and n's are. # output-control SHOULD NOT include \n at end. # output-text output SHOULD include \n at end, but regular text output # may or may not - but there is the problem of whether to flush or not. Ick. # 2. font and character size control req ps parse-absrel-num x point-size eol point-size $1 req ss parse-num x eol space-size $1 req cs parse-name parse-num x parse-num x eol constant-width $1 $2 $3 req bd parse-embolden eol embolden $1 $2 $3 req ft parse-name eol font $1 req fp parse-num x parse-name eol font-position $1 $2 # 3. page control (not implemented: pn ne mk rt) req pl parse-absrel-num v page-length eol page-length $1 # no way to know current page number; so sorry... req bp parse-absrel-num u 0 eol break begin-page $1 req pn parse-absrel-num u 0 eol page-number $1 req po parse-absrel-num m offset eol offset $1 req ne parse-num v eol need $1 req mk parse-name eol req rt parse-absrel-num v 0 eol # 4. text filling, adjusting and centering req br eol break req fi eol break fill req nf eol break nofill req ad parse-char eol adjust $1 req na eol noadjust req ce parse-num x eol break center $1 # 5. vertical spacing (not implemented: sv os ns rs) # seems odd, but vs and ls don't allow parse-absrel-num? req vs parse-num p eol spacing $1 req ls parse-num x eol line-spacing $1 req sp parse-num v eol break space $1 req sv parse-num v eol req os eol req ns eol no-space n req rs eol no-space y # 6. line length and indenting req ll parse-absrel-num m line-length eol line-length $1 req in parse-absrel-num m indent eol break indent $1 # temp indent interpreted relative to indent if +/- req ti parse-absrel-num m indent eol break temp-indent $1 # 7. macros, strings, diversion, and position traps # (not implemented: wh ch dt) req de parse-name parse-name eol define-macro $1 $2 req am parse-name parse-name eol append-macro $1 $2 req ds parse-name parse-string-value y eol define-string $1 $2 req as parse-name parse-string-value y eol append-string $1 $2 # since multiple names can be removed, call remove-names many times to allow # up to 99 names. req rm parse-names eol \ remove-names n $1 $2 $3 $4 $5 $6 $7 $8 $9 \ remove-names n $10 $11 $12 $13 $14 $15 $16 $17 $18 \ remove-names n $19 $20 $21 $22 $23 $24 $25 $26 $27 \ remove-names n $28 $29 $30 $31 $32 $33 $34 $35 $36 \ remove-names n $37 $38 $39 $40 $41 $42 $43 $44 $45 \ remove-names n $46 $47 $48 $49 $50 $51 $52 $53 $54 \ remove-names n $55 $56 $57 $58 $59 $60 $61 $62 $63 \ remove-names n $64 $65 $66 $67 $68 $69 $70 $71 $72 \ remove-names n $73 $74 $75 $76 $77 $78 $79 $80 $81 \ remove-names n $82 $83 $84 $85 $86 $87 $88 $89 $90 \ remove-names n $91 $92 $93 $94 $95 $96 $97 $98 $99 req rn parse-name parse-name eol rename $1 $2 req di parse-name eol diversion-begin $1 req da parse-name eol diversion-append $1 req wh parse-num v parse-name eol req ch parse-name parse-num v eol req dt parse-num v parse-name eol req it parse-num x parse-name eol input-trap $1 $2 req em parse-name eol end-macro $1 # 8. number registers req nr parse-name parse-absrel-num u \\$1 parse-num x eol \ define-register $1 $2 $3 # this isn't quite right, because second arg can be 01, 001, etc. # (fix this sometime!) req af parse-name parse-char eol register-format $1 $2 # since multiple names can be removed, call remove-names many times to allow # up to 99 names. req rr parse-names eol \ remove-names y $1 $2 $3 $4 $5 $6 $7 $8 $9 \ remove-names y $10 $11 $12 $13 $14 $15 $16 $17 $18 \ remove-names y $19 $20 $21 $22 $23 $24 $25 $26 $27 \ remove-names y $28 $29 $30 $31 $32 $33 $34 $35 $36 \ remove-names y $37 $38 $39 $40 $41 $42 $43 $44 $45 \ remove-names y $46 $47 $48 $49 $50 $51 $52 $53 $54 \ remove-names y $55 $56 $57 $58 $59 $60 $61 $62 $63 \ remove-names y $64 $65 $66 $67 $68 $69 $70 $71 $72 \ remove-names y $73 $74 $75 $76 $77 $78 $79 $80 $81 \ remove-names y $82 $83 $84 $85 $86 $87 $88 $89 $90 \ remove-names y $91 $92 $93 $94 $95 $96 $97 $98 $99 # 9. tabs, leaders and fields req ta parse-tab-stops eol req tc parse-char eol set-tab $1 req lc parse-char eol set-leader $1 req fc parse-char parse-char eol set-field $1 $2 # 10. input and output conventions and character translations # not implemented: lg tr # 10.1. input character translations req ec parse-char eol set-escape $1 req eo eol noescape # 10.2. ligatures req lg parse-num u eol # 10.3 backspacing, underlining, overstriking, etc. req ul parse-num x eol underline $1 req cu parse-num x eol continuous-underline $1 req uf parse-name eol underline-font $1 # 10.4. control characters req cc parse-char eol set-control $1 req c2 parse-char eol set-control2 $1 # 10.5. output translations req tr parse-transliteration eol transliterate $1 # 13. hyphenation (not implemented nh hy hc hw) req nh eol hyphenate 0 req hy parse-num x eol hyphenate $1 req hc parse-char eol hyphen-char $1 req hw eol # 14. three part titles (not implemented properly: tl) req tl parse-title eol title $1 $2 $3 req pc parse-char eol page-num-char $1 req lt parse-absrel-num m title-length eol title-length $1 # 15. output line numbering (not implemented: nm nn) # not really right because last three arguments can be non-numeric req nm parse-num u parse-num u parse-num u parse-num u eol req nn parse-num u eol # 16. conditional acceptance of input req if parse-condition n eol req ie parse-condition y eol req el process-condition eol # 17. environment switching req ev parse-name eol environment $1 # 18. insertions from the standard input (not implemented: rd) req rd eol req ex eol end-input # 19. input/output file switching (not implemented: pi) req so parse-filename eol push-file $1 req nx parse-filename eol switch-file $1 req pi eol # 20. miscellaneous (not implemented: mc pm fl) req mc parse-char parse-num m eol req tm parse-string-value n eol echo $1 req ab parse-string-value n eol abort $1 req ig parse-name eol ignore $1 req pm parse-char eol req fl eol # -------------------------------------------------------------------------- # groff-like stuff. req cp parse-num x eol set-compatibility $1 req mso parse-filename eol push-macro-file $1 req shift parse-num x eol shift-args $1 req do process-do eol req als parse-name parse-name eol alias-macro $1 $2 req aln parse-name parse-name eol alias-register $1 $2 # At the moment, these special characters are just the ones that I've # seen troffcvt complain about not knowing. There are lots of others # that I simply haven't bothered to define. imm special-char lq @quotedblleft imm special-char rq @quotedblright # -------------------------------------------------------------------------- # debugging stuff. Uncomment the ones you want, to turn them on. # imm dump-bad-requests 1 # req dump_stack eol dump-input-stack # req db parse-num x eol debug-flag $1 # req dp parse-name eol dump-macro $1 # -------------------------------------------------------------------------- # tblcvt support # Mostly all these do is use output-control to write out controls that # correspond to the input requests. This means we trust tblcvt not to # write out-of-order requests, and to write correct values for the request # arguments. # The action lists for T*cell*begin and T*cell*end do generate output other # than a \table-xxx control because cell font, point size, and vertical # spacing information are part of the cell formatting that needs to be seen # by troffcvt. # T*table*begin rows cols header-rows align expand box allbox doublebox req T*table*begin \ parse-num x parse-num x parse-num x \ parse-char parse-char parse-char parse-char parse-char eol \ output-control "table-begin $1 $2 $3 $4 $5 $6 $7 $8" req T*table*end eol \ output-control "table-end" # T*column*info width sep equal req T*column*info \ parse-num n parse-num n parse-char eol \ output-control "table-column-info $1 $2 $3" req T*row*begin eol \ output-control "table-row-begin" req T*row*end eol \ output-control "table-row-end" # T*cell*info type hspan vspan vspantop border req T*cell*info \ parse-char parse-num x parse-num x \ parse-char parse-num x eol \ output-control "table-cell-info $1 $2 $3 $4 $5" # T*cell*begin font ptsize vspace # The font, ptsize, and vspace arguments are processed by troffcvt # Save the current font, size, and spacing before changing them. req T*cell*begin \ parse-name parse-num x parse-num x eol \ output-control "table-cell-begin" \ push-string ".nr T*cell*ft \\n(.f\n.if !'$1'0' .ft $1\n" \ push-string ".nr T*cell*ps \\n(.s\n.if !'$2'0' .ps $2\n" \ push-string ".nr T*cell*vs \\n(.v\n.if !'$3'0' .vs $3\n" # Restore initial font, point size, and vertical spacing req T*cell*end eol \ push-string ".ft \\n[T*cell*ft]\n" \ push-string ".ps \\n[T*cell*ps]\n" \ push-string ".vs \\n[T*cell*vs]u\n" \ output-control "table-cell-end" req T*row*line \ parse-num x eol \ output-control "table-row-line $1" req T*cell*line \ parse-num x eol \ output-control "table-cell-line $1" req T*spanned*cell eol \ output-control "table-spanned-cell" req T*empty*cell eol \ output-control "table-empty-cell" # General setup stuff # special characters - define in immediate mode imm special-char em @emdash imm special-char hy @hyphen imm special-char bu @bullet imm special-char sq @square imm special-char ru @ru imm special-char 14 @onequarter imm special-char 12 @onehalf imm special-char 34 @threequarters imm special-char fi @fi imm special-char fl @fl imm special-char ff @ff imm special-char Fi @ffi imm special-char Fl @ffl imm special-char de @degree imm special-char dg @dagger # footmark imm special-char fm @minute imm special-char ct @cent imm special-char rg @registered imm special-char co @copyright imm special-char pl @plusmath imm special-char mi @minusmath imm special-char eq @equalmath imm special-char ** @asteriskmath imm special-char sc @section imm special-char aa @acute imm special-char ga @grave imm special-char .. @umlaut imm special-char ul @ul imm special-char sl @slash imm special-char *a @alpha imm special-char *b @beta imm special-char *g @gamma imm special-char *d @delta imm special-char *e @epsilon imm special-char *z @zeta imm special-char *y @eta imm special-char *h @theta imm special-char +h @theta1 imm special-char *i @iota imm special-char *k @kappa imm special-char *l @lambda imm special-char *m @mu imm special-char *n @nu imm special-char *c @xi imm special-char *o @omicron imm special-char *p @pi imm special-char *r @rho imm special-char *s @sigma imm special-char ts @sigma1 imm special-char *t @tau imm special-char *u @upsilon imm special-char *f @phi imm special-char +f @phi1 imm special-char *x @chi imm special-char *q @psi imm special-char *w @omega imm special-char +p @omega1 imm special-char *A @Alpha imm special-char *B @Beta imm special-char *G @Gamma imm special-char *D @Delta imm special-char *E @Epsilon imm special-char *Z @Zeta imm special-char *Y @Eta imm special-char *H @Theta imm special-char *I @Iota imm special-char *K @Kappa imm special-char *L @Lambda imm special-char *M @Mu imm special-char *N @Nu imm special-char *C @Xi imm special-char *O @Omicron imm special-char *P @Pi imm special-char *R @Rho imm special-char *S @Sigma imm special-char *T @Tau imm special-char *U @Upsilon imm special-char *F @Phi imm special-char *X @Chi imm special-char *Q @Psi imm special-char *W @Omega imm special-char sr @radical imm special-char rn @radicalex imm special-char >= @greaterequal imm special-char <= @lessequal imm special-char == @equivalence imm special-char ~= @approxequal imm special-char ap @similar imm special-char != @notequal imm special-char -> @arrowright imm special-char <- @arrowleft imm special-char ua @arrowup imm special-char da @arrowdown imm special-char mu @multiply imm special-char di @divide imm special-char +- @plusminus imm special-char cu @union imm special-char ca @intersection imm special-char sb @propersubset imm special-char sp @propersuperset imm special-char ib @reflexsubset imm special-char ip @reflexsuperset imm special-char if @infinity imm special-char pd @partialdiff imm special-char gr @gradient imm special-char no @logicalnot imm special-char is @integral imm special-char pt @proportional imm special-char es @emptyset imm special-char mo @element imm special-char br @br imm special-char dd @daggerdbl imm special-char rh @handright imm special-char lh @handleft imm special-char bs @bell imm special-char or @bar imm special-char ci @circle imm special-char bv @bv imm special-char lt @bracelefttp imm special-char lb @braceleftbt imm special-char rt @bracerighttp imm special-char rb @bracerightbt imm special-char lk @braceleftmid imm special-char rk @bracerightmid imm special-char lf @bracketleftbt imm special-char rf @bracketrightbt imm special-char lc @bracketlefttp imm special-char rc @bracketrighttp imm special-char /o @oslash imm special-char "'A" @Aacute imm special-char "'E" @Eacute imm special-char "'I" @Iacute imm special-char "'O" @Oacute imm special-char "'U" @Uacute imm special-char "'Y" @Yacute imm special-char "'a" @aacute imm special-char "'e" @eacute imm special-char "'i" @iacute imm special-char "'o" @oacute imm special-char "'u" @uacute imm special-char "'y" @yacute imm special-char "`A" @Agrave imm special-char "`E" @Egrave imm special-char "`I" @Igrave imm special-char "`O" @Ograve imm special-char "`U" @Ugrave imm special-char "`a" @agrave imm special-char "`e" @egrave imm special-char "`i" @igrave imm special-char "`o" @ograve imm special-char "`u" @ugrave imm special-char :a @adieresis imm special-char :e @edieresis imm special-char :i @idieresis imm special-char :o @odieresis imm special-char :u @udieresis imm special-char :y @ydieresis imm special-char :A @Adieresis imm special-char :E @Edieresis imm special-char :I @Idieresis imm special-char :O @Odieresis imm special-char :U @Udieresis imm special-char :Y @Ydieresis imm special-char ~n @ntilde imm special-char "'C" @Cacute imm special-char "'c" @cacute imm special-char %0 @perthousand imm special-char 'a"' @hungarumlaut imm special-char ,C @Ccedilla imm special-char ,c @ccedilla imm special-char -+ @minusplus imm special-char -D @Eth imm special-char -h @hbar imm special-char .i @dotlessi imm special-char .j @dotlessj imm special-char /L @Lslash imm special-char /O @Oslash imm special-char /_ @angle imm special-char /l @lslash imm special-char 3d @therefore imm special-char << @muchless imm special-char <> @arrowboth imm special-char =~ @congruent imm special-char >> @muchgreater imm special-char AE @AE imm special-char AN @logicaland imm special-char Ah @aleph imm special-char Bq @quotedblbase imm special-char CL @club imm special-char CR @carriagereturn imm special-char Cs @currency imm special-char DI @diamond imm special-char Do @dollar imm special-char Fc @guillemotright imm special-char Fn @florin imm special-char Fo @guillemotleft imm special-char HE @heart imm special-char IJ @IJ imm special-char Im @Ifraktur imm special-char OE @OE imm special-char OK @checkmark imm special-char OR @logicalor imm special-char Of @ordfeminine imm special-char Om @ordmasculine imm special-char Po @sterling imm special-char Re @Rfraktur imm special-char S1 @onesuperior imm special-char S2 @twosuperior imm special-char S3 @threesuperior imm special-char SP @spade imm special-char Sd @eth imm special-char TP @Thorn imm special-char Tp @thorn imm special-char Ye @yen imm special-char ^A @Acircumflex imm special-char ^E @Ecircumflex imm special-char ^I @Icircumflex imm special-char ^O @Ocircumflex imm special-char ^U @Ucircumflex imm special-char ^a @acircumflex imm special-char ^e @ecircumflex imm special-char ^i @icircumflex imm special-char ^o @ocircumflex imm special-char ^u @ucircumflex imm special-char a- @macron imm special-char a. @dotaccent imm special-char a^ @circumflex imm special-char ab @breve imm special-char ac @cedilla imm special-char ad @dieresis imm special-char ae @ae imm special-char ah @caron imm special-char an @arrowhorizex imm special-char ao @ring imm special-char aq @quotesingle imm special-char at @at imm special-char a~ @tilde imm special-char ba @bar imm special-char bb @brokenbar imm special-char bq @quotesinglbase imm special-char c* @circlemultiply imm special-char c+ @circleplus imm special-char dA @arrowdbldown imm special-char en @endash imm special-char f/ @fraction imm special-char fa @universal imm special-char fc @guilsinglright imm special-char fo @guilsinglleft imm special-char hA @arrowdblboth imm special-char ha @asciicircum imm special-char ho @ogonek imm special-char ij @ij imm special-char lA @arrowdblleft imm special-char lB @bracketleft imm special-char lC @braceleft imm special-char la @angleleft imm special-char lz @lozenge imm special-char md @dotmath imm special-char nb @notsubset imm special-char nc @notpropersuperset imm special-char ne @notequivalence imm special-char nm @notelement imm special-char oA @Aring imm special-char oa @aring imm special-char oe @oe imm special-char oq @quoteleft imm special-char pp @perpendicular imm special-char ps @paragraph imm special-char r! @exclamdown imm special-char r? @questiondown imm special-char rA @arrowdblright imm special-char rB @bracketright imm special-char rC @braceright imm special-char ra @angleright imm special-char rs @backslash imm special-char sd @second imm special-char sh @numbersign imm special-char ss @germandbls imm special-char st @suchthat imm special-char te @existential imm special-char tf @therefore imm special-char ti @asciitilde imm special-char tm @trademark imm special-char uA @arrowdblup imm special-char vA @arrowdblvert imm special-char vS @Scaron imm special-char vZ @Zcaron imm special-char va @arrowvertboth imm special-char vs @scaron imm special-char vz @zcaron imm special-char wp @weierstrass imm special-char ~A @Atilde imm special-char ~N @Ntilde imm special-char ~O @Otilde imm special-char ~a @atilde imm special-char ~o @otilde imm special-char ~~ @approxequal # initial page layout imm page-length 11i imm offset 1i imm line-length 6.5i imm indent 0 imm temp-indent 0 imm title-length 6.5i imm fill imm adjust b imm point-size 10 imm spacing 12p imm line-spacing 1 imm font R " \ push-string ".nr T*cell*ps \\n(.s\n.if !'$2'0' .ps $2\n" \ push-string ".nr T*cell*vs \\n(.v\n.if !'$3'0' .vs $3\n" # Restore initial font, point size, and vertical spacing req T*cell*end eol \ push-string ".ft \\n[T*cell*ft]\n" \ push-string ".ps \\n[T*cell*ps]\n" \ push-string ".vs \\n[T*cell*vs]u\n" \ output-control "table-cell-end" req Ttroffcvt-1.04/troffcvt/macfile.c010064400017710000151000000007700626662670500204410ustar00junkyarddatamgmt00000400000027/* * Routine for opening troff macro files. The procedure that's actually * used must be installed on a platform-dependent basis by the application * driver. */ #include #include "troffcvt.h" /* * Open a macro file. */ static FILE *(*macroFileOpen) () = NULL; void SetOpenMacroFileProc (FILE *(*proc) ()) { macroFileOpen = proc; } FILE * OpenMacroFile (char *file, char *mode) { if (macroFileOpen == NULL) return ((FILE *) NULL); return ((*macroFileOpen) (file, mode)); } troffcvt-1.04/troffcvt/xchar.c010064400017710000151000000070240627026646500201430ustar00junkyarddatamgmt00000400000027/* * xchar.c -- routines that operate on extended characters and strings * of extended characters. */ #include #include "etm.h" #include "memmgr.h" #include "troffcvt.h" /* * Return length of an extended string */ int XStrLen (XChar *xstr) { int len = 0; while (*xstr++ != (XChar) '\0') ++len; return (len); } /* * Copy an extended-char string and return a pointer to the result */ XChar * XStrCpy (XChar *xdst, XChar *xsrc) { XChar *xsave = xdst; while ((*xdst++ = *xsrc++) != (XChar) '\0') { /* loop */ } return (xsave); } /* * Copy at most n bytes of an extended-char string and return a pointer * to the result */ XChar * XStrNCpy (XChar *xdst, XChar *xsrc, long n) { XChar *xsave = xdst; while (n-- > 0 && (*xdst++ = *xsrc++) != (XChar) '\0') { /* loop */ } return (xsave); } /* * Compare two extended-char strings, returning: * * 0 xstr1 == xstr2 * -1 xstr1 < xstr2 * 1 xstr1 > xstr2 */ int XStrCmp (XChar *xstr1, XChar *xstr2) { int i; while ((i = (*xstr2 - *xstr1)) == 0 && *xstr1++ != (XChar) '\0' && *xstr2++ != (XChar) '\0') { /* loop */ } if (i == 0) return (0); return (i < 0 ? -1 : 1); } /* * Compare at most n bytes of two extended-char strings, returning: * * 0 xstr1 == xstr2 * -1 xstr1 < xstr2 * 1 xstr1 > xstr2 */ int XStrNCmp (XChar *xstr1, XChar *xstr2, long n) { int i = 0; while (n-- > 0 && (i = (*xstr2 - *xstr1)) == 0 && *xstr1++ != (XChar) '\0' && *xstr2++ != (XChar) '\0') { /* loop */ } if (i == 0) return (0); return (i < 0 ? -1 : 1); } /* * Allocate space for an extended-char string, copy the given string into * it, and return a pointer to the copy. */ XChar * XStrAlloc (XChar *xstr) { int len; XChar *p; len = XStrLen (xstr); p = (XChar *) VAllocNP (len + 1, sizeof (XChar)); if (p == (XChar *) NULL) ETMMsg ("XStrAlloc: out of memory"); return (XStrCpy (p, xstr)); } /* * Stuff a string into an extended-char string, and return a pointer * to the result. * * Returns a pointer to a static buffer. Caller should copy the * return value if it needs to hang onto it for a while. */ XChar * StrToXStr (char *str) { static XChar xstr[bufSiz]; XChar *xp = xstr; while ((*xp++ = *str++) != (XChar) '\0') { /* loop */ } return (xstr); } /* * Convert coded XChar value to printable ASCII representation. * Returns a pointer to a static buffer. Caller should copy the * return value if it needs to hang onto it for a while. */ char * XCharToStr (XChar c) { static char buf[bufSiz]; SpChar *sp; if (Special (c)) { if ((sp = LookupSpCharByCode (c)) != (SpChar *) NULL) { if (XStrLen (sp->spName) == 2) { sprintf (buf, "%c(%s", escChar, XStrToStr (sp->spName)); } else { sprintf (buf, "%c[%s]", escChar, XStrToStr (sp->spName)); } } else { ETMMsg ("%sXCharToStr: bad special-char code: %ld", FileInfo (), c); buf[0] = '\0'; } } else if (Esc (c)) sprintf (buf, "%c%c", escChar, FromEsc (c)); else { buf[0] = c; buf[1] = '\0'; } return (buf); } /* * Convert XChar string to printable ASCII representation. * Returns a pointer to a static buffer. Caller should copy the * return value if it needs to hang onto it for a while. */ char * XStrToStr (XChar *xstr) { static char buf[bufSiz]; char *p, *p2; XChar xc; p = buf; while ((xc = *xstr++) != (XChar) '\0') { p2 = XCharToStr (xc); /* convert XChar to string */ (void) strcpy (p, p2); /* add string to end of buffer */ p += strlen (p); /* advance to new end of buffer */ } *p = '\0'; return (buf); } troffcvt-1.04/troffcvt/tests/004077500017710000151000000000000634123030700200175ustar00junkyarddatamgmt00000400000027troffcvt-1.04/troffcvt/tests/de010064400017710000151000000000340626662670500203430ustar00junkyarddatamgmt00000400000027.de xx \\$1 \\$2 .. .xx a b troffcvt-1.04/troffcvt/tests/special-char010066400017710000151000000103700634110413000222650ustar00junkyarddatamgmt00000400000027.nf AE: \(AE Aacute: \('A Acircumflex: \(^A Adieresis: \(:A Agrave: \(`A Alpha: \(*A Aring: \(oA Atilde: \(~A Beta: \(*B Cacute: \('C Ccedilla: \(,C Chi: \(*X Delta: \(*D Eacute: \('E Ecircumflex: \(^E Edieresis: \(:E Egrave: \(`E Epsilon: \(*E Eta: \(*Y Eth: \(-D Gamma: \(*G IJ: \(IJ Iacute: \('I Icircumflex: \(^I Idieresis: \(:I Ifraktur: \(Im Igrave: \(`I Iota: \(*I Kappa: \(*K Lambda: \(*L Lslash: \(/L Mu: \(*M Ntilde: \(~N Nu: \(*N OE: \(OE Oacute: \('O Ocircumflex: \(^O Odieresis: \(:O Ograve: \(`O Omega: \(*W Omicron: \(*O Oslash: \(/O Otilde: \(~O Phi: \(*F Pi: \(*P Psi: \(*Q Rfraktur: \(Re Rho: \(*R Scaron: \(vS Sigma: \(*S Tau: \(*T Theta: \(*H Thorn: \(TP Uacute: \('U Ucircumflex: \(^U Udieresis: \(:U Ugrave: \(`U Upsilon: \(*U Xi: \(*C Yacute: \('Y Ydieresis: \(:Y Zcaron: \(vZ Zeta: \(*Z aacute: \('a acircumflex: \(^a acute: \(aa adieresis: \(:a ae: \(ae agrave: \(`a aleph: \(Ah alpha: \(*a angle: \(/_ angleleft: \(la angleright: \(ra approxequal: \(~= approxequal: \(~~ aring: \(oa arrowboth: \(<> arrowdblboth: \(hA arrowdbldown: \(dA arrowdblleft: \(lA arrowdblright: \(rA arrowdblup: \(uA arrowdblvert: \(vA arrowdown: \(da arrowhorizex: \(an arrowleft: \(<- arrowright: \(-> arrowup: \(ua asciicircum: \(ha asciitilde: \(ti asteriskmath: \(** at: \(at atilde: \(~a backslash: \(rs bar: \(ba bar: \(or bell: \(bs beta: \(*b br: \(br braceleft: \(lC braceright: \(rC bracketleft: \(lB bracketright: \(rB breve: \(ab brokenbar: \(bb bullet: \(bu bv: \(bv cacute: \('c caron: \(ah carriagereturn: \(CR ccedilla: \(,c cedilla: \(ac cent: \(ct checkmark: \(OK chi: \(*x circle: \(ci circlemultiply: \(c* circleplus: \(c+ circumflex: \(a^ club: \(CL congruent: \(=~ copyright: \(co currency: \(Cs dagger: \(dg daggerdbl: \(dd arrowvertboth: \(va degree: \(de delta: \(*d diamond: \(DI dieresis: \(ad divide: \(di dollar: \(Do dotaccent: \(a. dotlessi: \(.i dotlessj: \(.j dotmath: \(md eacute: \('e ecircumflex: \(^e edieresis: \(:e egrave: \(`e element: \(mo emdash: \(em emptyset: \(es endash: \(en epsilon: \(*e equalmath: \(eq equivalence: \(== eta: \(*y eth: \(Sd exclamdown: \(r! existential: \(te ff: \(ff ffi: \(Fi ffl: \(Fl fi: \(fi fl: \(fl florin: \(Fn fraction: \(f/ gamma: \(*g germandbls: \(ss gradient: \(gr grave: \(ga greaterequal: \(>= guillemotleft: \(Fo guillemotright: \(Fc guilsinglleft: \(fo guilsinglright: \(fc handleft: \(lh handright: \(rh hbar: \(-h heart: \(HE hungarumlaut: \(a" hyphen: \(hy iacute: \('i icircumflex: \(^i idieresis: \(:i igrave: \(`i ij: \(ij infinity: \(if integral: \(is intersection: \(ca iota: \(*i kappa: \(*k lambda: \(*l braceleftbt: \(lb bracketlefttp: \(lc braceleftmid: \(lk bracketleftbt: \(lf bracelefttp: \(lt lessequal: \(<= logicaland: \(AN logicalnot: \(no logicalor: \(OR lozenge: \(lz lslash: \(/l macron: \(a- minusmath: \(mi minusplus: \(-+ minute: \(fm mu: \(*m muchgreater: \(>> muchless: \(<< multiply: \(mu notelement: \(nm notequal: \(!= notequivalence: \(ne notpropersuperset: \(nc notsubset: \(nb ntilde: \(~n nu: \(*n numbersign: \(sh oacute: \('o ocircumflex: \(^o odieresis: \(:o oe: \(oe ogonek: \(ho ograve: \(`o omega1: \(+p omega: \(*w omicron: \(*o onehalf: \(12 onequarter: \(14 onesuperior: \(S1 ordfeminine: \(Of ordmasculine: \(Om oslash: \(/o otilde: \(~o paragraph: \(ps partialdiff: \(pd perpendicular: \(pp perthousand: \(%0 phi1: \(+f phi: \(*f pi: \(*p plusmath: \(pl plusminus: \(+- propersubset: \(sb propersuperset: \(sp proportional: \(pt psi: \(*q questiondown: \(r? quotedblbase: \(Bq quotedblleft: \(lq quotedblright: \(rq quoteleft: \(oq quotesinglbase: \(bq quotesingle: \(aq reflexsubset: \(ib reflexsuperset: \(ip registered: \(rg rho: \(*r bracerightbt: \(rb bracketrighttp: \(rc bracerightmid: \(rk bracketrightbt: \(rf bracerighttp: \(rt ring: \(ao radicalex: \(rn ru: \(ru scaron: \(vs second: \(sd section: \(sc sigma1: \(ts sigma: \(*s similar: \(ap slash: \(sl spade: \(SP radical: \(sr square: \(sq sterling: \(Po suchthat: \(st tau: \(*t therefore: \(3d therefore: \(tf theta1: \(+h theta: \(*h thorn: \(Tp threequarters: \(34 threesuperior: \(S3 tilde: \(a~ trademark: \(tm twosuperior: \(S2 uacute: \('u ucircumflex: \(^u udieresis: \(:u ugrave: \(`u ul: \(ul umlaut: \(.. union: \(cu universal: \(fa upsilon: \(*u weierstrass: \(wp xi: \(*c yacute: \('y ydieresis: \(:y yen: \(Ye zcaron: \(vz zeta: \(*z cute: \('Y Ydieresis: \(:Y Zcaron: \(vZ Zeta: \(*Z aacute: \('a acircumflex: \(^a acute: \(aa adieresis: \(:a ae: \(ae agrave: \(`a aleph: \(Ah alpha: \(*a angle: \(/_ angleleft: \(la angleright: \(ra approxequal: \(~= approxequal: \(~~ aring: \(oa arrowboth: \(<>troffcvt-1.04/troffcvt/tests/special-char.result010066400017710000151000000203710634110413400236100ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file special-char \nofill AE: @AE \break Aacute: @Aacute \break Acircumflex: @Acircumflex \break Adieresis: @Adieresis \break Agrave: @Agrave \break Alpha: @Alpha \break Aring: @Aring \break Atilde: @Atilde \break Beta: @Beta \break Cacute: @Cacute \break Ccedilla: @Ccedilla \break Chi: @Chi \break Delta: @Delta \break Eacute: @Eacute \break Ecircumflex: @Ecircumflex \break Edieresis: @Edieresis \break Egrave: @Egrave \break Epsilon: @Epsilon \break Eta: @Eta \break Eth: @Eth \break Gamma: @Gamma \break IJ: @IJ \break Iacute: @Iacute \break Icircumflex: @Icircumflex \break Idieresis: @Idieresis \break Ifraktur: @Ifraktur \break Igrave: @Igrave \break Iota: @Iota \break Kappa: @Kappa \break Lambda: @Lambda \break Lslash: @Lslash \break Mu: @Mu \break Ntilde: @Ntilde \break Nu: @Nu \break OE: @OE \break Oacute: @Oacute \break Ocircumflex: @Ocircumflex \break Odieresis: @Odieresis \break Ograve: @Ograve \break Omega: @Omega \break Omicron: @Omicron \break Oslash: @Oslash \break Otilde: @Otilde \break Phi: @Phi \break Pi: @Pi \break Psi: @Psi \break Rfraktur: @Rfraktur \break Rho: @Rho \break Scaron: @Scaron \break Sigma: @Sigma \break Tau: @Tau \break Theta: @Theta \break Thorn: @Thorn \break Uacute: @Uacute \break Ucircumflex: @Ucircumflex \break Udieresis: @Udieresis \break Ugrave: @Ugrave \break Upsilon: @Upsilon \break Xi: @Xi \break Yacute: @Yacute \break Ydieresis: @Ydieresis \break Zcaron: @Zcaron \break Zeta: @Zeta \break aacute: @aacute \break acircumflex: @acircumflex \break acute: @acute \break adieresis: @adieresis \break ae: @ae \break agrave: @agrave \break aleph: @aleph \break alpha: @alpha \break angle: @angle \break angleleft: @angleleft \break angleright: @angleright \break approxequal: @approxequal \break approxequal: @approxequal \break aring: @aring \break arrowboth: @arrowboth \break arrowdblboth: @arrowdblboth \break arrowdbldown: @arrowdbldown \break arrowdblleft: @arrowdblleft \break arrowdblright: @arrowdblright \break arrowdblup: @arrowdblup \break arrowdblvert: @arrowdblvert \break arrowdown: @arrowdown \break arrowhorizex: @arrowhorizex \break arrowleft: @arrowleft \break arrowright: @arrowright \break arrowup: @arrowup \break asciicircum: @asciicircum \break asciitilde: @asciitilde \break asteriskmath: @asteriskmath \break at: @at \break atilde: @atilde \break backslash: @backslash \break bar: @bar \break bar: @bar \break bell: @bell \break beta: @beta \break br: @br \break braceleft: @braceleft \break braceright: @braceright \break bracketleft: @bracketleft \break bracketright: @bracketright \break breve: @breve \break brokenbar: @brokenbar \break bullet: @bullet \break bv: @bv \break cacute: @cacute \break caron: @caron \break carriagereturn: @carriagereturn \break ccedilla: @ccedilla \break cedilla: @cedilla \break cent: @cent \break checkmark: @checkmark \break chi: @chi \break circle: @circle \break circlemultiply: @circlemultiply \break circleplus: @circleplus \break circumflex: @circumflex \break club: @club \break congruent: @congruent \break copyright: @copyright \break currency: @currency \break dagger: @dagger \break daggerdbl: @daggerdbl \break arrowvertboth: @arrowvertboth \break degree: @degree \break delta: @delta \break diamond: @diamond \break dieresis: @dieresis \break divide: @divide \break dollar: @dollar \break dotaccent: @dotaccent \break dotlessi: @dotlessi \break dotlessj: @dotlessj \break dotmath: @dotmath \break eacute: @eacute \break ecircumflex: @ecircumflex \break edieresis: @edieresis \break egrave: @egrave \break element: @element \break emdash: @emdash \break emptyset: @emptyset \break endash: @endash \break epsilon: @epsilon \break equalmath: @equalmath \break equivalence: @equivalence \break eta: @eta \break eth: @eth \break exclamdown: @exclamdown \break existential: @existential \break ff: @ff \break ffi: @ffi \break ffl: @ffl \break fi: @fi \break fl: @fl \break florin: @florin \break fraction: @fraction \break gamma: @gamma \break germandbls: @germandbls \break gradient: @gradient \break grave: @grave \break greaterequal: @greaterequal \break guillemotleft: @guillemotleft \break guillemotright: @guillemotright \break guilsinglleft: @guilsinglleft \break guilsinglright: @guilsinglright \break handleft: @handleft \break handright: @handright \break hbar: @hbar \break heart: @heart \break hungarumlaut: @hungarumlaut \break hyphen: @hyphen \break iacute: @iacute \break icircumflex: @icircumflex \break idieresis: @idieresis \break igrave: @igrave \break ij: @ij \break infinity: @infinity \break integral: @integral \break intersection: @intersection \break iota: @iota \break kappa: @kappa \break lambda: @lambda \break braceleftbt: @braceleftbt \break bracketlefttp: @bracketlefttp \break braceleftmid: @braceleftmid \break bracketleftbt: @bracketleftbt \break bracelefttp: @bracelefttp \break lessequal: @lessequal \break logicaland: @logicaland \break logicalnot: @logicalnot \break logicalor: @logicalor \break lozenge: @lozenge \break lslash: @lslash \break macron: @macron \break minusmath: @minusmath \break minusplus: @minusplus \break minute: @minute \break mu: @mu \break muchgreater: @muchgreater \break muchless: @muchless \break multiply: @multiply \break notelement: @notelement \break notequal: @notequal \break notequivalence: @notequivalence \break notpropersuperset: @notpropersuperset \break notsubset: @notsubset \break ntilde: @ntilde \break nu: @nu \break numbersign: @numbersign \break oacute: @oacute \break ocircumflex: @ocircumflex \break odieresis: @odieresis \break oe: @oe \break ogonek: @ogonek \break ograve: @ograve \break omega1: @omega1 \break omega: @omega \break omicron: @omicron \break onehalf: @onehalf \break onequarter: @onequarter \break onesuperior: @onesuperior \break ordfeminine: @ordfeminine \break ordmasculine: @ordmasculine \break oslash: @oslash \break otilde: @otilde \break paragraph: @paragraph \break partialdiff: @partialdiff \break perpendicular: @perpendicular \break perthousand: @perthousand \break phi1: @phi1 \break phi: @phi \break pi: @pi \break plusmath: @plusmath \break plusminus: @plusminus \break propersubset: @propersubset \break propersuperset: @propersuperset \break proportional: @proportional \break psi: @psi \break questiondown: @questiondown \break quotedblbase: @quotedblbase \break quotedblleft: @quotedblleft \break quotedblright: @quotedblright \break quoteleft: @quoteleft \break quotesinglbase: @quotesinglbase \break quotesingle: @quotesingle \break reflexsubset: @reflexsubset \break reflexsuperset: @reflexsuperset \break registered: @registered \break rho: @rho \break bracerightbt: @bracerightbt \break bracketrighttp: @bracketrighttp \break bracerightmid: @bracerightmid \break bracketrightbt: @bracketrightbt \break bracerighttp: @bracerighttp \break ring: @ring \break radicalex: @radicalex \break ru: @ru \break scaron: @scaron \break second: @second \break section: @section \break sigma1: @sigma1 \break sigma: @sigma \break similar: @similar \break slash: @slash \break spade: @spade \break radical: @radical \break square: @square \break sterling: @sterling \break suchthat: @suchthat \break tau: @tau \break therefore: @therefore \break therefore: @therefore \break theta1: @theta1 \break theta: @theta \break thorn: @thorn \break threequarters: @threequarters \break threesuperior: @threesuperior \break tilde: @tilde \break trademark: @trademark \break twosuperior: @twosuperior \break uacute: @uacute \break ucircumflex: @ucircumflex \break udieresis: @udieresis \break ugrave: @ugrave \break ul: @ul \break umlaut: @umlaut \break union: @union \break universal: @universal \break upsilon: @upsilon \break weierstrass: @weierstrass \break xi: @xi \break yacute: @yacute \break ydieresis: @ydieresis \break yen: @yen \break zcaron: @zcaron \break zeta: @zeta \break troffcvt-1.04/troffcvt/tests/de.result010066400017710000151000000005400633745435500216630ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file de a b \break troffcvt-1.04/troffcvt/tests/de2010064400017710000151000000027260626662670500204370ustar00junkyarddatamgmt00000400000027.\" test allocation of macro buffer by defining a macro that's large .\" enough to require a reallocation of more space after the initial .\" macro body buffer has been allocated. .de xx 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* .. .nf .xx troffcvt-1.04/troffcvt/tests/de2.result010066400017710000151000000033360633745435700217550ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file de2 \nofill 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break 123456789*123456789*123456789*123456789*123456789*123456789*123456789*123456789* \break troffcvt-1.04/troffcvt/tests/inputtrap010064400017710000151000000001070626662670600220030ustar00junkyarddatamgmt00000400000027.de IT input trap sprung .. .it 1 IT .ul 2 abc def .it 1 IT abc\c def troffcvt-1.04/troffcvt/tests/dump-stack010064400017710000151000000007770627353251500220320ustar00junkyarddatamgmt00000400000027.ig define a recursive macro that prints the recursion level, then prints the input stack. Eventually this should break with an macro-recursion-too-deep error. This assumes that the action file contains a line like this: req dump_stack eol dump-input-stack (otherwise .dump_stack won't do anything) .. .cp 0 .nr recursion_level 1 1 .\" define the macro .de recurse .tm recursion level is \\n[recursion_level] .dump_stack .nr recursion_level \\n[recursion_level]+1 1 .recurse .. .\" invoke the macro .recurse troffcvt-1.04/troffcvt/tests/req-args010066400017710000151000000011200626754162300214670ustar00junkyarddatamgmt00000400000027# action file to make sure that post-processing actions that require # request argument processing don't clobber the arguments for the request # for which they're being executed. # To run this test, execute the following command: # % echo ".test a b c" | troffcvt -A -a thisfile # You should see the following after the \end-setup line: # a b c # \break # a b c # \break # You should NOT see: # a b c # \break # d e f g # \break req test parse-macro-args eol \ output-text "$*" \ break \ push-string ".null d e f g" \ output-text "$*" \ break req null parse-macro-args eol troffcvt-1.04/troffcvt/tests/shift010066400017710000151000000005350631240741000210560ustar00junkyarddatamgmt00000400000027.ig Test the .shift request by passing some arguments to a macro that prints information about its arguments, shifts them, and recurses, until it has no more arguments. .. .cp 0 .de shift-test .sp Number of arguments: \\n[.$] .br Arguments: \\$@ .if \\n[.$] \{\ .br Recursing... .shift .shift-test \\$@ .\} .. .\" .shift-test a b "two words" "" xyz troffcvt-1.04/troffcvt/tests/shift.result010066400017710000151000000015620633745444100224110ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file shift \space 72 Number of arguments: 5 \break Arguments: "a" "b" "two words" "" "xyz" \break Recursing... \break \space 72 Number of arguments: 4 \break Arguments: "b" "two words" "" "xyz" \break Recursing... \break \space 72 Number of arguments: 3 \break Arguments: "two words" "" "xyz" \break Recursing... \break \space 72 Number of arguments: 2 \break Arguments: "" "xyz" \break Recursing... \break \space 72 Number of arguments: 1 \break Arguments: "xyz" \break Recursing... \break \space 72 Number of arguments: 0 \break Arguments: \break troffcvt-1.04/troffcvt/tests/do010066400017710000151000000010270627075331100203470ustar00junkyarddatamgmt00000400000027.\" test the .do request by using it to define a string with a long .\" name, and then echoing it. .\" .cp 1 \" turn compatibility mode on .\" .\" next commands should print that abcd has value "abcd]" .\" .tm First, with compatibility mode on: .ds abcd this is a string .tm string named abcd has value = "\*[abcd]" .\" .\" next commands should print that abcd has value "this is a string" .\" .tm Second, using .do to temporarily disable compatibility mode .do ds abcd this is a string .do tm string named abcd has value = "\*[abcd]" troffcvt-1.04/troffcvt/tests/shift2b010066400017710000151000000000070627102427500213040ustar00junkyarddatamgmt00000400000027.shift troffcvt-1.04/troffcvt/tests/macro-args010066400017710000151000000011720631234407400220000ustar00junkyarddatamgmt00000400000027.\" make sure macro argument references work .\" $0 = macro name .\" $n, n > 0 = macro argument n (if n > \n(.$, arg should be empty) .\" $* = all arguments, space-separated .\" $@ = all arguments, space-separated and double-quoted .\" .cp 0 .nf .de test-macro Macro name: \\$0 Number of arguments: \\n(.$ Argument 1: \\$1 Argument 2: \\$2 Argument 3: \\$3 All arguments: \\$* All arguments, quoted: \\$@ .. .\" ----- Called with no arguments .test-macro ----- Called with one argument .test-macro arg1 ----- Called with three arguments .test-macro arg1 arg2 arg3 ----- Called with five arguments .test-macro arg1 arg2 arg3 arg4 arg5 troffcvt-1.04/troffcvt/tests/shift2a010066400017710000151000000006010627353422400213050ustar00junkyarddatamgmt00000400000027.ig This is like the "shift" test except that the .shift request occurs in a file that's .so'd from within the macro, to verify that .shift works even if the macro isn't the most recent input source. .. .cp 0 .de shift-test .sp Number of arguments: \\n[.$] .br Arguments: \\$@ .if \\n[.$] \{\ .br Recursing... .so shift2b .shift-test \\$@ .\} .. .\" .shift-test a b "two words" "" xyz troffcvt-1.04/troffcvt/tests/macro-args.result010066400017710000151000000025210633745442000233200ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file macro-args \nofill ----- \break Called with no arguments \break Macro name: test-macro \break Number of arguments: 0 \break Argument 1: \break Argument 2: \break Argument 3: \break All arguments: \break All arguments, quoted: \break ----- \break Called with one argument \break Macro name: test-macro \break Number of arguments: 1 \break Argument 1: arg1 \break Argument 2: \break Argument 3: \break All arguments: arg1 \break All arguments, quoted: "arg1" \break ----- \break Called with three arguments \break Macro name: test-macro \break Number of arguments: 3 \break Argument 1: arg1 \break Argument 2: arg2 \break Argument 3: arg3 \break All arguments: arg1 arg2 arg3 \break All arguments, quoted: "arg1" "arg2" "arg3" \break ----- \break Called with five arguments \break Macro name: test-macro \break Number of arguments: 5 \break Argument 1: arg1 \break Argument 2: arg2 \break Argument 3: arg3 \break All arguments: arg1 arg2 arg3 arg4 arg5 \break All arguments, quoted: "arg1" "arg2" "arg3" "arg4" "arg5" \break troffcvt-1.04/troffcvt/tests/shift2a.result010066400017710000151000000015640633745444300226400ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file shift2a \space 72 Number of arguments: 5 \break Arguments: "a" "b" "two words" "" "xyz" \break Recursing... \break \space 72 Number of arguments: 4 \break Arguments: "b" "two words" "" "xyz" \break Recursing... \break \space 72 Number of arguments: 3 \break Arguments: "two words" "" "xyz" \break Recursing... \break \space 72 Number of arguments: 2 \break Arguments: "" "xyz" \break Recursing... \break \space 72 Number of arguments: 1 \break Arguments: "xyz" \break Recursing... \break \space 72 Number of arguments: 0 \break Arguments: \break troffcvt-1.04/troffcvt/tests/mactest1010066400017710000151000000002630631264401400214630ustar00junkyarddatamgmt00000400000027.ig A macro that removes itself, then tries to print the name under which it was invoked (this should work). .. .cp 0 .de xx .rm xx Macro name is (should print "xx"): \\$0 .. .xx troffcvt-1.04/troffcvt/tests/mactest2010066400017710000151000000004320631264407600214720ustar00junkyarddatamgmt00000400000027.ig A macro that redefines itself .. .cp 0 .de xx This is the original xx. .br .de xx This is the redefined xx .br \\.. .xx .. .\" invoke xx - this gets the original xx, which should itself invoke .\" the redefined xx. .xx .\" invoke xx again - this should get the redefined xx .xx troffcvt-1.04/troffcvt/tests/mactest2.result010066400017710000151000000006730633745443200230200ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mactest2 This is the original xx. \break This is the redefined xx \break This is the redefined xx \break troffcvt-1.04/troffcvt/tests/runtest012077700017710000151000000000000634147251400233122../runtestustar00junkyarddatamgmt00000400000027troffcvt-1.04/troffcvt/tests/inputtrap.result010066400017710000151000000007030633745437600233250ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file inputtrap \underline abc input trap sprung \nounderline def \break \space 72 abc input trap sprung def \break troffcvt-1.04/troffcvt/tests/mactest1.result010066400017710000151000000006100633745443000230040ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mactest1 Macro name is (should print "xx"): xx \break troffcvt-1.04/troffcvt/tests/if1010064400017710000151000000007540626662670700204450ustar00junkyarddatamgmt00000400000027.if 1 .tm 1 .if 0 .tm 0 (error) .if !0 .tm !0 .if -1 .tm -1 (error) .if 1/0 .tm 1/0 (error) .if 1%2 .tm 1%2 ACCEPT ELSE PART .ie !t \{\ Level 1, if part, reject .\} .el \{\ Level 1, else part, accept .\} ACCEPT IF PART .ie t \{\ Level 1, if part, accept .\} .el \{\ Level 1, else part, reject .\} ACCEPT IF (level 1) and ELSE (level 2) .ie t \{\ Level 1, if part, accept .ie n \{\ Level 2, if part, reject .\} .el \{\ Level 2, else part, accept .\} .el \{\ Level 1, else part, reject .\} .\} troffcvt-1.04/troffcvt/tests/if2010064400017710000151000000001210626662670700204320ustar00junkyarddatamgmt00000400000027ACCEPT ELSE PART .ie !t \{\ Level 1, reject .\} .el \{\ Level 1, accept .\} DONE troffcvt-1.04/troffcvt/tests/do.result010066400017710000151000000010130633745436600216730ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file do First, with compatibility mode on: string named abcd has value = "abcd]" Second, using .do to temporarily disable compatibility mode string named abcd has value = "this is a string" troffcvt-1.04/troffcvt/tests/alias-m2010066400017710000151000000004710627351177400213640ustar00junkyarddatamgmt00000400000027.ig Define a macro, then define an alias to it. Redefining the original macro should redefine the alias as well, and vice-versa. .. .de xx This is a macro. .br .. .als yy xx .xx .yy .de xx This is a macro, redefined the first time. .br .. .xx .yy .de yy This is a macro, redefined the second time. .br .. .xx .yy troffcvt-1.04/troffcvt/tests/alias-m1010066400017710000151000000002440627351145700213570ustar00junkyarddatamgmt00000400000027.ig Define a macro, then define an alias to it. The alias should produce the same result as the original macro .. .de xx This is a macro. .br .. .als yy xx .xx .yy troffcvt-1.04/troffcvt/tests/alias-s1010066400017710000151000000002500627351155300213570ustar00junkyarddatamgmt00000400000027.ig Define a string, then define an alias to it. The alias should produce the same result as the original string .. .ds xx This is a string. .als yy xx \*(xx .br \*(yy troffcvt-1.04/troffcvt/tests/alias-s2010066400017710000151000000005150627351227700213700ustar00junkyarddatamgmt00000400000027.ig Define a string, then define an alias to it. Redefining the original string should redefine the alias as well, and vice-versa. .. .ds xx This is a string. .als yy xx \*(xx .br \*(yy .br .ds xx This is a string, redefined the first time. \*(xx .br \*(yy .br .ds yy This is a string, redefined the second time. \*(xx .br \*(yy .br troffcvt-1.04/troffcvt/tests/alias-r1010066400017710000151000000004730627353232600213660ustar00junkyarddatamgmt00000400000027.ig Create a register, then create an alias to it, then alias the original name to the alias. This should work. .. .cp 0 .nr r1 10 1 Original value of r1: \n[r1] .br Increment r1. .br .nr r1 \n+[r1] .aln r2 r1 Value of alias r2: \n[r2] .br Increment r2. .br .nr r2 \n+[r2] .aln r1 r2 Value of alias r1: \n[r1] .br troffcvt-1.04/troffcvt/tests/alias-r1.result010066400017710000151000000007370633745434700227150ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file alias-r1 Original value of r1: 10 \break Increment r1. \break Value of alias r2: 11 \break Increment r2. \break Value of alias r1: 12 \break troffcvt-1.04/troffcvt/tests/mac1010066400017710000151000000001400627353264200205660ustar00junkyarddatamgmt00000400000027.ig Define a macro that removes itself. Should succeed without crashing .. .de xx .rm xx .. .xx troffcvt-1.04/troffcvt/tests/mac1.result010066400017710000151000000005270633745437700221250ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac1 troffcvt-1.04/troffcvt/tests/mac2010066400017710000151000000003770627353276500206110ustar00junkyarddatamgmt00000400000027.ig Define a macro that removes itself, then invokes itself. This should fail, in the sense that the macro will no longer be invocable. It should succeed in the sense that the macro doesn't go into an infinite recursion loop. .. .de xx .rm xx .xx .. .xx troffcvt-1.04/troffcvt/tests/mac2.result010066400017710000151000000005270633745440100221120ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac2 troffcvt-1.04/troffcvt/tests/mac3010066400017710000151000000003750627353325700206050ustar00junkyarddatamgmt00000400000027.ig Create a macro that creates an alias to itself, then removes itself, then invokes the alias. This should succeed invoking itself the first time, but then fail with an infinite recursion on yy. .. .de xx This is a macro. .als yy xx .rm xx .yy .. .xx troffcvt-1.04/troffcvt/tests/mac3.result010066400017710000151000000100500633745440400221060ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac3 This is a macro. This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name This is a macro. mac3 (line 13): you cannot alias to non-existing name mac3 (line 13): macro or string possible infinite recursion refused \break troffcvt-1.04/troffcvt/tests/mac4010066400017710000151000000004240627353344500206000ustar00junkyarddatamgmt00000400000027.ig Create a macro that removes itself, then tries to create an alias to itself and invoke the alias. This should fail, because by the time the attempt to create the alias happens, the original macro should be removed from the namelist. .. .de xx .rm xx .als yy xx .yy .. .xx troffcvt-1.04/troffcvt/tests/mac4.result010066400017710000151000000006220633745440500221140ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac4 mac4 (line 13): you cannot alias to non-existing name troffcvt-1.04/troffcvt/tests/mac5010066400017710000151000000003560627353356600206110ustar00junkyarddatamgmt00000400000027.ig Create a macro that prints its name using \$0. Create an alias to the macro. Invoking the macro via the original name and the alias name should print different names. .. .de xx This is the macro named \\$0. .br .. .als yy xx .xx .yy troffcvt-1.04/troffcvt/tests/mac5.result010066400017710000151000000006350633745441100221160ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac5 This is the macro named xx. \break This is the macro named yy. \break troffcvt-1.04/troffcvt/tests/alias-m1.result010066400017710000151000000006130633745434300226750ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file alias-m1 This is a macro. \break This is a macro. \break troffcvt-1.04/troffcvt/tests/alias-m2.result010066400017710000151000000011250633745434500226770ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file alias-m2 This is a macro. \break This is a macro. \break This is a macro, redefined the first time. \break This is a macro, redefined the first time. \break This is a macro, redefined the second time. \break This is a macro, redefined the second time. \break troffcvt-1.04/troffcvt/tests/alias-s1.result010066400017710000151000000006150633745435100227040ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file alias-s1 This is a string. \break This is a string. \break troffcvt-1.04/troffcvt/tests/alias-s2.result010066400017710000151000000011330633745435300227030ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file alias-s2 This is a string. \break This is a string. \break This is a string, redefined the first time. \break This is a string, redefined the first time. \break This is a string, redefined the second time. \break This is a string, redefined the second time. \break troffcvt-1.04/troffcvt/tests/mac6010066400017710000151000000002270627353437700206100ustar00junkyarddatamgmt00000400000027.ig Define a macro that redefines itself as a string, then invokes the string. .. .de xx This is macro xx. .br .ds xx This is string xx. \\*(xx .. .xx troffcvt-1.04/troffcvt/tests/mac7010066400017710000151000000003020627353440300205710ustar00junkyarddatamgmt00000400000027.ig Define a macro that creates an alias to itself, then redefines itself as a string, then invokes the alias. .. .de xx .als yy xx This is macro xx. .br .ds xx This is string xx. \\*(yy .. .xx troffcvt-1.04/troffcvt/tests/mac7.result010066400017710000151000000006120633745441500221170ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac7 This is macro xx. \break This is string xx. \break troffcvt-1.04/troffcvt/tests/mac6.result010066400017710000151000000006120633745441300221140ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac6 This is macro xx. \break This is string xx. \break troffcvt-1.04/troffcvt/tests/str1010066400017710000151000000001710627353462300206430ustar00junkyarddatamgmt00000400000027.ig Define a string that refers to itself. This should fail .. .cp 0 .ds xx This string refers to itself: \\*[xx] \*[xx] troffcvt-1.04/troffcvt/tests/str1.result010066400017710000151000000035440633745445200221710ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file str1 This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself: This string refers to itself:str1 (line 7): macro or string possible infinite recursion refused \break troffcvt-1.04/troffcvt/tests/str2010066400017710000151000000002600627353501700206410ustar00junkyarddatamgmt00000400000027.ig Define a string that refers to another string. This should succeed. .. .cp 0 .ds str1 This is string 1. .ds str2 This is string2 and refers to string 1: \\*[str1] \*[str2] troffcvt-1.04/troffcvt/tests/str2.result010066400017710000151000000006300633745445400221650ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file str2 This is string2 and refers to string 1: This is string 1. \break troffcvt-1.04/troffcvt/tests/str3010066400017710000151000000003110627353515500206420ustar00junkyarddatamgmt00000400000027.ig Define a string that refers to another string, then is renamed to be that other string. This should fail. .. .cp 0 .ds str1 This is string1 and refers to string 2: \\*[str2] .rn str1 str2 \*[str2] troffcvt-1.04/troffcvt/tests/str3.result010066400017710000151000000044500633745445600221740ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file str3 This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2:str3 (line 9): macro or string possible infinite recursion refused \break troffcvt-1.04/troffcvt/tests/str4010066400017710000151000000003320627353526500206500ustar00junkyarddatamgmt00000400000027.ig Define a string that refers to another string. Create the other string as an alias to the first string. This should fail. .. .cp 0 .ds str1 This is string1 and refers to string 2: \\*[str2] .als str2 str1 \*[str1] troffcvt-1.04/troffcvt/tests/str4.result010066400017710000151000000044500633745446000221700ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file str4 This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2: This is string1 and refers to string 2:str4 (line 9): macro or string possible infinite recursion refused \break troffcvt-1.04/troffcvt/tests/mac8010066400017710000151000000004310627353550400206000ustar00junkyarddatamgmt00000400000027.ig Define a macro the redefines itself, then invokes itself. Should get the new definition when it invokes itself. .. .de xx This is the first definition of xx. .br .de xx This is the second definition of xx. \\.. I have redefined myself, now I will invoke myself. .br .xx .. .xx troffcvt-1.04/troffcvt/tests/mac8.result010066400017710000151000000007500633745441700221250ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file mac8 This is the first definition of xx. \break I have redefined myself, now I will invoke myself. \break This is the second definition of xx. \break troffcvt-1.04/troffcvt/tests/trap010066400017710000151000000000440627475135400207220ustar00junkyarddatamgmt00000400000027.de xx sprung! .. .it 1 xx abc\ def troffcvt-1.04/troffcvt/tests/quote2010066400017710000151000000011060630074245100211570ustar00junkyarddatamgmt00000400000027.ig Test handling of macro argument quoting where one macro passes its arguments to another. .. .de yy <\\$1> .. .de xx .yy \\$1 .yy "\\$1" .br .. should be : .xx ab should be : .xx "ab" should be : .xx a"b should be : .xx a""b should be : .xx "a""b" should be <>: .xx "" should be <"">: .xx """""" Now turn compatibility mode on (results may not match expected results): .br .cp 1 should be : .xx ab should be : .xx "ab" should be : .xx a"b should be : .xx a""b should be : .xx "a""b" should be <>: .xx "" should be <"">: .xx """""" troffcvt-1.04/troffcvt/tests/quote2.result010066400017710000151000000016250633745443600225170ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file quote2 should be : \break should be : \break should be : \break should be : \break should be : \break should be <>: <> <> \break should be <"">: <> <""> \break Now turn compatibility mode on (results may not match expected results): \break should be : \break should be : \break should be : \break should be : \break should be : \break should be <>: <> <> \break should be <"">: <> <"> \break troffcvt-1.04/troffcvt/tests/macstring1.result010066400017710000151000000011740633745442500233450ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file macstring1 \nofill Macro name; this should print "outer": outer \break Outer name: outer \break Outer arg count: 5 \break Outer arguments: "a" "b" "c" "d" "e" \break Inner macro is shifting arguments \break Outer name: outer \break Outer arg count: 4 \break Outer arguments: "b" "c" "d" "e" \break troffcvt-1.04/troffcvt/tests/delim1010066400017710000151000000011530631237470700211250ustar00junkyarddatamgmt00000400000027.ig Test whether delimiters in strings are processed at higher input level than the surrounding context. The string values are chosen such that both tests should succeed with compatibility mode off and fail with compatibility mode on. .. .cp 0 .ds xx abc'abc Next test should succeed: .ie '\*(xx'xyz' test failed .el test succeeded .br .ds xx abc'def Next test should succeed: .ie !'\*(xx'\*(xx' test failed .el test succeeded .br .cp 1 .ds xx abc'abc Next test should fail: .ie '\*(xx'xyz' test failed .el test succeeded .br .ds xx abc'def Next test should fail: .ie !'\*(xx'\*(xx' test failed .el test succeeded .br he string values are chosen such that both tests should succeed with compatibility mode off and fail with compatibility mode on. .. .cp 0 .ds xx abc'abc Next test should succeed: .ie '\*(xx'xyz' test failed .el test succeeded .br .ds xx abc'def Next test should succeed: .ie !'\*(xx'\*(xx' test failed .el test succeeded .br .cp 1 .ds xx abc'abc Next test should fail: .ie '\*(xx'xyz' test failed .el testtroffcvt-1.04/troffcvt/tests/delim2010066400017710000151000000006430631240516400211210ustar00junkyarddatamgmt00000400000027.ig Test whether delimiter in string is processed at higher input level than surrounding context in \w'xxx'. .. The width of one character is \w'x'. .br .cp 0 .ds xx abc'abc xx is <\*(xx>. .br Width of xx is \w'\*(xx' (should be 7 character widths [compat mode off]). .br .cp 1 .ds xx abc'abc xx is <\*(xx>. .br Width of xx is \w'\*(xx' (should be 3 character widths with extra garbage following [compat mode on]). .br troffcvt-1.04/troffcvt/tests/slash-a010066400017710000151000000005310631234571300212740ustar00junkyarddatamgmt00000400000027.ig Test the groff \A'xxx' construction. To see what groff does with it, use this command: groff -a this-file .. .ta 2i .nf a \A'a' ab \A'ab' abc \A'abc' \&.abc \A'.abc' a c \A'a c' a"c \A'a"c' a*c \A'a*c' \(ts \A'\(ts' 0 \A'0' 10 \A'10' -1 \A'-1' \e\e \A'\\' \ee \A'\e' \ea \A'\a' \e0 \A'\0' empty \A'' no closing quote \A' nothing after A \A troffcvt-1.04/troffcvt/tests/delim3010066400017710000151000000006060631240527000211170ustar00junkyarddatamgmt00000400000027.ig Test whether delimiter in string is processed at higher input level than surrounding context in: .tl 'left'center'right' If it works, then each part looks like "location'location". Parsing should fail with compatiblity mode on. .. .ds l left'left .ds c center'center .ds r right'right .\" .cp 0 This should work: .br .tl '\*l'\*c'\*r' .br .cp 1 This should fail: .br .tl '\*l'\*c'\*r' troffcvt-1.04/troffcvt/tests/delim3.result010066400017710000151000000011520633745436400224500ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file delim3 This should work: \break \title-begin l left'left \title-end \title-begin m center'center \title-end \title-begin r right'right \title-end \break This should fail: \break \title-begin l left \title-end \title-begin m left \title-end \title-begin r center \title-end \break troffcvt-1.04/troffcvt/tests/delim1.result010066400017710000151000000011030633745454400224420ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file delim1 Next test should succeed: test succeeded \break Next test should succeed: test succeeded \break Next test should fail: xyz @quoteright test failed \break Next test should fail: abc @quoteright def @quoteright test failed \break troffcvt-1.04/troffcvt/tests/delim2.result010066400017710000151000000012160633745456600224540ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file delim2 The width of one character is 30. \break xx is . \break Width of xx is 210 (should be 7 character widths [compat mode off]). \break xx is . \break Width of xx is 90abc @quoteright (should be 3 character widths with extra garbage following [compat mode on]). \break troffcvt-1.04/troffcvt/tests/quote3010066400017710000151000000004750631237665300212020ustar00junkyarddatamgmt00000400000027.ig Test passing of arguments with quotes in them from one macro to another .. .de xx .yy \\$1 .. .de yy Argument is: <\\$1> .br .shift Other args are: <\\$*> .br .. should be "aa" with no remainder: .br .xx aa should be "aa" with remainder "bb": .br .xx "aa bb" should be "aa bb" with no remainder: .br .xx "aa\ bb" troffcvt-1.04/troffcvt/tests/macro-args2010066400017710000151000000003450631244352100220600ustar00junkyarddatamgmt00000400000027.nf .de xx xx arg: <\\$1> .yy \\$1 .yy "\\$1" .. .de yy yy arg: <\\$1> .. Should be : .xx a"b Should be : .xx a""b Should be : .xx "a""b" Should be : .xx "a b" troffcvt-1.04/troffcvt/tests/macro-args2.result010066400017710000151000000013640633745442200234100ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file macro-args2 \nofill Should be : \break xx arg: \break yy arg: \break yy arg: \break Should be : \break xx arg: \break yy arg: \break yy arg: \break Should be : \break xx arg: \break yy arg: \break yy arg: \break Should be : \break xx arg: \break yy arg: \break yy arg: \break troffcvt-1.04/troffcvt/tests/if3010064400017710000151000000001160626662670700204370ustar00junkyarddatamgmt00000400000027ACCEPT IF PART .ie t \{\ Level 1, accept .\} .el \{\ Level 1, reject .\} DONE troffcvt-1.04/troffcvt/tests/if1.result010066400017710000151000000011010633745437000217410ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file if1 1 !0 if1 (line 5): divide by zero detected 1%2 ACCEPT ELSE PART Level 1, else part, accept ACCEPT IF PART Level 1, if part, accept ACCEPT IF (level 1) and ELSE (level 2) Level 1, if part, accept Level 2, else part, accept \break troffcvt-1.04/troffcvt/tests/if2.result010066400017710000151000000006050633745437200217540ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file if2 ACCEPT ELSE PART Level 1, accept DONE \break troffcvt-1.04/troffcvt/tests/if3.result010066400017710000151000000006030633745437400217550ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file if3 ACCEPT IF PART Level 1, accept DONE \break troffcvt-1.04/troffcvt/tests/quote1010066400017710000151000000007160630074243000211610ustar00junkyarddatamgmt00000400000027.ig Test handling of macro argument quoting .. .de xx <\\$1> .br .. should be : .xx ab should be : .xx "ab" should be : .xx a"b should be : .xx a""b should be : .xx "a""b" should be <>: .xx "" should be <"">: .xx """""" Now turn compatibility mode on: .br .cp 1 should be : .xx ab should be : .xx "ab" should be : .xx a"b should be : .xx a""b should be : .xx "a""b" should be <>: .xx "" should be <"">: .xx """""" troffcvt-1.04/troffcvt/tests/macstring2010066400017710000151000000004140631274373100220170ustar00junkyarddatamgmt00000400000027.ig Interpolate a macro as a string, but *not* from within another macro, to verify that no arguments are available to it. .. .cp 0 .\" define inner macro that prints \$0 and \$@. .de xx This should print nothing: \\$0 .br This should print nothing: \\$@ .br .. \*(xx troffcvt-1.04/troffcvt/tests/macstring2.result010066400017710000151000000006530633745442600233500ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file macstring2 This should print nothing: \break This should print nothing: \break \space 72 troffcvt-1.04/troffcvt/tests/macstring1010066400017710000151000000014730631274746400220330ustar00junkyarddatamgmt00000400000027.ig Interpolate a macro as a string from within another macro to verify that the outer macro's arguments don't become hidden and are available to the inner macro. Also verify that shifting the arguments in the inner macro affects the outer macro's arguments. .. .cp 0 .nf .de outer \\*[inner]\\ .. .\" define inner macro that prints \$0. This should print "outer". .de inner Macro name; this should print "outer": \\$0 .. .outer .\" .\" define outer macro that prints arguments, calls inner macro, .\" and prints arguments again .\" .de outer Outer name: \\$0 Outer arg count: \\n[.$] Outer arguments: \\$@ \\*[inner]\\ Outer name: \\$0 Outer arg count: \\n[.$] Outer arguments: \\$@ .. .\" .\" define inner macro that shifts outer macro's arguments .\" .de inner Inner macro is shifting arguments .shift .. .outer a b c d e macro that prints \$0. This should print "outer". .de inner Macro name; this should print "outer": \\$0 .. .outer .\" .\" define outer macro that prints arguments, calls inner macro, .\" and printroffcvt-1.04/troffcvt/tests/quote3.result010066400017710000151000000012020634075007400224760ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file quote3 should be "aa" with no remainder: \break Argument is: \break Other args are: <> \break should be "aa" with remainder "bb": \break Argument is: \break Other args are: \break should be "aa bb" with no remainder: \break Argument is: \break Other args are: <> \break troffcvt-1.04/troffcvt/tests/quote1.result010066400017710000151000000014360633745443400225140ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file quote1 should be : \break should be : \break should be : \break should be : \break should be : \break should be <>: <> \break should be <"">: <""> \break Now turn compatibility mode on: \break should be : \break should be : \break should be : \break should be : \break should be : \break should be <>: <> \break should be <"">: <""> \break troffcvt-1.04/troffcvt/tests/slash-a.result010066400017710000151000000014100634075311000226010ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file slash-a \first-tab 864 l \nofill a @tab 1 \break ab @tab 1 \break abc @tab 1 \break @zerospace .abc @tab 1 \break a c @tab 0 \break a"c @tab 1 \break a*c @tab 1 \break @sigma1 @tab 0 \break 0 @tab 1 \break 10 @tab 1 \break -1 @tab 1 \break @backslash @backslash @tab 1 \break @backslash e @tab 0 \break @backslash a @tab 0 \break @backslash 0 @tab 0 \break empty @tab 0 \break no closing quote @tab 0 \break nothing after A @tab 0 \break troffcvt-1.04/troffcvt/tests/trap.result010066400017710000151000000005560634070426400222370ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file trap abcdef sprung! \break troffcvt-1.04/troffcvt/tests/specials010066400017710000151000000165750634122770200215650ustar00junkyarddatamgmt00000400000027.nf Built-in Special Characters: acute: \e' \' at: @ @ backslash: \ee \\ backspace: \e(backspace) not visible digitspace: \e0 not visible fieldbegin: varies fieldend: varies fieldpad: varies grave: \e` \` hardspace: \e(space) not visible leader: varies minus: \e- \- opthyphen: \e% \% quotedblleft: `` `` quotedblright: '' '' quoteleft: ` ` quoteright: ' ' sixthspace: \e| not visible tab: \et not visible twelfthspace: \e^ not visible zerospace: \e& not visible actions File Special Characters: AE: \e[AE] \[AE] Aacute: \e['A] \['A] Acircumflex: \e[^A] \[^A] Adieresis: \e[:A] \[:A] Agrave: \e[`A] \[`A] Alpha: \e[*A] \[*A] Aring: \e[oA] \[oA] Atilde: \e[~A] \[~A] Beta: \e[*B] \[*B] Cacute: \e['C] \['C] Ccedilla: \e[,C] \[,C] Chi: \e[*X] \[*X] Delta: \e[*D] \[*D] Eacute: \e['E] \['E] Ecircumflex: \e[^E] \[^E] Edieresis: \e[:E] \[:E] Egrave: \e[`E] \[`E] Epsilon: \e[*E] \[*E] Eta: \e[*Y] \[*Y] Eth: \e[-D] \[-D] Gamma: \e[*G] \[*G] IJ: \e[IJ] \[IJ] Iacute: \e['I] \['I] Icircumflex: \e[^I] \[^I] Idieresis: \e[:I] \[:I] Ifraktur: \e[Im] \[Im] Igrave: \e[`I] \[`I] Iota: \e[*I] \[*I] Kappa: \e[*K] \[*K] Lambda: \e[*L] \[*L] Lslash: \e[/L] \[/L] Mu: \e[*M] \[*M] Ntilde: \e[~N] \[~N] Nu: \e[*N] \[*N] OE: \e[OE] \[OE] Oacute: \e['O] \['O] Ocircumflex: \e[^O] \[^O] Odieresis: \e[:O] \[:O] Ograve: \e[`O] \[`O] Omega: \e[*W] \[*W] Omicron: \e[*O] \[*O] Oslash: \e[/O] \[/O] Otilde: \e[~O] \[~O] Phi: \e[*F] \[*F] Pi: \e[*P] \[*P] Psi: \e[*Q] \[*Q] Rfraktur: \e[Re] \[Re] Rho: \e[*R] \[*R] Scaron: \e[vS] \[vS] Sigma: \e[*S] \[*S] Tau: \e[*T] \[*T] Theta: \e[*H] \[*H] Thorn: \e[TP] \[TP] Uacute: \e['U] \['U] Ucircumflex: \e[^U] \[^U] Udieresis: \e[:U] \[:U] Ugrave: \e[`U] \[`U] Upsilon: \e[*U] \[*U] Xi: \e[*C] \[*C] Yacute: \e['Y] \['Y] Ydieresis: \e[:Y] \[:Y] Zcaron: \e[vZ] \[vZ] Zeta: \e[*Z] \[*Z] aacute: \e['a] \['a] acircumflex: \e[^a] \[^a] acute: \e[aa] \[aa] adieresis: \e[:a] \[:a] ae: \e[ae] \[ae] agrave: \e[`a] \[`a] aleph: \e[Ah] \[Ah] alpha: \e[*a] \[*a] angle: \e[/_] \[/_] angleleft: \e[la] \[la] angleright: \e[ra] \[ra] approxequal: \e[~=] \[~=] approxequal: \e[~~] \[~~] aring: \e[oa] \[oa] arrowboth: \e[<>] \[<>] arrowdblboth: \e[hA] \[hA] arrowdbldown: \e[dA] \[dA] arrowdblleft: \e[lA] \[lA] arrowdblright: \e[rA] \[rA] arrowdblup: \e[uA] \[uA] arrowdblvert: \e[vA] \[vA] arrowdown: \e[da] \[da] arrowhorizex: \e[an] \[an] arrowleft: \e[<-] \[<-] arrowright: \e[->] \[->] arrowup: \e[ua] \[ua] arrowvertboth: \e[va] \[va] asciicircum: \e[ha] \[ha] asciitilde: \e[ti] \[ti] asteriskmath: \e[**] \[**] at: \e[at] \[at] atilde: \e[~a] \[~a] backslash: \e[rs] \[rs] bar: \e[ba] \[ba] bar: \e[or] \[or] bell: \e[bs] \[bs] beta: \e[*b] \[*b] br: \e[br] \[br] braceleft: \e[lC] \[lC] braceleftbt: \e[lb] \[lb] braceleftmid: \e[lk] \[lk] bracelefttp: \e[lt] \[lt] braceright: \e[rC] \[rC] bracerightbt: \e[rb] \[rb] bracerightmid: \e[rk] \[rk] bracerighttp: \e[rt] \[rt] bracketleft: \e[lB] \[lB] bracketleftbt: \e[lf] \[lf] bracketlefttp: \e[lc] \[lc] bracketright: \e[rB] \[rB] bracketrightbt: \e[rf] \[rf] bracketrighttp: \e[rc] \[rc] breve: \e[ab] \[ab] brokenbar: \e[bb] \[bb] bullet: \e[bu] \[bu] bv: \e[bv] \[bv] cacute: \e['c] \['c] caron: \e[ah] \[ah] carriagereturn: \e[CR] \[CR] ccedilla: \e[,c] \[,c] cedilla: \e[ac] \[ac] cent: \e[ct] \[ct] checkmark: \e[OK] \[OK] chi: \e[*x] \[*x] circle: \e[ci] \[ci] circlemultiply: \e[c*] \[c*] circleplus: \e[c+] \[c+] circumflex: \e[a^] \[a^] club: \e[CL] \[CL] congruent: \e[=~] \[=~] copyright: \e[co] \[co] currency: \e[Cs] \[Cs] dagger: \e[dg] \[dg] daggerdbl: \e[dd] \[dd] degree: \e[de] \[de] delta: \e[*d] \[*d] diamond: \e[DI] \[DI] dieresis: \e[ad] \[ad] divide: \e[di] \[di] dollar: \e[Do] \[Do] dotaccent: \e[a.] \[a.] dotlessi: \e[.i] \[.i] dotlessj: \e[.j] \[.j] dotmath: \e[md] \[md] eacute: \e['e] \['e] ecircumflex: \e[^e] \[^e] edieresis: \e[:e] \[:e] egrave: \e[`e] \[`e] element: \e[mo] \[mo] emdash: \e[em] \[em] emptyset: \e[es] \[es] endash: \e[en] \[en] epsilon: \e[*e] \[*e] equalmath: \e[eq] \[eq] equivalence: \e[==] \[==] eta: \e[*y] \[*y] eth: \e[Sd] \[Sd] exclamdown: \e[r!] \[r!] existential: \e[te] \[te] ff: \e[ff] \[ff] ffi: \e[Fi] \[Fi] ffl: \e[Fl] \[Fl] fi: \e[fi] \[fi] fl: \e[fl] \[fl] florin: \e[Fn] \[Fn] fraction: \e[f/] \[f/] gamma: \e[*g] \[*g] germandbls: \e[ss] \[ss] gradient: \e[gr] \[gr] grave: \e[ga] \[ga] greaterequal: \e[>=] \[>=] guillemotleft: \e[Fo] \[Fo] guillemotright: \e[Fc] \[Fc] guilsinglleft: \e[fo] \[fo] guilsinglright: \e[fc] \[fc] handleft: \e[lh] \[lh] handright: \e[rh] \[rh] hbar: \e[-h] \[-h] heart: \e[HE] \[HE] hungarumlaut: \e[a"] \[a"] hyphen: \e[hy] \[hy] iacute: \e['i] \['i] icircumflex: \e[^i] \[^i] idieresis: \e[:i] \[:i] igrave: \e[`i] \[`i] ij: \e[ij] \[ij] infinity: \e[if] \[if] integral: \e[is] \[is] intersection: \e[ca] \[ca] iota: \e[*i] \[*i] kappa: \e[*k] \[*k] lambda: \e[*l] \[*l] lessequal: \e[<=] \[<=] logicaland: \e[AN] \[AN] logicalnot: \e[no] \[no] logicalor: \e[OR] \[OR] lozenge: \e[lz] \[lz] lslash: \e[/l] \[/l] macron: \e[a-] \[a-] minusmath: \e[mi] \[mi] minusplus: \e[-+] \[-+] minute: \e[fm] \[fm] mu: \e[*m] \[*m] muchgreater: \e[>>] \[>>] muchless: \e[<<] \[<<] multiply: \e[mu] \[mu] notelement: \e[nm] \[nm] notequal: \e[!=] \[!=] notequivalence: \e[ne] \[ne] notpropersuperset: \e[nc] \[nc] notsubset: \e[nb] \[nb] ntilde: \e[~n] \[~n] nu: \e[*n] \[*n] numbersign: \e[sh] \[sh] oacute: \e['o] \['o] ocircumflex: \e[^o] \[^o] odieresis: \e[:o] \[:o] oe: \e[oe] \[oe] ogonek: \e[ho] \[ho] ograve: \e[`o] \[`o] omega: \e[*w] \[*w] omega1: \e[+p] \[+p] omicron: \e[*o] \[*o] onehalf: \e[12] \[12] onequarter: \e[14] \[14] onesuperior: \e[S1] \[S1] ordfeminine: \e[Of] \[Of] ordmasculine: \e[Om] \[Om] oslash: \e[/o] \[/o] otilde: \e[~o] \[~o] paragraph: \e[ps] \[ps] partialdiff: \e[pd] \[pd] perpendicular: \e[pp] \[pp] perthousand: \e[%0] \[%0] phi: \e[*f] \[*f] phi1: \e[+f] \[+f] pi: \e[*p] \[*p] plusmath: \e[pl] \[pl] plusminus: \e[+-] \[+-] propersubset: \e[sb] \[sb] propersuperset: \e[sp] \[sp] proportional: \e[pt] \[pt] psi: \e[*q] \[*q] questiondown: \e[r?] \[r?] quotedblbase: \e[Bq] \[Bq] quotedblleft: \e[lq] \[lq] quotedblright: \e[rq] \[rq] quoteleft: \e[oq] \[oq] quotesinglbase: \e[bq] \[bq] quotesingle: \e[aq] \[aq] radical: \e[sr] \[sr] radicalex: \e[rn] \[rn] reflexsubset: \e[ib] \[ib] reflexsuperset: \e[ip] \[ip] registered: \e[rg] \[rg] rho: \e[*r] \[*r] ring: \e[ao] \[ao] ru: \e[ru] \[ru] scaron: \e[vs] \[vs] second: \e[sd] \[sd] section: \e[sc] \[sc] sigma: \e[*s] \[*s] sigma1: \e[ts] \[ts] similar: \e[ap] \[ap] slash: \e[sl] \[sl] spade: \e[SP] \[SP] square: \e[sq] \[sq] sterling: \e[Po] \[Po] suchthat: \e[st] \[st] tau: \e[*t] \[*t] therefore: \e[3d] \[3d] therefore: \e[tf] \[tf] theta: \e[*h] \[*h] theta1: \e[+h] \[+h] thorn: \e[Tp] \[Tp] threequarters: \e[34] \[34] threesuperior: \e[S3] \[S3] tilde: \e[a~] \[a~] trademark: \e[tm] \[tm] twosuperior: \e[S2] \[S2] uacute: \e['u] \['u] ucircumflex: \e[^u] \[^u] udieresis: \e[:u] \[:u] ugrave: \e[`u] \[`u] ul: \e[ul] \[ul] umlaut: \e[..] \[..] union: \e[cu] \[cu] universal: \e[fa] \[fa] upsilon: \e[*u] \[*u] weierstrass: \e[wp] \[wp] xi: \e[*c] \[*c] yacute: \e['y] \['y] ydieresis: \e[:y] \[:y] yen: \e[Ye] \[Ye] zcaron: \e[vz] \[vz] zeta: \e[*z] \[*z] troffcvt-1.04/troffcvt/tests/specials.result010066400017710000151000000377220634123030000230630ustar00junkyarddatamgmt00000400000027\comment processing action file ../actions \setup-begin \resolution 432 \page-length 4752 \point-size 10 \space-size 20 \spacing 72 \line-spacing 1 \offset 432 \line-length 2808 \indent 0 \title-length 2808 \hyphenate 1 \adjust-full \nounderline \font R \page-number 0 \setup-end \temp-indent 0 \reset-tabs \comment processing input file specials \nofill Built-in Special Characters: \break @tab acute: @backslash @quoteright @acute \break @tab at: @at @at \break @tab backslash: @backslash e @backslash \break @tab backspace: @backslash (backspace) not visible \break @tab digitspace: @backslash 0 not visible \break @tab fieldbegin: varies \break @tab fieldend: varies \break @tab fieldpad: varies \break @tab grave: @backslash @quoteleft @grave \break @tab hardspace: @backslash (space) not visible \break @tab leader: varies \break @tab minus: @backslash - @minus \break @tab opthyphen: @backslash % @opthyphen \break @tab quotedblleft: @quotedblleft @quotedblleft \break @tab quotedblright: @quotedblright @quotedblright \break @tab quoteleft: @quoteleft @quoteleft \break @tab quoteright: @quoteright @quoteright \break @tab sixthspace: @backslash | not visible \break @tab tab: @backslash t not visible \break @tab twelfthspace: @backslash ^ not visible \break @tab zerospace: @backslash & not visible \break \space 72 actions File Special Characters: \break @tab AE: @backslash [AE] @AE \break @tab Aacute: @backslash [ @quoteright A] @Aacute \break @tab Acircumflex: @backslash [^A] @Acircumflex \break @tab Adieresis: @backslash [:A] @Adieresis \break @tab Agrave: @backslash [ @quoteleft A] @Agrave \break @tab Alpha: @backslash [*A] @Alpha \break @tab Aring: @backslash [oA] @Aring \break @tab Atilde: @backslash [~A] @Atilde \break @tab Beta: @backslash [*B] @Beta \break @tab Cacute: @backslash [ @quoteright C] @Cacute \break @tab Ccedilla: @backslash [,C] @Ccedilla \break @tab Chi: @backslash [*X] @Chi \break @tab Delta: @backslash [*D] @Delta \break @tab Eacute: @backslash [ @quoteright E] @Eacute \break @tab Ecircumflex: @backslash [^E] @Ecircumflex \break @tab Edieresis: @backslash [:E] @Edieresis \break @tab Egrave: @backslash [ @quoteleft E] @Egrave \break @tab Epsilon: @backslash [*E] @Epsilon \break @tab Eta: @backslash [*Y] @Eta \break @tab Eth: @backslash [-D] @Eth \break @tab Gamma: @backslash [*G] @Gamma \break @tab IJ: @backslash [IJ] @IJ \break @tab Iacute: @backslash [ @quoteright I] @Iacute \break @tab Icircumflex: @backslash [^I] @Icircumflex \break @tab Idieresis: @backslash [:I] @Idieresis \break @tab Ifraktur: @backslash [Im] @Ifraktur \break @tab Igrave: @backslash [ @quoteleft I] @Igrave \break @tab Iota: @backslash [*I] @Iota \break @tab Kappa: @backslash [*K] @Kappa \break @tab Lambda: @backslash [*L] @Lambda \break @tab Lslash: @backslash [/L] @Lslash \break @tab Mu: @backslash [*M] @Mu \break @tab Ntilde: @backslash [~N] @Ntilde \break @tab Nu: @backslash [*N] @Nu \break @tab OE: @backslash [OE] @OE \break @tab Oacute: @backslash [ @quoteright O] @Oacute \break @tab Ocircumflex: @backslash [^O] @Ocircumflex \break @tab Odieresis: @backslash [:O] @Odieresis \break @tab Ograve: @backslash [ @quoteleft O] @Ograve \break @tab Omega: @backslash [*W] @Omega \break @tab Omicron: @backslash [*O] @Omicron \break @tab Oslash: @backslash [/O] @Oslash \break @tab Otilde: @backslash [~O] @Otilde \break @tab Phi: @backslash [*F] @Phi \break @tab Pi: @backslash [*P] @Pi \break @tab Psi: @backslash [*Q] @Psi \break @tab Rfraktur: @backslash [Re] @Rfraktur \break @tab Rho: @backslash [*R] @Rho \break @tab Scaron: @backslash [vS] @Scaron \break @tab Sigma: @backslash [*S] @Sigma \break @tab Tau: @backslash [*T] @Tau \break @tab Theta: @backslash [*H] @Theta \break @tab Thorn: @backslash [TP] @Thorn \break @tab Uacute: @backslash [ @quoteright U] @Uacute \break @tab Ucircumflex: @backslash [^U] @Ucircumflex \break @tab Udieresis: @backslash [:U] @Udieresis \break @tab Ugrave: @backslash [ @quoteleft U] @Ugrave \break @tab Upsilon: @backslash [*U] @Upsilon \break @tab Xi: @backslash [*C] @Xi \break @tab Yacute: @backslash [ @quoteright Y] @Yacute \break @tab Ydieresis: @backslash [:Y] @Ydieresis \break @tab Zcaron: @backslash [vZ] @Zcaron \break @tab Zeta: @backslash [*Z] @Zeta \break @tab aacute: @backslash [ @quoteright a] @aacute \break @tab acircumflex: @backslash [^a] @acircumflex \break @tab acute: @backslash [aa] @acute \break @tab adieresis: @backslash [:a] @adieresis \break @tab ae: @backslash [ae] @ae \break @tab agrave: @backslash [ @quoteleft a] @agrave \break @tab aleph: @backslash [Ah] @aleph \break @tab alpha: @backslash [*a] @alpha \break @tab angle: @backslash [/_] @angle \break @tab angleleft: @backslash [la] @angleleft \break @tab angleright: @backslash [ra] @angleright \break @tab approxequal: @backslash [~=] @approxequal \break @tab approxequal: @backslash [~~] @approxequal \break @tab aring: @backslash [oa] @aring \break @tab arrowboth: @backslash [<>] @arrowboth \break @tab arrowdblboth: @backslash [hA] @arrowdblboth \break @tab arrowdbldown: @backslash [dA] @arrowdbldown \break @tab arrowdblleft: @backslash [lA] @arrowdblleft \break @tab arrowdblright: @backslash [rA] @arrowdblright \break @tab arrowdblup: @backslash [uA] @arrowdblup \break @tab arrowdblvert: @backslash [vA] @arrowdblvert \break @tab arrowdown: @backslash [da] @arrowdown \break @tab arrowhorizex: @backslash [an] @arrowhorizex \break @tab arrowleft: @backslash [<-] @arrowleft \break @tab arrowright: @backslash [->] @arrowright \break @tab arrowup: @backslash [ua] @arrowup \break @tab arrowvertboth: @backslash [va] @arrowvertboth \break @tab asciicircum: @backslash [ha] @asciicircum \break @tab asciitilde: @backslash [ti] @asciitilde \break @tab asteriskmath: @backslash [**] @asteriskmath \break @tab at: @backslash [at] @at \break @tab atilde: @backslash [~a] @atilde \break @tab backslash: @backslash [rs] @backslash \break @tab bar: @backslash [ba] @bar \break @tab bar: @backslash [or] @bar \break @tab bell: @backslash [bs] @bell \break @tab beta: @backslash [*b] @beta \break @tab br: @backslash [br] @br \break @tab braceleft: @backslash [lC] @braceleft \break @tab braceleftbt: @backslash [lb] @braceleftbt \break @tab braceleftmid: @backslash [lk] @braceleftmid \break @tab bracelefttp: @backslash [lt] @bracelefttp \break @tab braceright: @backslash [rC] @braceright \break @tab bracerightbt: @backslash [rb] @bracerightbt \break @tab bracerightmid: @backslash [rk] @bracerightmid \break @tab bracerighttp: @backslash [rt] @bracerighttp \break @tab bracketleft: @backslash [lB] @bracketleft \break @tab bracketleftbt: @backslash [lf] @bracketleftbt \break @tab bracketlefttp: @backslash [lc] @bracketlefttp \break @tab bracketright: @backslash [rB] @bracketright \break @tab bracketrightbt: @backslash [rf] @bracketrightbt \break @tab bracketrighttp: @backslash [rc] @bracketrighttp \break @tab breve: @backslash [ab] @breve \break @tab brokenbar: @backslash [bb] @brokenbar \break @tab bullet: @backslash [bu] @bullet \break @tab bv: @backslash [bv] @bv \break @tab cacute: @backslash [ @quoteright c] @cacute \break @tab caron: @backslash [ah] @caron \break @tab carriagereturn: @backslash [CR] @carriagereturn \break @tab ccedilla: @backslash [,c] @ccedilla \break @tab cedilla: @backslash [ac] @cedilla \break @tab cent: @backslash [ct] @cent \break @tab checkmark: @backslash [OK] @checkmark \break @tab chi: @backslash [*x] @chi \break @tab circle: @backslash [ci] @circle \break @tab circlemultiply: @backslash [c*] @circlemultiply \break @tab circleplus: @backslash [c+] @circleplus \break @tab circumflex: @backslash [a^] @circumflex \break @tab club: @backslash [CL] @club \break @tab congruent: @backslash [=~] @congruent \break @tab copyright: @backslash [co] @copyright \break @tab currency: @backslash [Cs] @currency \break @tab dagger: @backslash [dg] @dagger \break @tab daggerdbl: @backslash [dd] @daggerdbl \break @tab degree: @backslash [de] @degree \break @tab delta: @backslash [*d] @delta \break @tab diamond: @backslash [DI] @diamond \break @tab dieresis: @backslash [ad] @dieresis \break @tab divide: @backslash [di] @divide \break @tab dollar: @backslash [Do] @dollar \break @tab dotaccent: @backslash [a.] @dotaccent \break @tab dotlessi: @backslash [.i] @dotlessi \break @tab dotlessj: @backslash [.j] @dotlessj \break @tab dotmath: @backslash [md] @dotmath \break @tab eacute: @backslash [ @quoteright e] @eacute \break @tab ecircumflex: @backslash [^e] @ecircumflex \break @tab edieresis: @backslash [:e] @edieresis \break @tab egrave: @backslash [ @quoteleft e] @egrave \break @tab element: @backslash [mo] @element \break @tab emdash: @backslash [em] @emdash \break @tab emptyset: @backslash [es] @emptyset \break @tab endash: @backslash [en] @endash \break @tab epsilon: @backslash [*e] @epsilon \break @tab equalmath: @backslash [eq] @equalmath \break @tab equivalence: @backslash [==] @equivalence \break @tab eta: @backslash [*y] @eta \break @tab eth: @backslash [Sd] @eth \break @tab exclamdown: @backslash [r!] @exclamdown \break @tab existential: @backslash [te] @existential \break @tab ff: @backslash [ff] @ff \break @tab ffi: @backslash [Fi] @ffi \break @tab ffl: @backslash [Fl] @ffl \break @tab fi: @backslash [fi] @fi \break @tab fl: @backslash [fl] @fl \break @tab florin: @backslash [Fn] @florin \break @tab fraction: @backslash [f/] @fraction \break @tab gamma: @backslash [*g] @gamma \break @tab germandbls: @backslash [ss] @germandbls \break @tab gradient: @backslash [gr] @gradient \break @tab grave: @backslash [ga] @grave \break @tab greaterequal: @backslash [>=] @greaterequal \break @tab guillemotleft: @backslash [Fo] @guillemotleft \break @tab guillemotright: @backslash [Fc] @guillemotright \break @tab guilsinglleft: @backslash [fo] @guilsinglleft \break @tab guilsinglright: @backslash [fc] @guilsinglright \break @tab handleft: @backslash [lh] @handleft \break @tab handright: @backslash [rh] @handright \break @tab hbar: @backslash [-h] @hbar \break @tab heart: @backslash [HE] @heart \break @tab hungarumlaut: @backslash [a"] @hungarumlaut \break @tab hyphen: @backslash [hy] @hyphen \break @tab iacute: @backslash [ @quoteright i] @iacute \break @tab icircumflex: @backslash [^i] @icircumflex \break @tab idieresis: @backslash [:i] @idieresis \break @tab igrave: @backslash [ @quoteleft i] @igrave \break @tab ij: @backslash [ij] @ij \break @tab infinity: @backslash [if] @infinity \break @tab integral: @backslash [is] @integral \break @tab intersection: @backslash [ca] @intersection \break @tab iota: @backslash [*i] @iota \break @tab kappa: @backslash [*k] @kappa \break @tab lambda: @backslash [*l] @lambda \break @tab lessequal: @backslash [<=] @lessequal \break @tab logicaland: @backslash [AN] @logicaland \break @tab logicalnot: @backslash [no] @logicalnot \break @tab logicalor: @backslash [OR] @logicalor \break @tab lozenge: @backslash [lz] @lozenge \break @tab lslash: @backslash [/l] @lslash \break @tab macron: @backslash [a-] @macron \break @tab minusmath: @backslash [mi] @minusmath \break @tab minusplus: @backslash [-+] @minusplus \break @tab minute: @backslash [fm] @minute \break @tab mu: @backslash [*m] @mu \break @tab muchgreater: @backslash [>>] @muchgreater \break @tab muchless: @backslash [<<] @muchless \break @tab multiply: @backslash [mu] @multiply \break @tab notelement: @backslash [nm] @notelement \break @tab notequal: @backslash [!=] @notequal \break @tab notequivalence: @backslash [ne] @notequivalence \break @tab notpropersuperset: @backslash [nc] @notpropersuperset \break @tab notsubset: @backslash [nb] @notsubset \break @tab ntilde: @backslash [~n] @ntilde \break @tab nu: @backslash [*n] @nu \break @tab numbersign: @backslash [sh] @numbersign \break @tab oacute: @backslash [ @quoteright o] @oacute \break @tab ocircumflex: @backslash [^o] @ocircumflex \break @tab odieresis: @backslash [:o] @odieresis \break @tab oe: @backslash [oe] @oe \break @tab ogonek: @backslash [ho] @ogonek \break @tab ograve: @backslash [ @quoteleft o] @ograve \break @tab omega: @backslash [*w] @omega \break @tab omega1: @backslash [+p] @omega1 \break @tab omicron: @backslash [*o] @omicron \break @tab onehalf: @backslash [12] @onehalf \break @tab onequarter: @backslash [14] @onequarter \break @tab onesuperior: @backslash [S1] @onesuperior \break @tab ordfeminine: @backslash [Of] @ordfeminine \break @tab ordmasculine: @backslash [Om] @ordmasculine \break @tab oslash: @backslash [/o] @oslash \break @tab otilde: @backslash [~o] @otilde \break @tab paragraph: @backslash [ps] @paragraph \break @tab partialdiff: @backslash [pd] @partialdiff \break @tab perpendicular: @backslash [pp] @perpendicular \break @tab perthousand: @backslash [%0] @perthousand \break @tab phi: @backslash [*f] @phi \break @tab phi1: @backslash [+f] @phi1 \break @tab pi: @backslash [*p] @pi \break @tab plusmath: @backslash [pl] @plusmath \break @tab plusminus: @backslash [+-] @plusminus \break @tab propersubset: @backslash [sb] @propersubset \break @tab propersuperset: @backslash [sp] @propersuperset \break @tab proportional: @backslash [pt] @proportional \break @tab psi: @backslash [*q] @psi \break @tab questiondown: @backslash [r?] @questiondown \break @tab quotedblbase: @backslash [Bq] @quotedblbase \break @tab quotedblleft: @backslash [lq] @quotedblleft \break @tab quotedblright: @backslash [rq] @quotedblright \break @tab quoteleft: @backslash [oq] @quoteleft \break @tab quotesinglbase: @backslash [bq] @quotesinglbase \break @tab quotesingle: @backslash [aq] @quotesingle \break @tab radical: @backslash [sr] @radical \break @tab radicalex: @backslash [rn] @radicalex \break @tab reflexsubset: @backslash [ib] @reflexsubset \break @tab reflexsuperset: @backslash [ip] @reflexsuperset \break @tab registered: @backslash [rg] @registered \break @tab rho: @backslash [*r] @rho \break @tab ring: @backslash [ao] @ring \break @tab ru: @backslash [ru] @ru \break @tab scaron: @backslash [vs] @scaron \break @tab second: @backslash [sd] @second \break @tab section: @backslash [sc] @section \break @tab sigma: @backslash [*s] @sigma \break @tab sigma1: @backslash [ts] @sigma1 \break @tab similar: @backslash [ap] @similar \break @tab slash: @backslash [sl] @slash \break @tab spade: @backslash [SP] @spade \break @tab square: @backslash [sq] @square \break @tab sterling: @backslash [Po] @sterling \break @tab suchthat: @backslash [st] @suchthat \break @tab tau: @backslash [*t] @tau \break @tab therefore: @backslash [3d] @therefore \break @tab therefore: @backslash [tf] @therefore \break @tab theta: @backslash [*h] @theta \break @tab theta1: @backslash [+h] @theta1 \break @tab thorn: @backslash [Tp] @thorn \break @tab threequarters: @backslash [34] @threequarters \break @tab threesuperior: @backslash [S3] @threesuperior \break @tab tilde: @backslash [a~] @tilde \break @tab trademark: @backslash [tm] @trademark \break @tab twosuperior: @backslash [S2] @twosuperior \break @tab uacute: @backslash [ @quoteright u] @uacute \break @tab ucircumflex: @backslash [^u] @ucircumflex \break @tab udieresis: @backslash [:u] @udieresis \break @tab ugrave: @backslash [ @quoteleft u] @ugrave \break @tab ul: @backslash [ul] @ul \break @tab umlaut: @backslash [..] @umlaut \break @tab union: @backslash [cu] @union \break @tab universal: @backslash [fa] @universal \break @tab upsilon: @backslash [*u] @upsilon \break @tab weierstrass: @backslash [wp] @weierstrass \break @tab xi: @backslash [*c] @xi \break @tab yacute: @backslash [ @quoteright y] @yacute \break @tab ydieresis: @backslash [:y] @ydieresis \break @tab yen: @backslash [Ye] @yen \break @tab zcaron: @backslash [vz] @zcaron \break @tab zeta: @backslash [*z] @zeta \break sh: @backslash [rs] @backslash \break @tab btroffcvt-1.04/troffcvt/tc.ms010064400017710000151000000016460630754035600176400ustar00junkyarddatamgmt00000400000027# -ms-specific stuff. Helps a little to make title/author/etc. stuff better. # define an internal-use-only request to reset the paragraph state req reset*para*params eol \ break center 0 fill adjust b font R \ point-size 10 spacing 12 line-spacing 1 imm remove-name n TL req TL parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".ce 999\n.ps +2\n.vs 14\n.ft B\n" imm remove-name n AU req AU parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".ce 999\n.ft I\n" imm remove-name n AI req AI parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".ce 999\n" # needs to write "ABSTRACT" if arg1 isn't "no" imm remove-name n AB req AB parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".if !'$1'no' \\{\\\n.sp\n.ce\n\\fIABSTRACT\\fR\n.sp\n.\\}\n" # groff -ms does a weird thing with .TS. Disable it here. imm remove-name n TS req TS eol troffcvt-1.04/troffcvt/actions-html010066400017710000151000000035210631366726200212150ustar00junkyarddatamgmt00000400000027req H*title eol output-control "html title" req H*header parse-num x eol output-control "html header $1" req H*header*end eol output-control "html header-end" req H*para eol output-control "html para" req H*disp eol output-control "html display" font CW req H*disp*end eol font R output-control "html display-end" req H*disp*indent parse-num x eol output-control "html display-indent $1" req H*bq eol output-control "html blockquote" req H*bq*end eol output-control "html blockquote-end" req H*list eol output-control "html list" req H*list*end eol output-control "html list-end" req H*list*item eol output-control "html list-item" req H*dterm eol output-control "html definition-term" req H*ddesc eol output-control "html definition-desc" req H*shift*right eol output-control "html shift-right" req H*shift*left eol output-control "html shift-left" # anchor macros: # .H*ahref URL -> # .H*aname LABEL -> # .H*atoc N -> begin level-N TOC entry (generates tag) # .H*aend -> req H*ahref parse-macro-args eol output-control 'html anchor-href "$1"' req H*aname parse-macro-args eol output-control 'html anchor-name "$1"' req H*atoc parse-num x eol output-control 'html anchor-toc $1' req H*aend eol output-control 'html anchor-end' # For the TOC title, reset any justification/centering that may be in effect. # If there is a second argument, make the location marker advisory only req H*toc*title parse-macro-args eol \ break fill adjust b \ push-string ".H*header 2\n$1\n.H*header*end\n" \ push-string ".ds H*tmp\n.if !'$2'' .ds H*tmp , MAYBE\n" \ push-string '.H*toc*marker "\n' req H*toc*marker parse-macro-args eol output-control "pass $1" # .Html stuff -> pass stuff straight through to output, no interpretation req Html parse-macro-args eol output-control 'pass $*' troffcvt-1.04/troffcvt/tc.wrprc-html010064400017710000151000000027100630145067700213110ustar00junkyarddatamgmt00000400000027# tmac.wrprc-specific stuff. # HTML-specific redefinitions for tmac.wrprc # Ah, Bh, Ch need additional break before output text imm remove-name y Ah req Ah parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*atoc 1\n" \ push-string ".H*header 2\n" \ push-string "$1\n" \ push-string ".H*header*end\n" \ push-string ".H*aend\n" imm remove-name y Bh req Bh parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*atoc 2\n" \ push-string ".H*header 3\n" \ push-string "$1\n" \ push-string ".H*header*end\n" \ push-string ".H*aend\n" imm remove-name y Ch req Ch parse-macro-args eol \ break center 0 fill adjust b \ push-string ".H*atoc 3\n" \ font "B" push-string "$1\n" font "R" \ push-string ".H*aend\n" # for the fill stuff, should really save the fill value, then restore imm remove-name y Ps req Ps parse-macro-args eol \ break center 0 nofill \ push-string ".ta 4n +4n +4n +4n +4n +4n +4n +4n\n" \ push-string ".H*disp*indent 3\n" \ push-string ".H*disp\n" imm remove-name y Pe req Pe parse-macro-args eol \ break center 0 fill \ push-string ".ta .5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i\n" \ push-string ".H*disp*end\n" imm remove-name y Ls req Ls parse-macro-args eol \ break \ push-string ".H*list\n" imm remove-name y Li req Li parse-macro-args eol \ break \ push-string ".H*list*item\n" imm remove-name y Le req Le parse-macro-args eol \ break \ push-string ".H*list*end\n" troffcvt-1.04/troffcvt/runtest.pl010066400017710000151000000022510634070416500207220ustar00junkyarddatamgmt00000400000027 # Script type: perl require "getopts.pl"; ($prog = $0) =~ s|.*/||; # get script name for messages $usage = "Usage: $prog [ -d ] [ testname ]"; &Getopts ("d") || die "$usage\n"; $showdiff = defined ($opt_d); # unbuffer STDOUT select (STDOUT); $| = 1; $alltests = (@ARGV == 0); # run all tests if no specific test named $troffcvt = "../troffcvt"; $actions = "../actions"; die "$prog: $troffcvt not found\n" unless -x $troffcvt; if ($alltests == 0) { @tests = @ARGV; } else { print "Running all tests...\n"; opendir (DH, ".") || die "$prog: can't read current directory\n"; @tests = sort (grep (s/\.result$//, readdir (DH))); closedir (DH); } foreach $test (@tests) { print "$test: "; if (! -f $test) { print "test input file not found\n"; } elsif (! -f "$test.result") { print "test result file not found\n"; } else { system "$troffcvt -A -a $actions $test > tmp 2>&1"; $result = system "$(CMP) $test.result tmp > /dev/null 2>&1"; $result /= 256; print $result == 0 ? "OK\n" : "*** not OK ***\n"; if ($result != 0 && $showdiff) { print "diff $test.result tmp:\n"; system "diff $test.result tmp"; } } } unlink "tmp" unless $showdiff; exit (0); troffcvt-1.04/troffcvt/tc.man010064400017710000151000000054130632503615100177610ustar00junkyarddatamgmt00000400000027# -man-specific stuff. # The requests below are used for font changes, because if the groff -man # macros are used, some of the macros with these names are implemented # using "while", which troffcvt doesn't understand. imm remove-name n B req B parse-macro-args eol \ push-string ".ie $$=0 .ft B\n.el \\&\\fB$*\\fP\n" imm remove-name n BR req BR parse-macro-args eol \ push-string ".if $$=0 .ft B\n" \ push-string ".if $$=1 \\fB$1\\fR\n" \ push-string ".if $$=2 \\fB$1\\fR$2\n" \ push-string ".if $$=3 \\fB$1\\fR$2\\fB$3\\fR\n" \ push-string ".if $$=4 \\fB$1\\fR$2\\fB$3\\fR$4\n" \ push-string ".if $$=5 \\fB$1\\fR$2\\fB$3\\fR$4\\fB$5\\fR\n" \ push-string ".if $$>5 \\fB$1\\fR$2\\fB$3\\fR$4\\fB$5\\fR$6\n" imm remove-name n BI req BI parse-macro-args eol \ push-string ".if $$=0 .ft B\n" \ push-string ".if $$=1 \\fB$1\\fR\n" \ push-string ".if $$=2 \\fB$1\\fI$2\\fR\n" \ push-string ".if $$=3 \\fB$1\\fI$2\\fB$3\\fR\n" \ push-string ".if $$=4 \\fB$1\\fI$2\\fB$3\\fI$4\\fR\n" \ push-string ".if $$=5 \\fB$1\\fI$2\\fB$3\\fI$4\\fB$5\\fR\n" \ push-string ".if $$>5 \\fB$1\\fI$2\\fB$3\\fI$4\\fB$5\\fI$6\\fR\n" imm remove-name n I req I parse-macro-args eol \ push-string ".ie $$=0 .ft I\n.el \\&\\fI$*\\fP\n" imm remove-name n IR req IR parse-macro-args eol \ push-string ".if $$=0 .ft I\n" \ push-string ".if $$=1 \\fI$1\\fR\n" \ push-string ".if $$=2 \\fI$1\\fR$2\n" \ push-string ".if $$=3 \\fI$1\\fR$2\\fI$3\\fR\n" \ push-string ".if $$=4 \\fI$1\\fR$2\\fI$3\\fR$4\n" \ push-string ".if $$=5 \\fI$1\\fR$2\\fI$3\\fR$4\\fI$5\\fR\n" \ push-string ".if $$>5 \\fI$1\\fR$2\\fI$3\\fR$4\\fI$5\\fR$6\\fR\n" imm remove-name n IB req IB parse-macro-args eol \ push-string ".if $$=0 .ft I\n" \ push-string ".if $$=1 \\fI$1\\fR\n" \ push-string ".if $$=2 \\fI$1\\fB$2\\fR\n" \ push-string ".if $$=3 \\fI$1\\fB$2\\fI$3\\fR\n" \ push-string ".if $$=4 \\fI$1\\fB$2\\fI$3\\fB$4\\fR\n" \ push-string ".if $$=5 \\fI$1\\fB$2\\fI$3\\fB$4\\fI$5\\fR\n" \ push-string ".if $$>5 \\fI$1\\fB$2\\fI$3\\fB$4\\fI$5\\fB$6\\fR\n" imm remove-name n RB req RB parse-macro-args eol \ push-string ".if $$=0 .ft R\n" \ push-string ".if $$=1 \\fR$1\n" \ push-string ".if $$=2 \\fR$1\\fB$2\\fR\n" \ push-string ".if $$=3 \\fR$1\\fB$2\\fR$3\n" \ push-string ".if $$=4 \\fR$1\\fB$2\\fR$3\\fB$4\\fR\n" \ push-string ".if $$=5 \\fR$1\\fB$2\\fR$3\\fB$4\\fR$5\n" \ push-string ".if $$>5 \\fR$1\\fB$2\\fR$3\\fB$4\\fR$5\\fB$6\\fR\n" imm remove-name n RI req RI parse-macro-args eol \ push-string ".if $$=0 .ft R\n" \ push-string ".if $$=1 \\fR$1\n" \ push-string ".if $$=2 \\fR$1\\fI$2\\fR\n" \ push-string ".if $$=3 \\fR$1\\fI$2\\fR$3\n" \ push-string ".if $$=4 \\fR$1\\fI$2\\fR$3\\fI$4\\fR\n" \ push-string ".if $$=5 \\fR$1\\fI$2\\fR$3\\fI$4\\fR$5\n" \ push-string ".if $$>5 \\fR$1\\fI$2\\fR$3\\fI$4\\fR$5\\fI$6\\fR\n" troffcvt-1.04/troffcvt/tc.mm-html010066400017710000151000000001160630145015500205540ustar00junkyarddatamgmt00000400000027# HTML-specific redefinitions for -mm # unfortunately, there are none yet... troffcvt-1.04/troffcvt/tc.me-html010066400017710000151000000122630630317535500205620ustar00junkyarddatamgmt00000400000027# -me-specific stuff for tc2html # Need: # - +c # - (c, )c # - default is different for (z than for (l, (b. # - .sh should number headings # this helps to map -me macros onto tc2hmtl concepts # When a name is redefined below, it's first removed. This is because groff # aliases many of the macros to an error macro until .TL is seen. Unless # a given name is removed before being redefined, redefining it would also # redefine all the other names that are aliases for it! # define an internal-use-only request to reset the paragraph state req reset*para*params eol \ break fill adjust b font R \ point-size 10 spacing 12 line-spacing 1 # define a request for resetting the numbered-paragraph register, and invoke # the request immediately req reset*para*num eol \ push-string ".nr \$p 0 1\n" imm push-string ".reset*para*num\n" imm remove-name n lp req lp parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".reset*para*num\n" \ push-string ".H*para\n" font "R" imm remove-name n pp imm alias-macro pp lp # write indented paragraphs as a definition list imm remove-name n ip req ip parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*dterm\n" font "R" \ push-string "$1" \ push-string ".H*ddesc\n" # write bulleted paragraphs as an indented paragraph with a bullet tag imm remove-name n bu req bu parse-macro-args eol \ push-string ".ip \\(bu\n" # write numbered paragraphs as an indented paragraph with a number tag imm remove-name n np req np parse-macro-args eol \ push-string ".ip (\\n+(\$p)\n" imm remove-name n RS req RS parse-macro-args eol \ break \ push-string ".H*shift*right\n" imm remove-name n RE req RE parse-macro-args eol \ break \ push-string ".H*shift*left\n" # if the first argument is < 1, use "1". Then generate, for argument # N, a level-N TOC entry and a level-(N+1) header using the second argument # for the header text. imm remove-name n sh req sh parse-num x parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".reset*para*num\n" \ push-string ".if $1<1 .nr H*sh*level 1 1\n" \ push-string ".if $1>0 .nr H*sh*level $1 1\n" \ push-string ".H*atoc \\n[H*sh*level]\n" \ push-string ".H*header \\n+[H*sh*level]\n" \ push-string "$2\n" \ push-string ".H*header*end\n" \ push-string ".H*aend\n" # .uh T is like .sh 1 T imm remove-name n uh req uh parse-macro-args eol \ push-string '.sh 1 "$1"\n' imm remove-name n (q req (q parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*bq" font "R" imm remove-name n )q req )q parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*bq*end" font "R" # Begin a block as a display. Argument is the display indent. req H*me*list parse-macro-args eol \ push-string ".reset*para*params\n" \ nofill \ push-string ".H*disp*indent $1\n" \ push-string ".H*disp" font "R" # End a block display req H*me*list*end parse-macro-args eol \ push-string ".H*disp*end" \ push-string ".reset*para*params\n" # Begin a block. Arguments are: # $1 = Default display for no-fill case # $2 = Default display for fill case # $3, $4 = The m and f arguments to the calling macro, as those argument # are explained in the -me reference. # # H*me*list*type indicates the list type: # 0 = regular list, indented # 1 = regular list, not indented # 2 = center line-by-line # 3 = just like .lp req H*me*block parse-macro-args eol \ push-string ".nr H*me*list*type $1\n" \ push-string ".if '$3'' .nr H*me*list*type $1\n" \ push-string ".if '$3'F' .nr H*me*list*type $2\n" \ push-string ".if '$3'' .if '$4'F' .nr H*me*list*type $2\n" \ push-string ".if '$3'C' .nr H*me*list*type 2\n" \ push-string ".if '$3'I' .nr H*me*list*type 0\n" \ push-string ".if '$3'I' .if '$4'F' .nr H*me*list*type 3\n" \ push-string ".if '$3'L' .nr H*me*list*type 1\n" \ push-string ".if '$3'L' .if '$4'F' .nr H*me*list*type 3\n" \ push-string ".if '$3'M' .nr H*me*list*type 1\n" \ push-string ".if '$3'M' .if '$4'F' .nr H*me*list*type 3\n" \ push-string ".if \\n[H*me*list*type]=0 .H*me*list 3\n" \ push-string ".if \\n[H*me*list*type]=1 .H*me*list 0\n" \ push-string ".if \\n[H*me*list*type]=2 .ce 9999\n" \ push-string ".if \\n[H*me*list*type]=3 .lp\n" # End a block. (This assumes blocks aren't nested.) req H*me*block*end eol \ push-string ".if \\n[H*me*list*type]=0 .H*me*list*end\n" \ push-string ".if \\n[H*me*list*type]=1 .H*me*list*end\n" \ push-string ".if \\n[H*me*list*type]=2 .ce 0\n" \ push-string '.if \\n[H*me*list*type]=3 .\\" nothing to do\n' imm remove-name n (b req (b parse-macro-args eol push-string ".H*me*block 0 3 $1 $2\n" imm remove-name n )b req )b eol push-string ".H*me*block*end\n" imm remove-name n (l imm alias-macro (l (b imm remove-name n )l imm alias-macro )l )b imm remove-name n (z req (z parse-macro-args eol push-string ".H*me*block 1 3 $1 $2\n" imm remove-name n )z req )z eol push-string ".H*me*block*end\n" # Footnote support. All these versions of .(f/.)f do is bracket the # footnote text with "[[footnote:" and "]]" so that at least the # footnote can be recognized for what it is. imm remove-name n (f req (f eol push-string "[[footnote:\n" imm remove-name n )f req )f eol push-string "]]\n" troffcvt-1.04/troffcvt/main.c010064400017710000151000000426620634065350100177560ustar00junkyarddatamgmt00000400000027/* * - Need platform-independent way of getting current date. * (Why? doesn't this work on a Macintosh?) */ /* * troffcvt - troff-to-XXX converter * * Options: * * -rN Set internal resolution to N * -a file Read action file * -A Don't read default action file * -dN Turn on debugging flag N (N missing = all flags) * -l Turn on "\line file number" output * -mXX Read macro package file XX * -t troff Act like troff * -t nroff Act like nroff * -C Turn on compatibility mode (long names not recognized) * * The default action file is read before any other action files named on * the command line. * * 02 Apr 92 Paul DuBois dubois@primate.wisc.edu * * 02 Apr 92 V1.00. Created. * * 16 Dec 96 * - Added -C option to turn on compatibility mode. This was added because * other code was changed to allow long name references using [xxx], and * -C provides a way to turn that off if needed. The register .C is also * set now to indicate whether compatibility mode is on or off. * 28 Dec 96 * - Change -troff and -nroff options to -t troff and -t nroff. Also allow * -t groff now, which sets the .g register non-zero and triggers other * groff-like behaviors. * - Add -A option to suppress reading default action file. * 24 Jan 97 * - Make acting like groff the standard behavior. -tgroff is no longer * necessary. * 17 Feb 97 * - Add -l command line option. */ #include #include #include /* for size_t */ #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "portlib.h" #include "etm.h" #include "memmgr.h" #include "tcgen.h" #include "tcunix.h" #include "troffcvt.h" #define defActionFile "actions" #define maxFileCount 20 /* max number of -a and -m files */ #define actionFileType 1 #define macroFileType 2 static void AddSetupFile (char *name, short type); static void ReadSetupFiles (void); static void SetupDefaults (void); static void WriteDefaults (void); static int ReadMacroFile (char *file); static char *FindFileByPathList (char *file, char *pathEnvVar); int troff = 1; /* 0 = nroff, !0 = troff */ Param resolution = 432; /* units/inch */ int allowInput = 1; /* input chars */ XChar escChar = defEscChar; /* escape char */ int doEscapes = 1; /* whether to process escape char */ int inCharTest = 0; /* whether processing .if c */ XChar ctrlChar = defCtrlChar; /* request control character */ XChar nbCtrlChar = defNbCtrlChar; /* non-break control character */ XChar curCtrlChar; /* ctrl char from current request */ XChar fieldDelimChar = '\0'; /* field delim char (null = none) */ XChar fieldPadChar = '\0'; /* field padding char */ int fieldDelimCount = 0; /* fdc's seen on current line */ XChar optHyphenChar; /* optional hyphen char */ /* output chars */ XChar tabChar = '\0'; /* tab char (null = motion) */ XChar leaderChar = '\0'; /* leader char (null = motion) */ int needSpace = 0; int inContinuation = 0; int ifLevel = 0; int ifResult = 1; /* set TRUE so any wayward .el will be skipped */ XChar fontTab[maxFonts][maxFontNameLen]; XChar curFont[maxFontNameLen]; XChar prevFont[maxFontNameLen]; XChar *itMacro = (XChar *) NULL; Param itCount = 0; XChar *endMacro = (XChar *) NULL; Param centerCount = 0; Param ulCount = 0; Param cUlCount = 0; Param fillMode = fill; Param adjMode = adjFull; Param adjust = 1; Param curSize; Param prevSize; Param curSpaceSize; Param curVSize; Param prevVSize; Param curLineSpacing; Param prevLineSpacing; Param curIndent; Param prevIndent; Param curTempIndent; Param curLineLen; Param prevLineLen; Param curPageLen; Param curPageNum; Param curOffset; Param prevOffset; Param curHyphenMode; Param pageNumChar; Param curTitleLen; Param prevTitleLen; Param curTabCount; Param tabPos[maxTabStops]; char tabType[maxTabStops]; Param compatMode = 0; long debug = 0; short writeLineInfo = 0; short dumpBadReq = 0; static short readDefActionFile = 1; static char *fileList[maxFileCount]; static short fileType[maxFileCount]; static short fileCount = 0; int main (argc, argv) int argc; char *argv[]; { char buf[bufSiz]; char *p; int inc; ETMInit (NULL); UnixSetProgPath (argv[0]); TCRSetOpenLibFileProc (UnixOpenLibFile); SetOpenMacroFileProc (UnixOpenMacroFile); /* examine option arguments */ --argc; ++argv; while (argc > 0 && argv[0][0] == '-' && argv[0][1] != '\0') { inc = 1; if (strncmp (argv[0], "-d", (size_t) 2) == 0) { if (argv[0][2] != '\0') debug |= (1 << StrToLong (&argv[0][2])); else debug = 0xffffffff; } else if (strcmp (argv[0], "-A") == 0) { /* don't read default action file */ readDefActionFile = 0; } else if (strncmp (argv[0], "-a", (size_t) 2) == 0) { if (argv[0][2] != '\0') p = &argv[0][2]; else if (argc > 1) { p = argv[1]; inc = 2; } else ETMPanic ("missing filename after -a"); AddSetupFile (p, actionFileType); } else if (strncmp (argv[0], "-m", (size_t) 2) == 0) { if (argv[0][2] == '\0') ETMPanic ("empty macro package specifier"); AddSetupFile (&argv[0][2], macroFileType); } else if (strncmp (argv[0], "-r", 2) == 0) { if (argv[0][2] != '\0') resolution = StrToLong (&argv[0][2]); else if (argc > 1) { resolution = StrToLong (argv[1]); inc = 2; } else ETMPanic ("missing resolution after -r"); if (resolution < 1) ETMPanic ("nonsensical resolution: %ld", resolution); } else if (strncmp (argv[0], "-t", 2) == 0) { if (argv[0][2] != '\0') p = &argv[0][2]; else if (argc > 1) { p = argv[1]; inc = 2; } else ETMPanic ("missing formatter type after -t"); if (strcmp (p, "troff") == 0) troff = 1; else if (strcmp (p, "nroff") == 0) troff = 0; else ETMPanic ("unknown formatter type: %s", p); } else if (strcmp (argv[0], "-C") == 0) compatMode = 1; else if (strcmp (argv[0], "-l") == 0) writeLineInfo = 1; else ETMPanic ("Unknown option: %s", argv[0]); argc -= inc; argv += inc; } if (debug) { /* don't want output order mixed up by buffering */ setbuf (stdout, (char *) NULL); setbuf (stderr, (char *) NULL); } InitTransliterate (); (void) AllowOutput (0); /* turn off output while doing setup */ SetupDefaults (); /* reset these here - its known that resolution won't change */ /*(void) StrNewRegister (".H", resolution, (Param) 0, "1", 1);*/ /*(void) StrNewRegister (".V", resolution, (Param) 0, "1", 1);*/ /*(void) StrNewRegister (".w", Units (1, 'n'), (Param) 0, "1", 1);*/ InitEnvironments (); /* read default action file unless -A was specified */ if (readDefActionFile) { if (!ReadActionFile (defActionFile)) { ETMPanic ("cannot read action file <%s>", defActionFile); } InitEnvironments (); } /* Read action and macro files specified on command line */ ReadSetupFiles (); /* Turn output back on and force out initial state */ (void) AllowOutput (1); WriteDefaults (); if (argc == 0) /* stdin */ { CommentOut ("processing input (stdin)"); if (!PushFile ((char *) NULL)) ETMPanic ("Cannot read stdin"); ReadInput (); } else while (argc > 0) { char buf[bufSiz]; if (strcmp (argv[0], "-") == 0) { CommentOut ("processing input file (stdin)"); if (!PushFile ((char *) NULL)) ETMMsg ("Cannot read stdin"); else ReadInput (); } else if (strncmp (argv[0], "-a", (size_t) 2) == 0) { if (argv[0][2] != '\0') p = &argv[0][2]; else if (argc > 1) { p = argv[1]; --argc; ++argv; } else ETMPanic ("missing filename after -a"); if (!ReadActionFile (p)) ETMMsg ("cannot read action file <%s>", p); } else { sprintf (buf, "processing input file %s", argv[0]); CommentOut (buf); if (!PushFile (argv[0])) ETMMsg ("Cannot open: %s", argv[0]); else ReadInput (); } --argc; ++argv; } /* do .em here if defined (no arguments) */ if (endMacro != (XChar *) NULL) { (void) PushMacro (endMacro, 0, (XChar **) NULL); ReadInput (); } /* Force a break in case a paragraph was still being collected */ Break (); ETMEnd (); exit (0); /*NOTREACHED*/ } /* * Set up defaults. * * troff manual says 26/27i for initial default offset, but that * was because of a 1/27i paper margin. Use 1i. * * Other values are set to those in the Ossanna manual. */ static void SetupDefaults (void) { struct tm *tm; time_t t; XChar buf[2]; int i; /* * General registers */ (void) time (&t); tm = localtime (&t); (void) StrNewRegister ("dw", (Param) tm->tm_wday+1, (Param) 0, "1", 0); (void) StrNewRegister ("dy", (Param) tm->tm_mday, (Param) 0, "1", 0); (void) StrNewRegister ("mo", (Param) tm->tm_mon+1, (Param) 0, "1", 0); (void) StrNewRegister ("yr", (Param) tm->tm_year, (Param) 0, "1", 0); (void) StrNewRegister ("%", (Param) 0, (Param) 0, "1", 0); (void) StrNewRegister (".b", (Param) 0, (Param) 0, "1", 0); (void) StrNewRegister ("c.", (Param) 0, (Param) 0, "1", 0); (void) StrNewRegister (".R", (Param) 10000, (Param) 0, "1", 0); /* * Read-only registers. Most are created with value zero, * but are modified by SetXXX() functions in setget.c. * Members of the first group below are actually supported, * members of the second group are created just so that * attempts to modify them can be noticed. * * Resolution-related registers (.H, .V, .w) are affected by the * -rN command-line option if that was given; but SetupDefaults() * is not called until after options are examined, so it's safe * to set them here and leave them alone. */ (void) StrNewRegister ("$$", (Param) GetPid (), (Param) 0, "1", 1); (void) StrNewRegister (".$", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".H", resolution, (Param) 0, "1", 1); (void) StrNewRegister (".V", resolution, (Param) 0, "1", 1); (void) StrNewRegister (".c", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".f", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".i", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".j", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".l", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".L", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".o", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".p", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".s", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".u", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".v", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".A", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".T", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".a", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".d", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".h", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".k", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".n", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".P", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".t", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".w", Units (1, 'n'), (Param) 0, "1", 1); (void) StrNewRegister (".x", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".y", (Param) 0, (Param) 0, "1", 1); (void) StrNewRegister (".z", (Param) 0, (Param) 0, "1", 1); /* * groff-related stuff * * .g is non-zero if troffcvt is supposed to try to act like groff * (which it always does). * .C indicates whether or not compatibility mode is turned on. If * so, it turns off groff long names. .g is always on. .C is off, * unless the -C command-line option is given. * .ev is really a string-valued register, so the name here is * fake. */ (void) StrNewRegister (".g", (Param) 1, (Param) 0, "1", 1); (void) StrNewRegister (".C", (Param) compatMode, (Param) 0, "1", 1); (void) StrNewRegister (".ev", (Param) 0, (Param) 0, "1", 1); /* font position zero is reserved */ curFont[0] = '\0'; prevFont[0] = '\0'; buf[0] = ' '; buf[1] = '\0'; SetFontNameBySlot ((Param) 0, buf); buf[0] = 'R'; SetFontNameBySlot ((Param) 1, buf); buf[0] = 'I'; SetFontNameBySlot ((Param) 2, buf); buf[0] = 'B'; SetFontNameBySlot ((Param) 3, buf); buf[0] = 'S'; for (i = 4; i < maxFonts; i++) SetFontNameBySlot ((Param) i, buf); buf[0] = 'R'; SetFont (buf); /* do twice to get current and previous */ SetFont (buf); /* both set to same value */ SetCFA ((Param) 0, (Param) 1, (Param) 1, (Param) adjFull); SetUnderline ((Param) 0, (Param) 0); curPageLen = Units (11, 'i'); curSize = prevSize = Units (10, 'x'); curSpaceSize = Units (12./36., 'm'); curVSize = prevVSize = Units (12, 'p'); curLineSpacing = prevLineSpacing = Units (1, 'v'); curIndent = prevIndent = Units (0, 'i'); curTempIndent = Units (0, 'i'); curLineLen = prevLineLen = Units (6.5, 'i'); curOffset = prevOffset = Units (0, 'i'); curTitleLen = prevTitleLen = Units (6.5, 'i'); SetTabStops ((Param) 0, tabPos, tabType); /* * Need curPageNum so can refer to "page-number" in * parse-absrel-num action */ curPageNum = StrGetRegisterValue ("%"); pageNumChar = '%'; curHyphenMode = 1; optHyphenChar = ToEsc ('%'); } /* * Since most of the SetXXX() functions only write out values * when they *change* from the current value (to avoid writing * unnecessary output), a trick is used to force out current * values: change the relevant parameter externally to the * SetXXX() function, then pass the real value back in to * both set it and write it out. Also then sync "previous" value * of revertibles to current value. * * Ugly tricks are also used to get the CFA, underlining and font * values written and synced. */ static void WriteDefaults (void) { XChar fontBuf[bufSiz]; XChar fakeFontBuf[2]; char buf[bufSiz]; ControlOut ("setup-begin"); sprintf (buf, "resolution %ld", resolution); ControlOut (buf); SetPageLength (++curPageLen - 1); SetSize (++curSize - 1); prevSize = curSize; SetSpaceSize (++curSpaceSize - 1); SetSpacing (++curVSize - 1); prevVSize = curVSize; SetLineSpacing (++curLineSpacing - 1); prevLineSpacing = curLineSpacing; SetOffset (++curOffset - 1); prevOffset = curOffset; SetLineLength (++curLineLen - 1); prevLineLen = curLineLen; SetIndent (++curIndent - 1); prevIndent = curIndent; SetTitleLength (++curTitleLen - 1); prevTitleLen = curTitleLen; SetHyphenation (++curHyphenMode - 1); /* more than a little ugly */ (void) AllowOutput (0); SetCFA (centerCount, fillMode, (Param) !adjust, adjMode); (void) AllowOutput (1); SetCFA (centerCount, fillMode, (Param) !adjust, adjMode); (void) AllowOutput (0); SetUnderline (ulCount + 1, cUlCount); (void) AllowOutput (1); SetUnderline (ulCount - 1, cUlCount); (void) AllowOutput (0); (void) XStrCpy (fontBuf, curFont); fakeFontBuf[0] = ' '; /* real fonts will never have this name */ fakeFontBuf[1] = 0; SetFont (fakeFontBuf); (void) AllowOutput (1); SetFont (fontBuf); /* will write out font */ SetFont (fontBuf); /* won't write, but syncs prevFont */ SetPageNumber (++curPageNum - 1); ControlOut ("setup-end"); SetTempIndent (++curTempIndent - 1); SetTabStops (++curTabCount - 1, tabPos, tabType); } /* * Add an action or macro file to the list of setup files to be read */ void AddSetupFile (char *name, short type) { if (fileCount >> maxFileCount) ETMPanic ("too many action/macro files named on command line"); fileList[fileCount] = name; fileType[fileCount] = type; ++fileCount; } /* * Read action and macro files named by -a and -m options on command line */ void ReadSetupFiles (void) { char buf[bufSiz]; char *name; short i; short out; for (i = 0; i < fileCount; i++) { name = fileList[i]; /* ETMMsg ("Read %s file %s", fileType[i] == actionFileType ? "action" : "macro", fileList[i]); */ if (fileType[i] == actionFileType) /* action file */ { if (!ReadActionFile (name)) ETMMsg ("cannot read action file <%s>", name); } else /* macro file */ { sprintf (buf, "%s%s", MACROFILEPREFIX, name); if (!ReadMacroFile (buf)) ETMPanic ("cannot read macro file for -m%s", name); } } } /* * Read and process input until there is no more */ void ReadInput (void) { while (ProcessLine ()) { /* */ } } /* * Process a single input line */ int ProcessLine (void) { int c; if ((c = ChPeek ()) == endOfInput) return (0); if (c == ctrlChar || c == nbCtrlChar) ProcessRequest (0); else if (c == ToEsc ('!')) /* transparent mode */ { /* BUG */ /* this isn't really correct since */ /* BUG */ /* \n, \$, \*, \w should still be processed */ SkipToEol (); } else ProcessText (); return (1); } int ProcessActionList (Action *ap) { XChar *argv[maxActionArgs+1]; /* +1 to allow for NULL at end */ int status; int i; while (ap != (Action *) NULL) { if (Debug (bugActionProcess)) ETMMsg ("processing %s %d", ap->actName, ap->actArgc); for (i = 0; i < ap->actArgc; i++) argv[i] = XStrAlloc (InterpretActionArg (ap->actArgv[i])); argv[i] = (XChar *) NULL; /* add NULL argument at end */ status = (*ap->actFunc) (ap->actArgc, argv); for (i = 0; i < ap->actArgc; i++) XStrFree (argv[i]); if (!status) return (0); /* action failed, bail out */ ap = ap->actNext; } return (1); } /* * Open and read a macro file. Be careful not to pass NULL to PushFile(), * because it will try to read stdin then. * * Return non-zero if the file was read, zero otherwise */ static int ReadMacroFile (char *file) { char buf[bufSiz]; char *p; short out; p = FindMacroFile (file); if (p == (char *) NULL) return (0); out = AllowOutput (1); sprintf (buf, "processing macro file %s", p); CommentOut (buf); (void) AllowOutput (0); if (!PushFile (p)) return (0); ReadInput (); return (1); } ETMPanic ("missing filename after -a"); if (!ReadActionFile (p)) ETMMstroffcvt-1.04/troffcvt/tmac.wrprc010064400017710000151000000107710630145063100206610ustar00junkyarddatamgmt00000400000027.\" .\" Font Notes: .\" CW, CB, CI are used for non-proportional, non-proportional bold, and .\" non-proportional italic (courier, courier-bold, courier-italic). If .\" the font names are different at your site, change definitions of .\" of .Cw, .Cb, and .Ci below. There may be other inline references to .\" CW, CB, and CI that need to be changed as well. .\" .\" The inline font reference is given using \f[xx], which requires a .\" version of troff that understands the [xx] notation, e.g., groff. .\" .\" .\" Ft - font reference .\" $1 = font to use for .ft switches .\" $2 = font to use for inline \f switches .\" $3 = thing to put in the given font .\" $4 = goes immediately after $3 .\" $5 = goes immediately before $4 .\" if $3-$5 are empty, simply switch font w/o switching back .de Ft .nr PQ \\n(.f .ie \(ts\\$3\\$4\\$5\(ts\(ts .ft \\$1 .el \&\\$5\\f[\\$2]\\$3\\f\\n(PQ\&\\$4 .. .\" .\" Cw - constant width font .de Cw .Ft CW CW "\\$1" "\\$2" "\\$3" .. .\" .\" Cb - bold constant width font .de Cb .Ft CB CB "\\$1" "\\$2" "\\$3" .. .\" .\" Ci - italic constant width font .de Ci .Ft CI CI "\\$1" "\\$2" "\\$3" .. .\" .\" I - italic font .de I .Ft I I "\\$1" "\\$2" "\\$3" .. .\" .\" B - bold font .de B .Ft B B "\\$1" "\\$2" "\\$3" .. .\" .\" Bi - bold italic font .de Bi .Ft BI BI "\\$1" "\\$2" "\\$3" .. .\" .\" Most of following are from ORA .\" .de Ps \" Printout start; $1 = indent (default is 5 spaces) .br .\".RT .nr pS \\n(.s \" Save current point size .nr vS \\n(.v \" Save current vertical spacing .nr pF \\n(.f \" Save current font .nr pI \\n(.iu \" Save current indent .sp \\n(PDu .ns .\".ps 9 .\".vs 11 .ps 8 .vs 10 .ft CW .ie !"\\$1"" .in \\n(.iu+\\$1n .el .in \\n(.iu+5n .nf .\" 4n doesn't work. How come? .\".ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n .nr Cw 4*\\w`n` .ta \\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu +\\n(Cwu .rr Cw .. .de Pe \" Printout end; if $1 non-null, no concluding blank line .br .if "\\$1"" .sp \\n(PDu .ps \\n(pS .vs \\n(vSu .ft \\n(pF .in \\n(pIu .rr pS .rr vS .rr pF .rr pI .fi .. .\" .\" Vertical ellipsis with squished vertical spacing. Optional argument .\" sets indent (restored afterward). .\" .de Ve .if !`\\$1`` .in \\$1 .vs 4 \&. \&. \&. .vs .if !`\\$1`` .in .. .\" .de Ls .\" list start; $1 = A(LPHA), a(alpha), B(ullet), N(umeric), .\" R(oman), r(oman); $2 = indent .br .if !"\\$1"P" .if !"\\$1"A" .if !"\\$1"B" .if !"\\$1"N" .if !"\\$1"R" \ . if !"\\$1"r" .if !"\\$1"a" .if !"\\$1"" \ .tm "Ls: Need A a B N R r or null as list type--abort" .nr l\\n+(l0 0 1 .ie "\\$1"" \{\ . if "\\n(l0"1" .af l\\n(l0 1 \" default to numeric at 1st level . if "\\n(l0"2" .af l\\n(l0 a \" default to lc alphabetic at 2nd level . if "\\n(l0"3" .af l\\n(l0 i \" default to lc roman at 3rd level . if "\\n(l0"4" .ds l\\n(l0 \(bu \" default to bullet at 4th level . if "\\n(l0"5" .ds l\\n(l0 \f3\-\f1 \" default to dash at 5th level . if \\n(l0-5 .ds l\\n(l0\(bu \" default to bullet above 5rd level . if \\n(l0-3 .nr l\\n(l0 0-1 . \} .el \{\ . if "\\$1"A" .af l\\n(l0 A . if "\\$1"P" .ds LK P . if "\\$1"a" .af l\\n(l0 a . if "\\$1"B"\{\ . if "\\$3"" .ds l\\n(l0 \(bu . if !"\\$3"" .ds l\\n(l0 \\$3 . nr l\\n(l0 0-1 . \} . if "\\$1"R" .af l\\n(l0 I . if "\\$1"r" .af l\\n(l0 i \} .ie !"\\$2"" .nr i\\n(l0 \\$2 \" list indent .el .nr i\\n(l0 3 \" default indent (used to be 5) .\".nr I0 0 .if \\n(l0>1 .RS .\".if \\n(IP=0 .in 0 .. .nr l0 0 1 \" initialize list nesting level counter .de Li \" list item; $1 = 0 means no blank line before item .br .if "\\$1"0" .ns .ie "\\n(l\\n(l0"-1" .IP "\\*(l\\n(l0" "\\n(i\\n(l0" .el \{\ . nr l\\n(l0 +1 . ie !"\\*(LK"P" .IP "\\n(l\\n(l0." "\\n(i\\n(l0" . el .IP "\fB\\n(l\\n(l0\fP" "\\n(i\\n(l0" . \} .. .de Le \" list end; $1 = 0 means no extra blank line following last item .br .rr l\\n(l0 .rr i\\n(l0 .rm l\\n(l0 .if \\n(l0>1 .RE .nr l0 -1 .ie !\\n(l0 \{\ . ie "\\$1"0" .LP 0 . el .LP\} .el .if !"\\$1"0" .sp \\n(PDu .\".if \\n(IP=0 'in 0 .. .\" .\" Ah, Bh, Ch - headings for various levels. $1 = heading .\" .de Ah .sp .RT .ne 5 .ps 14 .vs 16 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .de Bh .sp .RT .ne 5 .ps 11 .vs 13 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .de Ch .sp .RT .ne 5 .ps 10 .vs 12 .lg 0 .B \&\\$1 .R .lg .sp .ns .. .\" .\" Reset margins and paragraph distance. .nr PO 1.2i \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance ncludintroffcvt-1.04/troffcvt/tc.mdoc010064400017710000151000000000300631213421600201130ustar00junkyarddatamgmt00000400000027# -mdoc-specific stuff. troffcvt-1.04/troffcvt/tc.mdoc-html010066400017710000151000000006100631215624600210720ustar00junkyarddatamgmt00000400000027# HTML-specific redefinitions for -mdoc # this helps to map -mdoc macros onto tc2hmtl concepts # define an internal-use-only request to reset the paragraph state req reset*para*params eol \ break font R fill adjust b \ point-size 10 spacing 12 line-spacing 1 imm remove-name n Pp req Pp parse-macro-args eol \ push-string ".reset*para*params\n" \ push-string ".H*para\n" font "R" troffcvt-1.04/tblcvt/004077500017710000151000000000000634140312200163135ustar00junkyarddatamgmt00000400000027troffcvt-1.04/tblcvt/Imakefile010064400017710000151000000001720627620336500201350ustar00junkyarddatamgmt00000400000027XCOMM tblcvt Makefile ScriptFromMsubTemplate($(PERL5PATH),tblcvt,tblcvt.pl,NullArg) InstallScript(tblcvt,$(LOCALBINDIR)) troffcvt-1.04/tblcvt/Makefile010066400017710000151000000260310634136770000177650ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./tblcvt # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # tblcvt Makefile all:: tblcvt tblcvt:: tblcvt.pl $(RM) $@ echo "#!"$(PERL5PATH) > $@ $(MSUB) tblcvt.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) tblcvt help_aux:: @echo "'make "tblcvt"' to "build the tblcvt script install:: i.tblcvt help_aux:: @echo "'make "i.tblcvt"' to "install tblcvt i.tblcvt:: tblcvt @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTSCRIPTFLAGS) tblcvt $(LOCALBINDIR)/tblcvt # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend troffcvt-1.04/tblcvt/tblcvt.pl010066400017710000151000001060660634044560100201630ustar00junkyarddatamgmt00000400000027# To do: # - What if format says one type of line and data says another? # (In gtbl, the data takes precedence). # - Doesn't compute border values properly. Need function to set particular # border value, after clearing value for that border. # - box/allbox and doublebox aren't mutually exclusive. # - Error messages aren't great - they often are misleading wrt line number. # To do a better job of this, probably would need to do more data line # checking as soon as the line is parsed. # Script type: perl5 # tblcvt - troffcvt table preprocessor # Read troff input looking for tables (.TS + .TE and everything in between). # Parse table options and format lines, then read table data lines and write # them out in a more easily parsable form. # The output is intended to be used with troffcvt and a special set of # request redefinitions. The output cannot be parsed by troffcvt with # compatibility mode enabled (i.e., you cannot specify the -C flag to # troffcvt). # Table specifications are collected using these variables (among others): # @format Each element of this array is itself an array holding the # column entries for a row of format specifiers. # @rawdata Each element of this array holds one line of table data # (after \ continuation collapsing). The array holds "real" # data, and data lines that are actually just troff commands # (beginning with a dot). The variable $datarows is set to # the number of data rows that are *not* troff commands. # @formatidx Array to map $rawdata[i] to the index of the format row to be # used when formatting the data row. Elements of this array # may have the following values: # >= 0 Index into @format # -1 The data row is a line-drawing row and doesn't need # a format row # -2 The data row is a troff command # 05 Feb 1997 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 05 Feb 97 V1.00 # - Created. use strict refs; ($prog = $0) =~ s|.*//||; # get script name for messages @c = (); # character buffer # state numbers and initial state $seek_table = 1; $seek_options_or_format = 2; $seek_format = 3; $seek_table_content = 4; $state = $seek_table; $table_num = 0; # table alignment types # # Note that since the values are strings, must compare using # "eq" rather than "==". $align_left = "L"; $align_center = "C"; # End per-table values # Per-column values # Column entry types. For the first set, it's important that the # values be the key letter that signifies the corresponding column type. # For the second set, the values must be something that isn't any other column # type specifier. $col_borderonly is a special fake type used for the case # that a format line ends in | or || but has no other specifier following # it. $col_empty is a special fake type used to indicate in the output that # a cell's data is empty. $col_X is used during span calculations (it means # any non-span, non-line-drawing format type). # # Note that since the values are strings, must compare using # "eq" rather than "==". $col_left = "L"; $col_right = "R"; $col_center = "C"; $col_numeric = "N"; $col_alpha = "A"; $col_hspan = "S"; $col_vspan = "^"; $col_line = "_"; $col_dbl_line = "="; $col_borderonly = "|"; $col_empty = "E"; $col_X = "X"; $col_visited = "1"; $col_unknown = "0"; # border specifiers (these are or'ed together as necessary) $bord_left_s = 1; # left border, single/double $bord_left_d = 2; $bord_right_s = 4; # right border, single/double $bord_right_d = 8; $bord_top_s = 16; # top border, single/double $bord_top_d = 32; $bord_bottom_s = 64; # bottom border, single/double $bord_bottom_d = 128; # masks to pull out parts of border $bord_left = ($bord_left_s | $bord_left_d); $bord_right = ($bord_right_s | $bord_right_d); $bord_top = ($bord_top_s | $bord_top_d); $bord_bottom = ($bord_bottom_s | $bord_bottom_d); # End per-column values # Output request names $tbl_begin = ".T*table*begin"; $tbl_end = ".T*table*end"; $tbl_col_info = ".T*column*info"; $tbl_row_begin = ".T*row*begin"; $tbl_row_end = ".T*row*end"; $tbl_cell_info = ".T*cell*info"; $tbl_cell_begin = ".T*cell*begin"; $tbl_cell_end = ".T*cell*end"; $tbl_row_line = ".T*row*line"; $tbl_cell_line = ".T*cell*line"; $tbl_empty_cell = ".T*empty*cell"; $tbl_spanned_cell = ".T*spanned*cell"; # Read and process input while (<>) { #warn "state: $state\n"; chomp; if ($state == $seek_table) { if (!/^\.\s*TS\s*(H)?\s*(\\".*)?$/) # look for .TS or .TS H { print "$_\n"; next; } ++$table_num; $section_num = 1; $expect_TH = ($1 eq "H"); $header_rows = 0; # number of data rows in header # set options, format to defaults $align = $align_left; $expand = "n"; $box = "n"; $all_box = "n"; $double_box = "n"; $tab = "\t"; $linesize = 1; $eqndelim = "\$\$"; @format = (); # format for columns @columnglobal = (); # column global values @rawdata = (); # cell data values @formatidx = (); # data row -> format row map $fmtidx = 0; $tblcols = 0; $state = $seek_options_or_format; next; } if (/^\.\s*TH\s*(\\".*)?$/) # allow .TH at any point after .TS { if ($expect_TH) { # number of header rows is the number of data # rows collected so far $header_rows = @rawdata; $expect_TH = 0; } else { Warn ("extraneous .TH?"); } next; } if (/^\.\s*T\&\s*(\\".*)?$/) # allow .T& at any point after .TS { Warn ("missing table data?") if !@rawdata; Warn ("missing .TH?") if $expect_TH; # begin a new section of the current table ++$section_num; # data rows in this section use format rows in this section # so make sure $fmtidx starts with next format line index $fmtidx = @format; $state = $seek_format; next; } if (/^\.\s*TE\s*(\\".*)?$/) # allow .TE at any point after .TS { Warn ("missing .TH?") if $expect_TH; DumpTable (); $state = $seek_table; next; } if (/^\./ && $state != $seek_table_content) { Warn ("suspect request?: $_"); } if ($state == $seek_options_or_format) { $state = $seek_format; if (/;\s*$/) # it's an options line { ParseOptionsLine (); next; } # current line is a format line, just fall through to next test } if ($state == $seek_format) { if (/\.\s*$/) # last format line { s/\.\s*$//; # strip dot $state = $seek_table_content; } # might have multiple format lines, separated by commas @line = split (",", $_); ParseFormatLine (shift (@line)) while @line; # if this was last format line in section (state just changed # to $seek_table_content), and this is the initial format # section, calculate those values which cannot be changed # in subsequent format sections (following .T&). CalculateFormatConstants () if $state == $seek_table_content && $section_num == 1; next; } if ($state == $seek_table_content) { ParseDataRow (); next; } die "$prog: logic error, unknown state\n"; } Die ("EOF while collecting table (missing .TE?)") if $state != $seek_table; exit (0); # ---------------------------------------------------------------------------- # Parse a table options line (first line after .TS) sub ParseOptionsLine { my ($key, $rest); my ($status, $opt); #warn "process options: $_\n"; s/;\s*$//; # strip semicolon at end while (/^[\s,]*(\w+)(.*)/) { $key = $1; # strip off keyword $_ = $2; if ($key eq "center") { $align = $align_center; next; } if ($key eq "expand") { $expand = "y"; next; } if ($key eq "box") { $box = "y"; next; } if ($key eq "allbox") { $all_box = $box = "y"; # allbox implies box next; } if ($key eq "doublebox") { $double_box = $box = "y"; # doublebox implies box next; } if ($key eq "tab") { ($status, $opt) = ExtractParenOption (); if ($status == 0) { Warn ("bad tab setting"); next; } $tab = $opt; next; } if ($key eq "linesize") { ($status, $opt) = ExtractParenOption (); if ($status == 0) { Warn ("bad linesize setting"); next; } $linesize = $opt; next; } if ($key eq "delim") { # parse the delimiters, though they're not actually used ($status, $opt) = ExtractParenOption (); if ($status == 0) { Warn ("bad delim setting"); next; } $eqndelim = $opt; next; } Warn ("unrecognized tbl option keyword: $key"); } Warn ("extra ignored on tbl option line: $_") unless /^\s*$/; # print values here if debugging } # Extract an option in parentheses, e.g., for "linesize(2)", "tab(:)". # Returns a two-element array. First element is the status (zero = failure, # non-zero = success), second element is the option if status is non-zero. sub ExtractParenOption { my ($value); return (0, "") unless /^\s*\(([^)]+)\)(.*)/; $value = $1; $_ = $2; return (1, $value); } # Parse a format line that gives the format for one row of table cells. # Push each cell structure onto the @row array, then push that array onto # the @format array. sub ParseFormatLine { my ($key, $coltype); my (@row) = (); # array to hold this row's column entries my ($col); # pointer to current column entry hash my ($border); my ($v); $_[0] =~ s/\s+/ /g; # convert runs of whitespace to single spaces @c = split (//, $_[0]); # split up line, one char per array element for (;;) { SkipWhiteSpace (); last if !@c; # allocate an "empty" column info structure, using defaults $col = NewColumnEntry (); # Look for | or || separator. If present, pull off and change # the left border value. Also change column type to # $col_borderonly just in case no "real" column type follows # (i.e., if the | or || is the last thing on the line). if ($c[0] eq "|") { shift (@c); $border = $bord_left_s; if ($c[0] eq "|") { shift (@c); $border = $bord_left_d; } $col->{TYPE} = $col_borderonly; } SkipWhiteSpace (); if (!@c) { push (@row, $col) if $col->{TYPE} == $col_borderonly; last; } $key = shift (@c); $coltype = ColType ($key); if ($coltype eq $col_unknown) { Warn ("unknown column key: $key"); return; } # reset column type in column struct $col->{TYPE} = $coltype; $col = ParseColumnOptions ($col); push (@row, $col); } # For each column entry that has a left border (single or double) # specified, turn on the right border of the previous column entry. # Then if the final entry is only a border, remove it (this happens # when a format line ends with | or ||). for $v (1 .. @row-1) { $border = ($row[$v]->{BORDER} & $bord_left); next unless $border; # no border specified if ($border == $bord_left_s) { $border = $bord_right_s; } elsif ($border == $bord_left_d) { $border = $bord_right_d; } else { Die ("border calculation logic error"); } $row[$v-1]->{BORDER} |= $border; } pop (@row) if @row && $row[$#row]->{TYPE} eq $col_borderonly; # If this format row is not from the initial format section, then # it's known how many columns should be in the row. Add "L" format # columns if the row is short or shed excess columns if the row is # too long. @row = SquareUpFormatRow (@row) if $section_num > 1; push (@format, [ @row ]); } # Peel off column options that follow the column key character. Quit when # end of line or another column key character is found. sub ParseColumnOptions { my ($col) = $_[0]; my ($key, $opt, $have_opts); $have_opts = 0; for (;;) { SkipWhiteSpace (); last if !@c; # exit loop if next char begins a new column spec last if ColType ($c[0]) ne $col_unknown; $have_opts = 1; $key = shift (@c); if (Digit ($key)) # number = column separation { $col->{SEP} = $key . ExtractInteger (); next; } if (uc ($key) eq "T") # vertically span from top { $col->{VADJUST} = "T"; next; } if (uc ($key) =~ /^[BI]$/) # bold or italic { $col->{FONT} = uc ($key); next; } if (uc ($key) eq "F") # font setting { if (!@c) { Warn ("missing font after $key"); next; } if (Digit ($c[0])) { $opt = ExtractInteger (); if ($opt eq "") { Warn ("missing font after $key"); next; } } else { # Not numeric; allow one or two alpha # characters. If a single character, must be # followed by space if there are other option # characters following the font letter; in this # case, eat the space as well. if ($c[0] !~ /^[A-Z]$/i) { Warn ("malformed font spec"); next; } $opt = shift (@c); $opt .= shift (@c) if @c && $c[0] =~ /^[A-Z]$/i; } $col->{FONT} = $opt; next; } if (uc ($key) eq "P") # point size change { $opt = ExtractSignedInteger (); Warn ("missing value after $key") if !$opt; $col->{PTSIZE} = $opt; next; } if (uc ($key) eq "V") # vertical space change { $opt = ExtractSignedInteger (); Warn ("missing value after $key") if !$opt; $col->{VSPACE} = $opt; next; } if (uc ($key) eq "W") # width specification { if (!@c || (!Digit($c[0]) && $c[0] ne "(")) { Warn ("missing width after $key"); next; } if (Digit ($c[0])) # for int, no ()'s { $opt = ExtractInteger (); } elsif ($c[0] eq "(") { shift (@c); $opt = ""; $opt .= shift (@c) while @c && $c[0] ne ")"; shift (@c) if $c[0] eq ")"; } $col->{WIDTH} = $opt; next; } if (uc ($key) eq "E") # equal-width columns { $col->{EQWIDTH} = "y"; next; } Warn ("unknown column option: $key"); } Warn ("options are irrelevant for column type $col->{TYPE}") if $have_opts && ($col->{TYPE} eq $col_hspan || $col->{TYPE} eq $col_line || $col->{TYPE} eq $col_dbl_line); return ($col); } # Test whether or not the argument is a single character representing a digit sub Digit { return ($_[0] =~ /^\d$/); } # Pull an integer from the character buffer and return it, or "" if no # integer is present. sub ExtractInteger { my ($num) = ""; $num .= shift (@c) while @c && Digit ($c[0]); return ($num); } # Like ExtractInteger(), but allows an option sign (+ or -) preceding # the integer. Returns "" if there is no number, regardless of whether # or not there is a sign character. sub ExtractSignedInteger { my ($sign, $num); $sign = ""; $sign = shift (@c) if @c && $c[0] =~ /^[-+]$/; $num = ExtractInteger (); return ($sign . $num) if $num; return (""); } sub SkipWhiteSpace { shift (@c) while $c[0] eq " "; } sub ColType { my ($c) = $_[0]; $c = uc ($c); return ($c) if $c =~ /^[_=^ACLNRS|]$/; return ($col_unknown); } sub NewColumnEntry { return ( { TYPE => $col_unknown, BORDER => 0, # 0 = no border SEP => "", # blank = use default FONT => 0, # 0 = use default PTSIZE => 0, # 0 = use default VSPACE => 0, # 0 = use default VADJUST => "C", # C = centered vertical adjustment WIDTH => "", # blank = use default EQWIDTH => "n" # n = not specified as equal-width } ); } # Make sure format row has $tblcols columns by adding "L" entries to short # rows or by shedding excess columns as necessary. Before this is called # $tblcols should already have been set to the number of column entries in # a row. sub SquareUpFormatRow { my ($cellinfo); # Widen short row as necessary while (@_ < $tblcols) { $cellinfo = NewColumnEntry (); $cellinfo->{TYPE} = $col_left; push (@_, $cellinfo); } # Strip excess columns as necessary if (@_ > $tblcols) { Warn ("excess format specifiers discarded"); pop (@_) while @_ > $tblcols; } return (@_); } # Based on the formats for the column entries seen thus far, calculate those # values that cannot be changed from now on, even if other format sections are # given by .T&. These values include: # - the number of columns # - column separations # - column widths # - the set of columns to be made equal width # # This is called after the initial set of format lines has been collected. sub CalculateFormatConstants { my ($sep, $width, $eqwidth); my ($colglobal, $cellinfo); my ($h, $v); return if $section_num > 1; # return if values are already frozen # compute maximum number of columns $tblcols = 0; for $v (0 .. @format-1) { $tblcols = @{$format[$v]} if $tblcols < @{$format[$v]}; } # Make sure each format line has $tblcols columns for $v (0 .. @format-1) { @{$format[$v]} = SquareUpFormatRow (@{$format[$v]}); } @columnglobal = (); for $h (0 .. $tblcols-1) { $sep = -1; $width = ""; $eqwidth = "n"; for $v (0 .. @format-1) { Die ("CalculateFormatConstants: logic error") unless defined $format[$v][$h]; $cellinfo = $format[$v][$h]; # width is overridden by last explicit width $width = $cellinfo->{WIDTH} if $cellinfo->{WIDTH}; # sep is largest requested separation $sep = $cellinfo->{SEP} if $cellinfo->{SEP} && $sep < $cellinfo->{SEP}; # eqwidth is set if any cell in column requests it $eqwidth = "y" if $cellinfo->{EQWIDTH} eq "y"; } $sep = 3 if $sep eq -1; # default 3 if no explicit value given $width = 0 if $width eq ""; $colglobal = { SEP => $sep, WIDTH => $width, EQWIDTH => $eqwidth }; push (@columnglobal, $colglobal); } } # Parse a row of table data. Things that need to be handled here: # - The line might be continued to the next with \ at the end # - The line might really be a troff command (the rule tbl uses is # that troff commands begin with . followed by anything but a number) # - Data fields may be multi-line if the last thing on the row is T{, # in which case the field continues until a line that begins with T}. # - The data values will be written out (in DumpTable()) on separate # output lines, so values that begin with a dot must be escaped with # \&. Have to be somewhat careful here because a multi-line value # (between T{ and T}) might begin with a troff command itself, and # thus shouldn't be escaped. (This means that if a line doesn't look # like a troff command, escape all fields that begin with a dot, # EXCEPT that multi-line fields are escaped only if they begin with # a dot followed by a number. Sheesh.) # - As it turns out, it's also useful to escape with \& any data field # that begins with whitespace, to suppress extraneous break that # that troffcvt would produce as a result of a line beginning with # whitespace. sub ParseDataRow { my (@d, @d2); # data values my ($data); # if line is continued (\ at the end), keep reading while (/\\$/ && !eof) { s/\\$//; # chop trailing backslash $_ .= <>; chomp; } # Line is a troff command if it begins with a period followed # by anything but a number. if (/^\.(\D|$)/) { push (@rawdata, $_); push (@formatidx, -2); # line isn't associated with format row return; } # Split up data line, then keep reading input lines as long # as the current data ends with "T{". @d = split ($tab, $_); # Prepend \& to any fields that begin with . followed by a number, # to prevent a field like ".13" from being interpreted as a troff # command by troffcvt. Also escape fields beginning with whitespace. foreach (@d) { s/^([.\s])/\\\&\1/; } while (@d && $d[$#d] eq "T{") { pop (@d); # drop the "T{" $data = ""; # read until T}, use to replace T{ while (<>) { chomp; # if line is continued (\ at the end), keep reading while (/\\$/ && !eof) { s/\\$//; $_ .= <>; chomp; } Die (".TE found while in T{...T}") if /^\.\s*TE\s*$/; if (!/^T}(\Q$tab\E|$)/) { $data .= "\n" if $data; $data .= $_; next; } # escape whitespace or dot followed by number $data =~ s/^(\.\d)/\\\&\1/; $data =~ s/^(\s)/\\\&\1/; push (@d, $data); @d2 = split ($tab, $_); shift (@d2); # shift off the "T}" # escape any fields after the T{...T} field that # begin with dot or whitespace foreach (@d2) { s/^([.\s])/\\\&\1/; } push (@d, @d2); last; } last if eof; } # Push data row onto data matrix array, remember the index into # the format array of the format row that applies to this data row, # then (if we haven't reach the end of the formats) bump the index. # If the data row is a line-drawing row, don't associate it with a # format row. push (@rawdata, [ @d ]); if (LineDrawingRow (@d)) { push (@formatidx, -1); } else { push (@formatidx, $fmtidx); ++$fmtidx unless $fmtidx == @format - 1; } } # Check whether or not a row of cells is a line-drawing row, defined here as: # - A row with one column that is either "_" or "=" ("\_" doesn't count) # - A row with at least $tblcols columns, where the first $tblcols columns # are line-drawing instructions ("_", "\_, or "="). (If there are more # than $tblcols columns, they're ignored.) sub LineDrawingRow { my ($celldata); return (0) if !@_; # completely blank line is not line-drawing return (1) if @_ == 1 && $_[0] =~ /^[_=]$/; return (0) if @_ > 1 && @_ < $tblcols; # incomplete line foreach $celldata (@_) { return (0) if !LineDrawingCell ($celldata); } return (1); } sub LineDrawingCell { my ($celldata) = $_[0]; return ($celldata eq "_" || $celldata eq "\\_" || $celldata eq "="); } # Dump out table data # The @type, @vspan, and @hspan arrays are used as matrices, with one # member for each data cell in the table. The value of each @type # element is the format type for the cell. The value of @vspan and # @hspan elements is the number of cells that the cell spans. If the # value is 1, the cell spans only itself (the usual case). For values > 1, # the cell spans down (for @vspan) or to the right (for @hspan) the # given number of cells (including itself). If the value is 0, it means # the cell is spanned by a cell from above (for @vspan) or to its left # (for @hspan). # A tricky part is that vertical spans can be indicated in the cell format # section (^ column type) or in the data section (\^ data value). This is # handled by having \^ data values override the column format values as # necessary. sub DumpTable { my (@type, @vspan, @hspan, $vs, $hs); my (@fmtrow, $fmttype); my (@datarow, @ndatarow, $celldata); my ($nrows, $ncols, $spanidx); my ($cellinfo, $celltype, $colglobal); my ($h, $v, $h2, $v2, $i); Die ("logic error, \@formatidx != \@rawdata") if @formatidx != @rawdata; $ncols = $tblcols; if ($ncols == 0) { Warn ("no table format given, table skipped"); return; } # Calculate the @type, @hspan, and @vspan arrows for doing span # calculations. The dimensions will be $nrows x $ncols. The # span values are initialized to "1" (this indicates the default # case where each cell spans only itself). The type values come # come from the format entries, possibly overridden by the data # values. # $nrows is the number of non-troff-command rows # $ncols is the number of columns in the table @type = (); @hspan = (); @vspan = (); $nrows = 0; for $v (0 .. @rawdata-1) # for each data row { $fmtidx = $formatidx[$v]; next if $fmtidx == -2; # row is a troff command ++$nrows; push (@hspan, [ split (//, "1" x $ncols) ]); push (@vspan, [ split (//, "1" x $ncols) ]); # Construct types for this row. If $fmtidx is -1, the row # is a line-drawing row, so set the type to "_" for each cell. # Otherwise use the assocated format row to determine the # types, but allow those to be overridden if data values are # "\^" or line-drawing types. # Types used in the @type array: # $col_vspan ^ columns # $col_hspan s columns # $col_line _ or = columns # $col_X any non-span, non-line column # Elements are set to $col_visited as they are visited # during span calculations. @datarow = @{$rawdata[$v]}; $fmtidx = $formatidx[$v]; # If a row is a line-drawing row and it consists of a # single data value (meaning it's a table-width row), # set up the type row as $col_line followed by $ncols-1 # spanning columns. This helps catch attempts by other # cells to span vertically through the line. if ($fmtidx == -1) # line-drawing row { if (@datarow == 1) # table-width line { push (@type, [ $col_line , split (//, $col_hspan x ($ncols-1)) ]); } else { push (@type, [ split (//, $col_line x $ncols) ]); } next; } # if $fmtidx still < 0, it's a troff command; shouldn't happen Die ("logic error, \$fmtidx = $fmtidx") if $fmtidx < 0; @fmtrow = (); @ndatarow = (); for $h (0 .. $ncols-1) { # Get the type. Map all line types to $col_line for # simplicity, and map all non-line, non-span types # to $col_X $fmttype = $format[$fmtidx][$h]->{TYPE}; if ($fmttype eq $col_vspan || $fmttype eq $col_hspan) { push (@fmtrow, $fmttype); next; } $fmttype = $col_line if $fmttype eq $col_dbl_line; $fmttype = $col_X if $fmttype ne $col_line; # If there's no more data in row, format determines type if (!@datarow) { push (@fmtrow, $fmttype); next; } # Look at cell data to see if it overrides format # (and delete it from data row if it's "\^") $celldata = shift (@datarow); if (LineDrawingCell ($celldata)) # line { # lines can only override line and "X" if ($fmttype ne $col_line && $fmttype ne $col_X) { Die ("bad data (row $v, col $h)"); } $fmttype = $col_line; push (@ndatarow, $celldata); } elsif ($celldata eq "\\^") # vertical span { # spans can only override "X" if ($fmttype ne $col_X) { Die ("bad data (row $v, col $h)"); } $fmttype = $col_vspan; } else { push (@ndatarow, $celldata); } push (@fmtrow, $fmttype); } Die ("\@fmtrow logic error") if @fmtrow != $ncols; push (@type, [ @fmtrow ]); # @ndatarow now contains all non-\^ data values; # use it to replace the original data row. @{$rawdata[$v]} = @ndatarow; } #print "cell type:\n"; #PrintArray (@type); if ($nrows == 0) { Warn ("no table data given, table skipped"); return; } # Preliminary check: can't span horizontally in first column or # vertically in first row. foreach $v (0 .. $nrows-1) { next if $type[$v][0] ne $col_hspan; Die ("cannot span horizontally in first column"); } foreach $h (0 .. $ncols-1) { next if $type[0][$h] ne $col_vspan; Die ("cannot span vertically in first row"); } # Visit each cell of the type matrix, determine its horizontal/vertical # span extents to determine the size of the block the cell should span, # then verify that all cells in that block are indeed spanned. This # also sets the @hspan and @vspan matrix entries to the correct span # count for later when the table data values get written out. # If a cell spans down, its vspan value is the number of rows it # spans, including itself. If a cell is spanned by a cell above, # its vspan value is zero. If a cell spans to the right, its hspan # value is the number of columns it spans, including itself. If a # cell is spanned by a cell to the left, its hspan value is zero. foreach $v (0 .. $nrows-1) { foreach $h (0 .. $ncols-1) { # Skip the cell if it has already been visited next if $type[$v][$h] eq $col_visited; # The upper left corner of a span block can't be a # spanning type. Die ("illegal span at row ", $v+1, ", column ", $h+1) if $type[$v][$h] eq $col_vspan || $type[$v][$h] eq $col_hspan; # Mark cell as visited $type[$v][$h] = $col_visited; # Determine how many cells left and down this cell # spans by looking at cells lying to right of and down # from it. Size is always at least 1 x 1. $vs = $hs = 1; foreach $v2 ($v+1 .. $nrows-1) { last unless $type[$v2][$h] eq $col_vspan; ++$vs; } foreach $h2 ($h+1 .. $ncols-1) { last unless $type[$v][$h2] eq $col_hspan; ++$hs; } # Examine the spanned block, examining for illegal spans # and marking all the cells in the block as visited. # Set the span counts as follows: # - Leave upper left corner as set above # - All cells directly below get same hspan as upper # left and vspan of 0 # - All cells directly to right get same vspan as upper # left and hspan of 0 # - All other cells in block get hspan, vspan of 0 # Examine rest of spanned block (don't need to look at # first row or column; have already looked at them). # All these cells must span up or left. foreach $v2 ($v .. $v + $vs-1) { foreach $h2 ($h .. $h + $hs-1) { # set the span counts $vspan[$v2][$h2] = ($v2 == $v ? $vs : 0); $hspan[$v2][$h2] = ($h2 == $h ? $hs : 0); # mark cell as visited $celltype = $type[$v2][$h2]; $type[$v2][$h2] = $col_visited; # type for all cells but the upper left # one must be a spanned type next if $v2 == $v && $h2 == $h; if ($celltype ne $col_vspan && $celltype ne $col_hspan) { Die ("illegal span at row ", $v2+1, ", column ", $h2+1) } } } } } #print "vspan:\n"; #PrintArray (@vspan); #print "hspan:\n"; #PrintArray (@hspan); # Now the table data can be written out. Finally! # Take care to guard against the fact that data rows can be # troff commands, short, or even blank. # Write the initial table request line. print "$tbl_begin $nrows $ncols $header_rows $align $expand"; print " $box $all_box $double_box"; print "\n"; # Write column globals foreach $h (0 .. $ncols-1) { $colglobal = $columnglobal[$h]; print "$tbl_col_info"; print " $colglobal->{WIDTH}"; print " $colglobal->{SEP}"; print " $colglobal->{EQWIDTH}"; print "\n"; } # Only non-troff command data rows have entries in the span arrays. # $spanidx keeps track of which span array rows to use for a given # data row. $spanidx = -1; # Write table data foreach $v (0 .. @rawdata-1) { $datidx = $dataidx[$v]; $fmtidx = $formatidx[$v]; # format row to use if ($fmtidx == -2) # troff command { print "$rawdata[$v]\n"; next; } @datarow = @{$rawdata[$v]}; ++$spanidx; if ($fmtidx == -1) # line-drawing row { WriteLineDrawingRow ($ncols, @datarow); next; } # line is not line-drawing, or is only partially so, or line # types in different columns are different print "$tbl_row_begin\n"; foreach $h (0 .. $ncols-1) { $vs = $vspan[$spanidx][$h]; $hs = $hspan[$spanidx][$h]; $cellinfo = $format[$fmtidx][$h]; Die ("DumpTable: logic error") if !$cellinfo; $celltype = $cellinfo->{TYPE}; print "$tbl_cell_info"; print " $celltype $vs $hs"; print " $cellinfo->{VADJUST}"; print " $cellinfo->{BORDER}"; print "\n"; } foreach $h (0 .. $ncols-1) { $vs = $vspan[$spanidx][$h]; $hs = $hspan[$spanidx][$h]; # Print a spanned-cell marker if the cell is spanned # from the left or from the top. Otherwise shift off # the cell's data value and proceed to write cell info. # (A cell is spanned if either span value is zero.) if ($hs == 0 || $vs == 0) { print "$tbl_spanned_cell\n"; next; } $celldata = shift (@datarow); $cellinfo = $format[$fmtidx][$h]; Die ("DumpTable: logic error") if !$cellinfo; $celltype = $cellinfo->{TYPE}; # does the format or data value require line drawing? if ($celltype eq $col_line || $celldata eq "_") { Warn ("non-empty data for _ format ignored") if $celldata && $celldata ne "_"; Warn ("line spans vertically") if $vs > 1; print "$tbl_cell_line 1\n"; next; } if ($celltype eq $col_dbl_line || $celldata eq "=") { Warn ("non-empty data for = format ignored") if $celldata && $celldata ne "="; Warn ("line spans vertically") if $vs > 1; print "$tbl_cell_line 2\n"; next; } if ($celldata eq "\\_") { print "$tbl_cell_line 0\n"; next; } # Not a line-drawing cell, just regular data. If # the cell is empty, print the shorthand request, # otherwise print the begin and end requests, with # the data in between. if ($celldata eq "") { print "$tbl_empty_cell\n"; next; } print "$tbl_cell_begin"; print " $cellinfo->{FONT}"; print " $cellinfo->{PTSIZE}"; print " $cellinfo->{VSPACE}"; print "\n"; print "$celldata\n"; print "$tbl_cell_end\n"; } print "$tbl_row_end\n"; # warn about any excess data ExcessData (@datarow) if @datarow; } # Finish table print "$tbl_end\n"; } # Write a line-drawing row. First argument is the number of columns in a # row, second argument is the data array. # If the line indicates a table-width single or double line, a .T*row*line # request will be written. A table-width line is indicated if: # - The data row consists of exactly one "_" or "=" value ("\_" doesn't count) # - The data row consists of enough values to fill an entire row and the # values are all "_" or all "=" # If neither condition holds, individual cell requests are written as # .T*cell*line requests between .T*row*begin and .T*row*end requests. sub WriteLineDrawingRow { my ($ncols, @datarow) = @_; my (@excess); my ($h, $celldata, $homogeneous); # look only at first $ncols values in row (there may be extraneous # values, but they don't enter into the calculations). @excess = (); if (@datarow > $ncols) { @excess = splice (@datarow, $ncols); } Die ("WriteLineDrawingRow: logic error") unless LineDrawingRow (@datarow); # determine whether the cell values are "_" or "=" and all the same, # and whether line consists of a single data value or exactly $ncols # values. (A line consisting of exactly one "_" or "=" is homogeneous. # But a line consisting of, e.g., two "_" values is not homogeneous # if the table is three columns wide, because there is an implied empty # (i.e., not line-drawing) third cell.) $homogeneous = 0; if ($datarow[0] =~ /^[_=]$/ && (@datarow == 1 || @datarow == $ncols)) { # First cell is "_" or "=", are all the rest the same? $homogeneous = 1; for $h (1 .. @datarow-1) { if ($datarow[$h] ne $datarow[0]) { $homogeneous = 0; last; } } } if ($homogeneous) # write a table-width line { print "$tbl_row_line "; if ($datarow[0] eq "_") { print "1"; } elsif ($datarow[0] eq "=") { print "2"; } else { Die ("WriteLineDrawingRow: logic error"); } print "\n"; } else # write individual cell-line requests { print "$tbl_row_begin\n"; for $h (0 .. $ncols-1) { $celldata = shift (@datarow); if ($celldata eq "") { print "$tbl_empty_cell\n"; } else { print "$tbl_cell_line "; if ($celldata eq "\\_") { print "0"; } elsif ($celldata eq "_") { print "1"; } elsif ($celldata eq "=") { print "2"; } else { Die ("logic error"); } print "\n"; } } print "$tbl_row_end\n"; } # warn about any excess data ExcessData (@excess) if @excess; } # Print warning for any discarded cell data. For multiline # data, trim extra lines and replace with "..." before printing. sub ExcessData { my ($celldata); while (@_) { ($celldata = shift (@_)) =~ s/\n.*/.../s; Warn ("excess data discarded: $celldata"); } } sub PrintArray { my ($nrows, $ncols); my ($v, $h); # determine number of rows and columns; assume each row has same # number of columns; $nrows = @_; $ncols = @_ ? @{$_[0]} : 0; for $v (0 .. $nrows-1) { for $h (0 .. $ncols-1) { print " ", $_[$v][$h]; } print "\n"; } } # Sum up the elements of an array sub SumArray { my ($nrows, $ncols); my ($v, $h); my ($sum); # determine number of rows and columns; assume each row has same # number of columns; $nrows = @_; $ncols = @_ ? @{$_[0]} : 0; $sum = 0; for $v (0 .. $nrows-1) { for $h (0 .. $ncols-1) { $sum += $_[$v][$h]; } } return ($sum); } sub Warn { warn "$prog:line $. (table $table_num, section $section_num): ", join ("", @_), "\n"; } sub Die { Warn (@_); die "$prog quits\n"; } pe, [ @fmtrow ]); # @ndatarow now contains all non-\^ data values; # use it to replace the original data row. @{$rawdata[$v]} = @ndatarow; } #print "cell type:\n"; #PrintArray (@type); if ($nrows == 0) { Warn ("no table data given, table skipped"); return; } # Preliminary check: can't span horizontally in first column or # vertically in first row. foreach $v (0 .. $nrows-1) { next if $type[$v][0] ne $col_hspan; Die ("cannot stroffcvt-1.04/tblcvt/in010066400017710000151000000002530631162602100166430ustar00junkyarddatamgmt00000400000027.TS center allbox linesize(2) tab (:) ; lB lB lB l s ^w(1i) . left:center:right _ _:_ left2:center2:right2 left3:T{ center3_1 center3_2 T}:T{ right3_1 right3_2 T} .TE troffcvt-1.04/tblcvt/tblcvt.pl~010066400017710000151000001053600633642164700203660ustar00junkyarddatamgmt00000400000027# To do: # - What if format says one type of line and data says another? # (In gtbl, the data takes precedence). # - Doesn't compute border values properly. Need function to set particular # border value, after clearing value for that border. # - box/allbox and doublebox aren't mutually exclusive. # - Error messages aren't great - they often are misleading wrt line number. # To do a better job of this, probably would need to do more data line # checking as soon as the line is parsed. # Script type: perl5 # tblcvt - troffcvt table preprocessor # Read troff input looking for tables (.TS + .TE and everything in between). # Parse table options and format lines, then read table data lines and write # them out in a more easily parsable form. # The output is intended to be used with troffcvt and a special set of # request redefinitions. The output cannot be parsed by troffcvt with # compatibility mode enabled (i.e., you cannot specify the -C flag to # troffcvt). # Table specifications are collected using these variables (among others): # @format Each element of this array is itself an array holding the # column entries for a row of format specifiers. # @rawdata Each element of this array holds one line of table data # (after \ continuation collapsing). The array holds "real" # data, and data lines that are actually just troff commands # (beginning with a dot). The variable $datarows is set to # the number of data rows that are *not* troff commands. # @formatidx Array to map $rawdata[i] to the index of the format row to be # used when formatting the data row. Elements of this array # may have the following values: # >= 0 Index into @format # -1 The data row is a line-drawing row and doesn't need # a format row # -2 The data row is a troff command # 05 Feb 1997 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 05 Feb 97 V1.00 # - Created. use strict refs; ($prog = $0) =~ s|.*//||; # get script name for messages @c = (); # character buffer # state numbers and initial state $seek_table = 1; $seek_options_or_format = 2; $seek_format = 3; $seek_table_content = 4; $state = $seek_table; $table_num = 0; # table alignment types # # Note that since the values are strings, must compare using # "eq" rather than "==". $align_left = "L"; $align_center = "C"; # End per-table values # Per-column values # Column entry types. For the first set, it's important that the # values be the key letter that signifies the corresponding column type. # For the second set, the values must be something that isn't any other column # type specifier. $col_borderonly is a special fake type used for the case # that a format line ends in | or || but has no other specifier following # it. $col_empty is a special fake type used to indicate in the output that # a cell's data is empty. $col_X is used during span calculations (it means # any non-span, non-line-drawing format type). # # Note that since the values are strings, must compare using # "eq" rather than "==". $col_left = "L"; $col_right = "R"; $col_center = "C"; $col_numeric = "N"; $col_alpha = "A"; $col_hspan = "S"; $col_vspan = "^"; $col_line = "_"; $col_dbl_line = "="; $col_borderonly = "|"; $col_empty = "E"; $col_X = "X"; $col_visited = "0"; $col_unknown = "0"; # border specifiers (these are or'ed together as necessary) $bord_left_s = 1; # left border, single/double $bord_left_d = 2; $bord_right_s = 4; # right border, single/double $bord_right_d = 8; $bord_top_s = 16; # top border, single/double $bord_top_d = 32; $bord_bottom_s = 64; # bottom border, single/double $bord_bottom_d = 128; # masks to pull out parts of border $bord_left = ($bord_left_s | $bord_left_d); $bord_right = ($bord_right_s | $bord_right_d); $bord_top = ($bord_top_s | $bord_top_d); $bord_bottom = ($bord_bottom_s | $bord_bottom_d); # End per-column values # Output request names $tbl_begin = ".T*table*begin"; $tbl_end = ".T*table*end"; $tbl_col_info = ".T*column*info"; $tbl_row_begin = ".T*row*begin"; $tbl_row_end = ".T*row*end"; $tbl_cell_info = ".T*cell*info"; $tbl_cell_begin = ".T*cell*begin"; $tbl_cell_end = ".T*cell*end"; $tbl_row_line = ".T*row*line"; $tbl_cell_line = ".T*cell*line"; $tbl_empty_cell = ".T*empty*cell"; $tbl_spanned_cell = ".T*spanned*cell"; # Read and process input while (<>) { #warn "state: $state\n"; chomp; if ($state == $seek_table) { if (!/^\.\s*TS\s*(H)?\s*(\\".*)?$/) # look for .TS or .TS H { print "$_\n"; next; } ++$table_num; $section_num = 1; $expect_TH = ($1 eq "H"); $header_rows = 0; # number of data rows in header # set options, format to defaults $align = $align_left; $expand = "n"; $box = "n"; $all_box = "n"; $double_box = "n"; $tab = "\t"; $linesize = 1; $eqndelim = "\$\$"; @format = (); # format for columns @columnglobal = (); # column global values @rawdata = (); # cell data values @formatidx = (); # data row -> format row map $fmtidx = 0; $tblcols = 0; $state = $seek_options_or_format; next; } if (/^\.\s*TH\s*(\\".*)?$/) # allow .TH at any point after .TS { if ($expect_TH) { # number of header rows is the number of data # rows collected so far $header_rows = @rawdata; $expect_TH = 0; } else { Warn ("extraneous .TH?"); } next; } if (/^\.\s*T\&\s*(\\".*)?$/) # allow .T& at any point after .TS { Warn ("missing table data?") if !@rawdata; Warn ("missing .TH?") if $expect_TH; # begin a new section of the current table ++$section_num; # data rows in this section use format rows in this section # so make sure $fmtidx starts with next format line index $fmtidx = @format; $state = $seek_format; next; } if (/^\.\s*TE\s*(\\".*)?$/) # allow .TE at any point after .TS { Warn ("missing .TH?") if $expect_TH; DumpTable (); $state = $seek_table; next; } if (/^\./ && $state != $seek_table_content) { Warn ("suspect request?: $_"); } if ($state == $seek_options_or_format) { $state = $seek_format; if (/;\s*$/) # it's an options line { ParseOptionsLine (); next; } # current line is a format line, just fall through to next test } if ($state == $seek_format) { if (/\.\s*$/) # last format line { s/\.\s*$//; # strip dot $state = $seek_table_content; } # might have multiple format lines, separated by commas @line = split (",", $_); ParseFormatLine (shift (@line)) while @line; # if this was last format line in section (state just changed # to $seek_table_content), and this is the initial format # section, calculate those values which cannot be changed # in subsequent format sections (following .T&). CalculateFormatConstants () if $state == $seek_table_content && $section_num == 1; next; } if ($state == $seek_table_content) { ParseDataRow (); next; } die "$prog: logic error, unknown state\n"; } Die ("EOF while collecting table (missing .TE?)") if $state != $seek_table; exit (0); # ---------------------------------------------------------------------------- # Parse a table options line (first line after .TS) sub ParseOptionsLine { my ($key, $rest); my ($status, $opt); #warn "process options: $_\n"; s/;\s*$//; # strip semicolon at end while (/^[\s,]*(\w+)(.*)/) { $key = $1; # strip off keyword $_ = $2; if ($key eq "center") { $align = $align_center; next; } if ($key eq "expand") { $expand = "y"; next; } if ($key eq "box") { $box = "y"; next; } if ($key eq "allbox") { $all_box = $box = "y"; # allbox implies box next; } if ($key eq "doublebox") { $double_box = $box = "y"; # doublebox implies box next; } if ($key eq "tab") { ($status, $opt) = ExtractParenOption (); if ($status == 0) { Warn ("bad tab setting"); next; } $tab = $opt; next; } if ($key eq "linesize") { ($status, $opt) = ExtractParenOption (); if ($status == 0) { Warn ("bad linesize setting"); next; } $linesize = $opt; next; } if ($key eq "delim") { # parse the delimiters, though they're not actually used ($status, $opt) = ExtractParenOption (); if ($status == 0) { Warn ("bad delim setting"); next; } $eqndelim = $opt; next; } Warn ("unrecognized tbl option keyword: $key"); } Warn ("extra ignored on tbl option line: $_") unless /^\s*$/; # print values here if debugging } # Extract an option in parentheses, e.g., for "linesize(2)", "tab(:)". # Returns a two-element array. First element is the status (zero = failure, # non-zero = success), second element is the option if status is non-zero. sub ExtractParenOption { my ($value); return (0, "") unless /^\s*\(([^)]+)\)(.*)/; $value = $1; $_ = $2; return (1, $value); } # Parse a format line that gives the format for one row of table cells. # Push each cell structure onto the @row array, then push that array onto # the @format array. sub ParseFormatLine { my ($key, $coltype); my (@row) = (); # array to hold this row's column entries my ($col); # pointer to current column entry hash my ($border); my ($v); $_[0] =~ s/\s+/ /g; # convert runs of whitespace to single spaces @c = split (//, $_[0]); # split up line, one char per array element for (;;) { SkipWhiteSpace (); last if !@c; # allocate an "empty" column info structure, using defaults $col = NewColumnEntry (); # Look for | or || separator. If present, pull off and change # the left border value. Also change column type to # $col_borderonly just in case no "real" column type follows # (i.e., if the | or || is the last thing on the line). if ($c[0] eq "|") { shift (@c); $border = $bord_left_s; if ($c[0] eq "|") { shift (@c); $border = $bord_left_d; } $col->{TYPE} = $col_borderonly; } SkipWhiteSpace (); if (!@c) { push (@row, $col) if $col->{TYPE} == $col_borderonly; last; } $key = shift (@c); $coltype = ColType ($key); if ($coltype eq $col_unknown) { Warn ("unknown column key: $key"); return; } # reset column type in column struct $col->{TYPE} = $coltype; $col = ParseColumnOptions ($col); push (@row, $col); } # For each column entry that has a left border (single or double) # specified, turn on the right border of the previous column entry. # Then if the final entry is only a border, remove it (this happens # when a format line ends with | or ||). for $v (1 .. @row-1) { $border = ($row[$v]->{BORDER} & $bord_left); next unless $border; # no border specified if ($border == $bord_left_s) { $border = $bord_right_s; } elsif ($border == $bord_left_d) { $border = $bord_right_d; } else { Die ("border calculation logic error"); } $row[$v-1]->{BORDER} |= $border; } pop (@row) if @row && $row[$#row]->{TYPE} eq $col_borderonly; # If this format row is not from the initial format section, then # it's known how many columns should be in the row. Add "L" format # columns if the row is short or shed excess columns if the row is # too long. @row = SquareUpFormatRow (@row) if $section_num > 1; push (@format, [ @row ]); } # Peel off column options that follow the column key character. Quit when # end of line or another column key character is found. sub ParseColumnOptions { my ($col) = $_[0]; my ($key, $opt, $have_opts); $have_opts = 0; for (;;) { SkipWhiteSpace (); last if !@c; # exit loop if next char begins a new column spec last if ColType ($c[0]) ne $col_unknown; $have_opts = 1; $key = shift (@c); if (Digit ($key)) # number = column separation { $col->{SEP} = $key . ExtractInteger (); next; } if (uc ($key) eq "T") # vertically span from top { $col->{VSPANTOP} = "y"; next; } if (uc ($key) =~ /^[BI]$/) # bold or italic { $col->{FONT} = uc ($key); next; } if (uc ($key) eq "F") # font setting { if (!@c) { Warn ("missing font after $key"); next; } if (Digit ($c[0])) { $opt = ExtractInteger (); if ($opt eq "") { Warn ("missing font after $key"); next; } } else { # Not numeric; allow one or two alpha # characters. If a single character, must be # followed by space if there are other option # characters following the font letter; in this # case, eat the space as well. if ($c[0] !~ /^[A-Z]$/i) { Warn ("malformed font spec"); next; } $opt = shift (@c); $opt .= shift (@c) if @c && $c[0] =~ /^[A-Z]$/i; } $col->{FONT} = $opt; next; } if (uc ($key) eq "P") # point size change { $opt = ExtractSignedInteger (); Warn ("missing value after $key") if !$opt; $col->{PTSIZE} = $opt; next; } if (uc ($key) eq "V") # vertical space change { $opt = ExtractSignedInteger (); Warn ("missing value after $key") if !$opt; $col->{VSPACE} = $opt; next; } if (uc ($key) eq "W") # width specification { if (!@c || (!Digit($c[0]) && $c[0] ne "(")) { Warn ("missing width after $key"); next; } if (Digit ($c[0])) # for int, no ()'s { $opt = ExtractInteger (); } elsif ($c[0] eq "(") { shift (@c); $opt = ""; $opt .= shift (@c) while @c && $c[0] ne ")"; shift (@c) if $c[0] eq ")"; } $col->{WIDTH} = $opt; next; } if (uc ($key) eq "E") # equal-width columns { $col->{EQWIDTH} = "y"; next; } Warn ("unknown column option: $key"); } Warn ("options are irrelevant for column type $col->{TYPE}") if $have_opts && ($col->{TYPE} eq $col_hspan || $col->{TYPE} eq $col_line || $col->{TYPE} eq $col_dbl_line); return ($col); } # Test whether or not the argument is a single character representing a digit sub Digit { return ($_[0] =~ /^\d$/); } # Pull an integer from the character buffer and return it, or "" if no # integer is present. sub ExtractInteger { my ($num) = ""; $num .= shift (@c) while @c && Digit ($c[0]); return ($num); } # Like ExtractInteger(), but allows an option sign (+ or -) preceding # the integer. Returns "" if there is no number, regardless of whether # or not there is a sign character. sub ExtractSignedInteger { my ($sign, $num); $sign = ""; $sign = shift (@c) if @c && $c[0] =~ /^[-+]$/; $num = ExtractInteger (); return ($sign . $num) if $num; return (""); } sub SkipWhiteSpace { shift (@c) while $c[0] eq " "; } sub ColType { my ($c) = $_[0]; $c = uc ($c); return ($c) if $c =~ /^[_=^ACLNRS|]$/; return ($col_unknown); } sub NewColumnEntry { return ( { TYPE => $col_unknown, BORDER => 0, # 0 = no border SEP => "", # blank = use default FONT => 0, # 0 = use default PTSIZE => 0, # 0 = use default VSPACE => 0, # 0 = use default VSPANTOP => "n", # n = not spanned from top WIDTH => "", # blank = use default EQWIDTH => "n" # n = not specified as equal-width } ); } # Make sure format row has $tblcols columns by adding "L" entries to short # rows or by shedding excess columns as necessary. Before this is called # $tblcols should already have been set to the number of column entries in # a row. sub SquareUpFormatRow { my ($cellinfo); # Widen short row as necessary while (@_ < $tblcols) { $cellinfo = NewColumnEntry (); $cellinfo->{TYPE} = $col_left; push (@_, $cellinfo); } # Strip excess columns as necessary if (@_ > $tblcols) { Warn ("excess format specifiers discarded"); pop (@_) while @_ > $tblcols; } return (@_); } # Based on the formats for the column entries seen thus far, calculate those # values that cannot be changed from now on, even if other format sections are # given by .T&. These values include: # - the number of columns # - column separations # - column widths # - the set of columns to be made equal width # # This is called after the initial set of format lines has been collected. sub CalculateFormatConstants { my ($sep, $width, $eqwidth); my ($colglobal, $cellinfo); my ($h, $v); return if $section_num > 1; # return if values are already frozen # compute maximum number of columns $tblcols = 0; for $v (0 .. @format-1) { $tblcols = @{$format[$v]} if $tblcols < @{$format[$v]}; } # Make sure each format line has $tblcols columns for $v (0 .. @format-1) { @{$format[$v]} = SquareUpFormatRow (@{$format[$v]}); } @columnglobal = (); for $h (0 .. $tblcols-1) { $sep = -1; $width = ""; $eqwidth = "n"; for $v (0 .. @format-1) { Die ("CalculateFormatConstants: logic error") unless defined $format[$v][$h]; $cellinfo = $format[$v][$h]; # width is overridden by last explicit width $width = $cellinfo->{WIDTH} if $cellinfo->{WIDTH}; # sep is largest requested separation $sep = $cellinfo->{SEP} if $cellinfo->{SEP} && $sep < $cellinfo->{SEP}; # eqwidth is set if any cell in column requests it $eqwidth = "y" if $cellinfo->{EQWIDTH} eq "y"; } $sep = 3 if $sep eq -1; # default 3 if no explicit value given $width = 0 if $width eq ""; $colglobal = { SEP => $sep, WIDTH => $width, EQWIDTH => $eqwidth }; push (@columnglobal, $colglobal); } } # Parse a row of table data. Things that need to be handled here: # - The line might be continued to the next with \ at the end # - The line might really be a troff command (the rule tbl uses is # that troff commands begin with . followed by anything but a number) # - Data fields may be multi-line if the last thing on the row is T{, # in which case the field continues until a line that begins with T}. # - The data values will be written out (in DumpTable()) on separate # output lines, so values that begin with a dot must be escaped with # \&. Have to be somewhat careful here because a multi-line value # (between T{ and T}) might begin with a troff command itself, and # thus shouldn't be escaped. (This means that if a line doesn't look # like a troff command, escape all fields that begin with a dot, # EXCEPT that multi-line fields are escaped only if they begin with # a dot followed by a number. Sheesh.) # - As it turns out, it's also useful to escape with \& any data field # that begins with whitespace, to suppress extraneous break that # that troffcvt would produce as a result of a line beginning with # whitespace. sub ParseDataRow { my (@d, @d2); # data values my ($data); # if line is continued (\ at the end), keep reading while (/\\$/ && !eof) { s/\\$//; # chop trailing backslash $_ .= <>; chomp; } # Line is a troff command if it begins with a period followed # by anything but a number. if (/^\.(\D|$)/) { push (@rawdata, $_); push (@formatidx, -2); # line isn't associated with format row return; } # Split up data line, then keep reading input lines as long # as the current data ends with "T{". @d = split ($tab, $_); # Prepend \& to any fields that begin with . followed by a number, # to prevent a field like ".13" from being interpreted as a troff # command by troffcvt. Also escape fields beginning with whitespace. foreach (@d) { s/^([.\s])/\\\&\1/; } while (@d && $d[$#d] eq "T{") { pop (@d); # drop the "T{" $data = ""; # read until T}, use to replace T{ while (<>) { chomp; # if line is continued (\ at the end), keep reading while (/\\$/ && !eof) { s/\\$//; $_ .= <>; chomp; } Die (".TE found while in T{...T}") if /^\.\s*TE\s*$/; if (!/^T}(\Q$tab\E|$)/) { $data .= "\n" if $data; $data .= $_; next; } # escape whitespace or dot followed by number $data =~ s/^(\.\d)/\\\&\1/; $data =~ s/^(\s)/\\\&\1/; push (@d, $data); @d2 = split ($tab, $_); shift (@d2); # shift off the "T}" # escape any fields after the T{...T} field that # begin with dot or whitespace foreach (@d2) { s/^([.\s])/\\\&\1/; } push (@d, @d2); last; } last if eof; } # Push data row onto data matrix array, remember the index into # the format array of the format row that applies to this data row, # then (if we haven't reach the end of the formats) bump the index. # If the data row is a line-drawing row, don't associate it with a # format row. push (@rawdata, [ @d ]); if (LineDrawingRow (@d)) { push (@formatidx, -1); } else { push (@formatidx, $fmtidx); ++$fmtidx unless $fmtidx == @format - 1; } } # Check whether or not a row of cells is a line-drawing row, defined here as: # - A row with one column that is either "_" or "=" ("\_" doesn't count) # - A row with at least $tblcols columns, where the first $tblcols columns # are line-drawing instructions ("_", "\_, or "="). (If there are more # than $tblcols columns, they're ignored.) sub LineDrawingRow { my ($celldata); return (0) if !@_; # completely blank line is not line-drawing return (1) if @_ == 1 && $_[0] =~ /^[_=]$/; return (0) if @_ > 1 && @_ < $tblcols; # incomplete line foreach $celldata (@_) { return (0) if !LineDrawingCell ($celldata); } return (1); } sub LineDrawingCell { my ($celldata) = $_[0]; return ($celldata eq "_" || $celldata eq "\\_" || $celldata eq "="); } # Dump out table data # The @type, @vspan, and @hspan arrays are used as matrices, with one # member for each data cell in the table. The value of each @type # element is the format type for the cell. The value of @vspan and # @hspan elements is the number of cells that the cell spans. If the # value is 1, the cell spans only itself (the usual case). For values > 1, # the cell spans down (for @vspan) or to the right (for @hspan) the # given number of cells (including itself). If the value is 0, it means # the cell is spanned by a cell from above (for @vspan) or to its left # (for @hspan). # A tricky part is that vertical spans can be indicated in the cell format # section (^ column type) or in the data section (\^ data value). This is # handled by having \^ data values override the column format values as # necessary. sub DumpTable { my (@type, @vspan, @hspan, $vs, $hs); my (@fmtrow, $fmttype); my (@datarow, @ndatarow, $celldata); my ($nrows, $ncols, $spanidx); my ($cellinfo, $celltype, $colglobal); my ($hsize, $vsize); my ($h, $v, $h2, $v2, $i); Die ("logic error, \@formatidx != \@rawdata") if @formatidx != @rawdata; $ncols = $tblcols; if ($ncols == 0) { Warn ("no table format given, table skipped"); return; } # Calculate the @type, @hspan, and @vspan arrows for doing span # calculations. The dimensions will be $nrows x $ncols. The # span values are initialized to "1" (this indicates the default # case where each cell spans only itself). The type values come # come from the format entries, possibly overridden by the data # values. # $nrows is the number of non-troff-command rows # $ncols is the number of columns in the table @type = (); @hspan = (); @vspan = (); $nrows = 0; for $v (0 .. @rawdata-1) # for each data row { $fmtidx = $formatidx[$v]; next if $fmtidx == -2; # row is a troff command ++$nrows; push (@hspan, [ split (//, "1" x $ncols) ]); push (@vspan, [ split (//, "1" x $ncols) ]); # Construct types for this row. If $fmtidx is -1, the row # is a line-drawing row, so set the type to "_" for each cell. # Otherwise use the assocated format row to determine the # types, but allow those to be overridden if data values are # "\^" or line-drawing types. # Types used in the @type array: # $col_vspan ^ columns # $col_hspan s columns # $col_line _ or = columns # $col_X any non-span, non-line column # Elements are set to $col_visited as they are visited # during span calculations. @datarow = @{$rawdata[$v]}; $fmtidx = $formatidx[$v]; # If a row is a line-drawing row and it consists of a # single data value (meaning it's a table-width row), # set up the type row as $col_line followed by $ncols-1 # spanning columns. This helps catch attempts by other # cells to span vertically through the line. if ($fmtidx == -1) # line-drawing row { if (@datarow == 1) # table-width line { push (@type, [ $col_line , split (//, $col_hspan x ($ncols-1)) ]); } else { push (@type, [ split (//, $col_line x $ncols) ]); } next; } # if $fmtidx still < 0, it's a troff command; shouldn't happen Die ("logic error, \$fmtidx = $fmtidx") if $fmtidx < 0; @fmtrow = (); @ndatarow = (); for $h (0 .. $ncols-1) { # Get the type. Map all line types to $col_line for # simplicity, and map all non-line, non-span types # to $col_X $fmttype = $format[$fmtidx][$h]->{TYPE}; if ($fmttype eq $col_vspan || $fmttype eq $col_hspan) { push (@fmtrow, $fmttype); next; } $fmttype = $col_line if $fmttype eq $col_dbl_line; $fmttype = $col_X if $fmttype ne $col_line; # If there's no more data in row, format determines type if (!@datarow) { push (@fmtrow, $fmttype); next; } # Look at cell data to see if it overrides format # (and delete it from data row if it's "\^") $celldata = shift (@datarow); if (LineDrawingCell ($celldata)) # line { # lines can only override line and "X" if ($fmttype ne $col_line && $fmttype ne $col_X) { Die ("bad data (row $v, col $h)"); } $fmttype = $col_line; push (@ndatarow, $celldata); } elsif ($celldata eq "\\^") # vertical span { # spans can only override "X" if ($fmttype ne $col_X) { Die ("bad data (row $v, col $h)"); } $fmttype = $col_vspan; } else { push (@ndatarow, $celldata); } push (@fmtrow, $fmttype); } Die ("\@fmtrow logic error") if @fmtrow != $ncols; push (@type, [ @fmtrow ]); # @ndata row now contains all non-\^ data values; # use it to replace the original data row. @{$rawdata[$v]} = @ndatarow; } #print "cell type:\n"; #PrintArray (@type); if ($nrows == 0) { Warn ("no table data given, table skipped"); return; } # Preliminary check: can't span horizontally in first column or # vertically in first row. foreach $v (0 .. $nrows-1) { next if $type[$v][0] ne $col_hspan; Die ("cannot span horizontally in first column"); } foreach $h (0 .. $ncols-1) { next if $type[0][$h] ne $col_vspan; Die ("cannot span vertically in first row"); } # Visit each cell of the type matrix, determine its horizontal/vertical # span extents to determine the size of the block the cell should span, # then verify that all cells in that block are indeed spanned. This # also sets the @hspan and @vspan matrix entries to the correct span # count for later when the table data values get written out. foreach $v (0 .. $nrows-1) { foreach $h (0 .. $ncols-1) { # Skip the cell if it has already been visited next if $type[$v][$h] eq $col_visited; # The upper left corner of a span block can't be a # spanning type. Die ("illegal span at row ", $v+1, ", column ", $h+1) if $type[$v][$h] eq $col_vspan || $type[$v][$h] eq $col_hspan; # Mark cell as visited $type[$v][$h] = $col_visited; # Determine how many cells left and down this cell # spans by looking at cells lying to right of and down # from it. foreach $v2 ($v+1 .. $nrows-1) { last unless $type[$v2][$h] eq $col_vspan; # Increment the spanning cell's count. # Zero the spanned cell's count. # Mark the cell as visited. ++$vspan[$v][$h]; $hspan[$v2][$h] = 0; $vspan[$v2][$h] = 0; $type[$v2][$h] = $col_visited; } foreach $h2 ($h+1 .. $ncols-1) { last unless $type[$v][$h2] eq $col_hspan; # Increment the spanning cell's count. # Zero the spanned cell's count. # Mark the cell as visited. ++$hspan[$v][$h]; $hspan[$v][$h2] = 0; $vspan[$v][$h2] = 0; $type[$v][$h2] = $col_visited; } # Size of spanned block $hsize = $hspan[$v][$h]; $vsize = $vspan[$v][$h]; # Examine rest of spanned block (don't need to look at # first row or column; have already looked at them). # All these cells must span up or left. foreach $v2 ($v+1 .. $v + $vsize-1) { foreach $h2 ($h+1 .. $h + $hsize-1) { if ($type[$v2][$h2] ne $col_vspan && $type[$v2][$h2] ne $col_hspan) { Die ("illegal span at row ", $v2+1, ", column ", $h2+1) } # Zero the spanned cells' span count $hspan[$v2][$h2] = 0; $vspan[$v2][$h2] = 0; # Mark cell as visited $type[$v2][$h2] = $col_visited; } } } } #print "hspan:\n"; #PrintArray (@hspan); #print "vspan:\n"; #PrintArray (@vspan); # Now the table data can be written out. Finally! # Take care to guard against the fact that data rows can be # troff commands, short, or even blank. # Write the initial table request line. print "$tbl_begin $nrows $ncols $header_rows $align $expand"; print " $box $all_box $double_box"; print "\n"; # Write column globals foreach $h (0 .. $ncols-1) { $colglobal = $columnglobal[$h]; print "$tbl_col_info ", $h+1; print " $colglobal->{SEP}"; print " $colglobal->{WIDTH}"; print " $colglobal->{EQWIDTH}"; print "\n"; } # Only non-troff command data rows have entries in the span arrays. # $spanidx keeps track of which span array rows to use for a given # data row. $spanidx = -1; # Write table data foreach $v (0 .. @rawdata-1) { $datidx = $dataidx[$v]; $fmtidx = $formatidx[$v]; # format row to use if ($fmtidx == -2) # troff command { print "$rawdata[$v]\n"; next; } @datarow = @{$rawdata[$v]}; ++$spanidx; if ($fmtidx == -1) # line-drawing row { WriteLineDrawingRow ($ncols, @datarow); next; } # line is not line-drawing, or is only partially so, or line # types in different columns are different print "$tbl_row_begin\n"; foreach $h (0 .. $ncols-1) { $vs = $vspan[$spanidx][$h]; $hs = $hspan[$spanidx][$h]; $cellinfo = $format[$fmtidx][$h]; Die ("DumpTable: logic error") if !$cellinfo; $celltype = $cellinfo->{TYPE}; print "$tbl_cell_info"; print " $celltype $vs $hs"; print " $cellinfo->{VSPANTOP}"; print " $cellinfo->{BORDER}"; print "\n"; } foreach $h (0 .. $ncols-1) { $vs = $vspan[$spanidx][$h]; $hs = $hspan[$spanidx][$h]; # Get the cell's data value. (Don't shift off a # value for a horizontally spanned cell, since none is # given in the table specification). $celldata = ($hs > 0 ? shift (@datarow) : ""); # print a spanned-cell marker if the cell is spanned # from the left or from the top if ($hs == 0 || $vs == 0) { print "$tbl_spanned_cell\n"; next; } $cellinfo = $format[$fmtidx][$h]; Die ("DumpTable: logic error") if !$cellinfo; $celltype = $cellinfo->{TYPE}; # does the format or data value require line drawing? if ($celltype eq $col_line || $celldata eq "_") { Warn ("non-empty data for _ format ignored") if $celldata && $celldata ne "_"; Warn ("line spans vertically") if $vs > 1; for $i (1 .. $hs) # HACK HACK HACK { print "$tbl_cell_line 1\n"; } next; } if ($celltype eq $col_dbl_line || $celldata eq "=") { Warn ("non-empty data for = format ignored") if $celldata && $celldata ne "="; Warn ("line spans vertically") if $vs > 1; for $i (1 .. $hs) # HACK HACK HACK { print "$tbl_cell_line 2\n"; } next; } if ($celldata eq "\\_") { print "$tbl_cell_line 0\n"; next; } # Not a line-drawing cell, just regular data. If # the cell is empty, print the shorthand request, # otherwise print the begin and end requests, with # the data in between. if ($celldata eq "") { print "$tbl_empty_cell\n"; next; } print "$tbl_cell_begin"; print " $cellinfo->{FONT}"; print " $cellinfo->{PTSIZE}"; print " $cellinfo->{VSPACE}"; print "\n"; print "$celldata\n" if $celldata; print "$tbl_cell_end\n"; } print "$tbl_row_end\n"; # Print warnings for any discarded cell data. For multiline # data, trim extra lines and replace with "..." before printing. ExcessData (@datarow) if @datarow; } # Finish table print "$tbl_end\n"; } # Write a line-drawing row. First argument is the number of columns in a # row, second argument is the data array. # If the line indicates a table-width single or double line, a .T*row*line # request will be written. A table-width line is indicated if: # - The data row consists of exactly one "_" or "=" value ("\_" doesn't count) # - The data row consists of enough values to fill an entire row and the # values are all "_" or all "=" # If neither condition holds, individual cell requests are written as # .T*cell*line requests between .T*row*begin and .T*row*end requests. sub WriteLineDrawingRow { my ($ncols, @datarow) = @_; my (@excess); my ($h, $celldata, $homogeneous); # look only at first $ncols values in row (there may be extraneous # values, but they don't enter into the calculations). @excess = (); if (@datarow > $ncols) { @excess = splice (@datarow, $ncols); } Die ("WriteLineDrawingRow: logic error") unless LineDrawingRow (@datarow); # determine whether the cell values are "_" or "=" and all the same, # and whether line consists of a single data value or exactly $ncols # values. (A line consisting of exactly one "_" or "=" is homogeneous. # But a line consisting of, e.g., two "_" values is not homogeneous # if the table is three columns wide, because thre is an implied empty # (i.e., not line-drawing) third cell.) $homogeneous = 0; if ($datarow[0] =~ /^[_=]$/ && (@datarow == 1 || @datarow == $ncols)) { # First cell is "_" or "=", are all the rest the same? $homogeneous = 1; for $h (1 .. @datarow-1) { if ($datarow[$h] ne $datarow[0]) { $homogeneous = 0; last; } } } if ($homogeneous) # write a table-width line { print "$tbl_row_line "; if ($datarow[0] eq "_") { print "1"; } elsif ($datarow[0] eq "=") { print "2"; } else { Die ("WriteLineDrawingRow: logic error"); } print "\n"; } else # write individual cell-line requests { print "$tbl_row_begin\n"; for $h (0 .. $ncols-1) { $celldata = shift (@datarow); if ($celldata eq "") { print "$tbl_empty_cell\n"; } else { print "$tbl_cell_line "; if ($celldata eq "\\_") { print "0"; } elsif ($celldata eq "_") { print "1"; } elsif ($celldata eq "=") { print "2"; } else { Die ("logic error"); } print "\n"; } } print "$tbl_row_end\n"; } # warn about any excess data ExcessData (@excess) if @excess; } sub ExcessData { my ($celldata); while (@_) { ($celldata = shift (@_)) =~ s/\n.*/.../s; Warn ("excess data discarded: $celldata"); } } sub PrintArray { my ($nrows, $ncols); my ($v, $h); # determine number of rows and columns; assume each row has same # number of columns; $nrows = @_; $ncols = @_ ? @{$_[0]} : 0; for $v (0 .. $nrows-1) { for $h (0 .. $ncols-1) { print " ", $_[$v][$h]; } print "\n"; } } # Sum up the elements of an array sub SumArray { my ($nrows, $ncols); my ($v, $h); my ($sum); # determine number of rows and columns; assume each row has same # number of columns; $nrows = @_; $ncols = @_ ? @{$_[0]} : 0; $sum = 0; for $v (0 .. $nrows-1) { for $h (0 .. $ncols-1) { $sum += $_[$v][$h]; } } return ($sum); } sub Warn { warn "$prog:line $. (table $table_num, section $section_num): ", join ("", @_), "\n"; } sub Die { Warn (@_); die "$prog quits\n"; } elsif ($celldata eq "\\^") # vertical span { # spans can only override "X" if ($fmttype ne $col_X) { Die ("bad data (row $v, col $h)"); } $fmttype = $col_vspan; } else { push (@ndatarow, $celldata); } push (@fmtrow, $fmttroffcvt-1.04/tblcvt/in2010066400017710000151000000000270630465507100167350ustar00junkyarddatamgmt00000400000027.TS box; .sp l l . .TE troffcvt-1.04/tblcvt/in3010066400017710000151000000002050630467722400167400ustar00junkyarddatamgmt00000400000027.TS allbox tab(:); l l l ^ l l ^ l l . left:center:right :center:right :center:right :center:right :center:right :center:right .TE troffcvt-1.04/tblcvt/odd010066400017710000151000000001110630534503300170000ustar00junkyarddatamgmt00000400000027.TS allbox tab(:); c s s s ^ s ^ ^ ^ ^ s s . x:x:x:x x:x:x:x x:x:x:x .TE troffcvt-1.04/tblcvt/bad1010066400017710000151000000001200630544342200170420ustar00junkyarddatamgmt00000400000027.\" one of the two smallest illegally-spanning format sections. .TS ^ . xxx .TE troffcvt-1.04/tblcvt/bad2010066400017710000151000000001200630544342600170470ustar00junkyarddatamgmt00000400000027.\" one of the two smallest illegally-spanning format sections. .TS s . xxx .TE troffcvt-1.04/tblcvt/bad3010066400017710000151000000001470630544337200170610ustar00junkyarddatamgmt00000400000027.\" one of the smallest possible illegally-spanning format sections. .TS l l ^ s . xxx xxx xxx xxx .TE troffcvt-1.04/tblcvt/bad4010066400017710000151000000001470630544341100170540ustar00junkyarddatamgmt00000400000027.\" one of the smallest possible illegally-spanning format sections. .TS l s l ^ . xxx xxx xxx xxx .TE troffcvt-1.04/tblcvt/bad5010066400017710000151000000001160630565521000170530ustar00junkyarddatamgmt00000400000027.\" table with empty format line (empty except for bar) .TS box; | . xxx .TE troffcvt-1.04/tblcvt/bad6010066400017710000151000000001130630614635200170540ustar00junkyarddatamgmt00000400000027.\" table with no format .TS . xxx .TE .\" table with no data .TS l . .TE troffcvt-1.04/tblcvt/bad7010066400017710000151000000000660630707455100170660ustar00junkyarddatamgmt00000400000027.TS allbox; l l l ^ ^ s . xxx xxx xxx xxx xxx xxx .TE troffcvt-1.04/tblcvt/in4010066400017710000151000000000450631141417200167300ustar00junkyarddatamgmt00000400000027.TS l l l . x x x \^ x x \^ _ \^ .TE troffcvt-1.04/tblcvt/tests/004077500017710000151000000000000634046030100174565ustar00junkyarddatamgmt00000400000027troffcvt-1.04/tblcvt/tests/tbl01010066400017710000151000000006520631110141100203130ustar00junkyarddatamgmt00000400000027.TS center, box; c s s s c s s s c |c |c |c c |c |c |c l |n |n |n. 1970 Federal Budget Transfers \s-2(in billions of dollars)\s0 = State Taxes Money Net \^ collected spent \^ _ New York 22.91 21.35 \-1.56 New Jersey 8.33 6.96 \-1.37 Connecticut 4.12 3.10 \-1.02 Maine 0.74 0.67 \-0.07 California 22.29 22.42 +0.13 New Mexico 0.70 1.49 +0.79 Georgia 3.30 4.28 +0.98 Mississippi 1.15 2.32 +1.17 Texas 9.33 11.13 +1.80 .TE troffcvt-1.04/tblcvt/tests/tbl02010066400017710000151000000002040631110142600203130ustar00junkyarddatamgmt00000400000027.TS center; l6 n. 13 13 4\*.2 4\&\*.2 26\*.4\*.12 26\*.4\&\*.12 abc abc abc\e& abc\& 43\e&3\*.22 43\&3\*.22 749\*.12 749\&\*.12 .TE troffcvt-1.04/tblcvt/tests/tbl03010066400017710000151000000001530631110143600203200ustar00junkyarddatamgmt00000400000027.TS c s s l n n. Overall title Item-a 34.22 9.1 Item-b 12.65 .02 Items: c,d,e 23 5.8 Total 69.87 14.92 .TE troffcvt-1.04/tblcvt/tests/tbl04010066400017710000151000000003000631110145000203070ustar00junkyarddatamgmt00000400000027.TS box; c c c l l l. Language Authors Runs on Fortran Many Almost anything PL/1 IBM 360/370 C BTL 11/45,H6000,370 BLISS Carnegie-Mellon PDP-10,11 IDS Honeywell H6000 Pascal Stanford 370 .TE troffcvt-1.04/tblcvt/tests/tbl05010066400017710000151000000002620631110146300203230ustar00junkyarddatamgmt00000400000027.TS allbox; c s s c c c n n n. AT&T Common Stock Year Price Dividend 1971 41-54 $2.60 2 41-54 2.70 3 46-55 2.87 4 40-53 3.24 5 45-52 3.40 6 51-59 .95* .TE * (first quarter only) troffcvt-1.04/tblcvt/tests/tbl06010066400017710000151000000005570631110147600203370ustar00junkyarddatamgmt00000400000027.TS box; c s s c | c | c l | l | n. Major New York Bridges = Bridge Designer Length _ Brooklyn J. A. Roebling 1595 Manhattan G. Lindenthal 1470 Williamsburg L. L. Buck 1600 _ Queensborough Palmer & 1182 Hornbostel _ 1380 Triborough O. H. Ammann _ 383 _ Bronx Whitestone O. H. Ammann 2300 Throgs Neck O. H. Ammann 1800 _ George Washington O. H. Ammann 3500 .TE troffcvt-1.04/tblcvt/tests/tbl07010066400017710000151000000001140631110151000203120ustar00junkyarddatamgmt00000400000027.TS c c np-2 | n |. Stack _ 1 46 _ 2 23 _ 3 15 _ 4 6.5 _ 5 2.1 _ .TE troffcvt-1.04/tblcvt/tests/tbl08010066400017710000151000000002140631110152100203160ustar00junkyarddatamgmt00000400000027.TS box; L L L L L _ L L | LB L L _ L L L. january february march april may june july Months august september october november december .TE troffcvt-1.04/tblcvt/tests/tbl09010066400017710000151000000004510631110153300203250ustar00junkyarddatamgmt00000400000027.TS box; cfB s s s. Composition of Foods _ .T& c |c s s c |c s s c |c |c |c. Food Percent by Weight \^ _ \^ Protein Fat Carbo- \^ \^ \^ hydrate _ .T& l |n |n |n. Apples .4 .5 13.0 Halibut 18.4 5.2 ... Lima beans 7.5 .8 22.0 Milk 3.3 4.0 5.0 Mushrooms 3.5 .4 6.0 Rye bread 9.0 .6 52.7 .TE troffcvt-1.04/tblcvt/tests/tbl10010066400017710000151000000006510631110154700203240ustar00junkyarddatamgmt00000400000027.TS allbox; cfI s s c cw(1i) cw(1i) lp9 lp9 lp9. New York Area Rocks Era Formation Age (years) Precambrian Reading Prong >1 billion Paleozoic Manhattan Prong 400 million Mesozoic T{ .na Newark Basin, incl. Stockton, Lockatong, and Brunswick formations; also Watchungs and Palisades. T} 200 million Cenozoic Coastal Plain T{ On Long Island 30,000 years; Cretaceous sediments redeposited by recent glaciation. .ad T} .TE troffcvt-1.04/tblcvt/tests/tbl11010066400017710000151000000006030631110156200203170ustar00junkyarddatamgmt00000400000027.TS box, tab(:); cb s s s s cp-2 s s s s c ||c |c |c |c c ||c |c |c |c r2 ||n2 |n2 |n2 |n. Readability of Text Line Width and Leading for 10-Point Type = Line:Set:1-Point:2-Point:4-Point Width:Solid:Leading:Leading:Leading _ 9 Pica:\-9.3:\-6.0:\-5.3:\-7.1 14 Pica:\-4.5:\-0.6:\-0.3:\-1.7 19 Pica:\-5.0:\-5.1: 0.0:\-2.0 31 Pica:\-3.7:\-3.8:\-2.4:\-3.6 43 Pica:\-9.1:\-9.0:\-5.9:\-8.8 .TE troffcvt-1.04/tblcvt/tests/tbl12010066400017710000151000000013300631110157500203220ustar00junkyarddatamgmt00000400000027.TS c s cip-2 s l n a n. Some London Transport Statistics (Year 1964) Railway route miles 244 Tube 66 Sub-surface 22 Surface 156 .sp .5 .T& l r a r. Passenger traffic \(mi railway Journeys 674 million Average length 4.55 miles Passenger miles 3,066 million .T& l r a r. Passenger traffic \(mi road Journeys 2,252 million Average length 2.26 miles Passenger miles 5,094 million .T& l n a n. .sp .5 Vehicles 12,521 Railway motor cars 2,905 Railway trailer cars 1,269 Total railway 4,174 Omnibuses 8,347 .T& l n a n. .sp .5 Staff 73,739 Administrative, etc. 5,582 Civil engineering 5,134 Electrical eng. 1,714 Mech. eng. \(mi railway 4,310 Mech. eng. \(mi road 9,152 Railway operations 8,930 Road operations 35,946 Other 2,971 .TE troffcvt-1.04/tblcvt/tests/tbl13010066400017710000151000000022130631110161200203140ustar00junkyarddatamgmt00000400000027.TS center box; c s s ci s s c c c lB l n. New Jersey Representatives (Democrats) .sp .5 Name Office address Phone .sp .5 James J. Florio 23 S. White Horse Pike, Somerdale 08083 609-627-8222 William J. Hughes 2920 Atlantic Ave., Atlantic City 08401 609-345-4844 James J. Howard 801 Bangs Ave., Asbury Park 07712 201-774-1600 Frank Thompson, Jr. 10 Rutgers Pl., Trenton 08618 609-599-1619 Andrew Maguire 115 W. Passaic St., Rochelle Park 07662 201-843-0240 Robert A. Roe U.S.P.O., 194 Ward St., Paterson 07510 201-523-5152 Henry Helstoski 666 Paterson Ave., East Rutherford 07073 201-939-9090 Peter W. Rodino, Jr. Suite 1435A, 970 Broad St., Newark 07102 201-645-3213 Joseph G. Minish 308 Main St., Orange 07050 201-645-6363 Helen S. Meyner 32 Bridge St., Lambertville 08530 609-397-1830 Dominick V. Daniels 895 Bergen Ave., Jersey City 07306 201-659-7700 Edward J. Patten Natl. Bank Bldg., Perth Amboy 08861 201-826-4610 .sp .5 .T& ci s s lB l n. (Republicans) .sp .5v Millicent Fenwick 41 N. Bridge St., Somerville 08876 201-722-8200 Edwin B. Forsythe 301 Mill St., Moorestown 08057 609-235-6622 Matthew J. Rinaldo 1961 Morris Ave., Union 07083 201-687-4235 .TE troffcvt-1.04/tblcvt/tests/tbl14010066400017710000151000000004260631110162200203220ustar00junkyarddatamgmt00000400000027.TS expand; c s s s c c c c l l n n. Bell Labs Locations Name Address Area Code Phone Holmdel Holmdel, N. J. 07733 201 949-3000 Murray Hill Murray Hill, N. J. 07974 201 582-6377 Whippany Whippany, N. J. 07981 201 386-3000 Indian Hill Naperville, Illinois 60540 312 690-2000 .TE troffcvt-1.04/tblcvt/tests/tbl15010066400017710000151000000033510631110164300203260ustar00junkyarddatamgmt00000400000027.TS box; cb s s s c | c | c s ltiw(1i) | ltw(2i) | lp8| lw(1.5i)p8. Some Interesting Places _ Name Description Practical Information _ T{ American Museum of Natural History T} T{ The collections fill 11.5 acres (Michelin) or 25 acres (MTA) of exhibition halls on four floors. There is a full-sized replica of a blue whale and the world's largest star sapphire (stolen in 1964). T} Hours 10-5, ex. Sun 11-5, Wed. to 9 \^ \^ Location T{ Central Park West & 79th St. T} \^ \^ Admission Donation: $1.00 asked \^ \^ Subway AA to 81st St. \^ \^ Telephone 212-873-4225 _ Bronx Zoo T{ About a mile long and .6 mile wide, this is the largest zoo in America. A lion eats 18 pounds of meat a day while a sea lion eats 15 pounds of fish. T} Hours T{ 10-4:30 winter, to 5:00 summer T} \^ \^ Location T{ 185th St. & Southern Blvd, the Bronx. T} \^ \^ Admission $1.00, but Tu,We,Th free \^ \^ Subway 2, 5 to East Tremont Ave. \^ \^ Telephone 212-933-1759 _ Brooklyn Museum T{ Five floors of galleries contain American and ancient art. There are American period rooms and architectural ornaments saved from wreckers, such as a classical figure from Pennsylvania Station. T} Hours Wed-Sat, 10-5, Sun 12-5 \^ \^ Location T{ Eastern Parkway & Washington Ave., Brooklyn. T} \^ \^ Admission Free \^ \^ Subway 2,3 to Eastern Parkway. \^ \^ Telephone 718-638-5000 _ T{ New-York Historical Society T} T{ All the original paintings for Audubon's .I Birds of America .R are here, as are exhibits of American decorative arts, New York history, Hudson River school paintings, carriages, and glass paperweights. T} Hours T{ Tues-Fri & Sun, 1-5; Sat 10-5 T} \^ \^ Location T{ Central Park West & 77th St. T} \^ \^ Admission Free \^ \^ Subway AA to 81st St. \^ \^ Telephone 212-873-3400 .TE troffcvt-1.04/tblcvt/tests/tbl16010066400017710000151000000017340631110166400203350ustar00junkyarddatamgmt00000400000027.TS center; cI cI cI aB lf1 nf1 . Command Meaning Section a A Alphabetic subcolumn 2 allbox Draw box around all items 1 b B Boldface item 2 box Draw box around table 1 c C Centered column 2 center Center table in page 1 doublebox Doubled box around table 1 e E Equal width columns 2 expand Make table full line width 1 f F Font change 2 i I Italic item 2 l L Left adjusted column 2 n N Numerical column 2 \fInnn\fR Column separation 2 p P Point size change 2 r R Right adjusted column 2 s S Spanned item 2 t T Vertical spanning at top 2 tab \fR(\fIx\|\fR) Change data separator character 1 $fat roman "T{" ~~ fat roman "T}"$ Text block 3 v V Vertical spacing change 2 w W Minimum width value 2 \&\s+4.\s0\fIxx\fR Included \fItroff\fR command 3 \(bv Vertical line 2 \(bv\|\(bv Double vertical line 2 \&\s+4\v'4p'^\v'-4p'\s0 Vertical span 2 \e\&\s+4\v'4p'^\v'-4p'\s0 Vertical span 3 \&= Double horizontal line 2,3 \&$fat "_"$ Horizontal line 2,3 \&$fat "\e\|_"$ Short horizontal line 3 .TE troffcvt-1.04/post/004077500017710000151000000000000634140161100160035ustar00junkyarddatamgmt00000400000027troffcvt-1.04/post/Imakefile010066400017710000151000000046260634070166200176310ustar00junkyarddatamgmt00000400000027XCOMM troffcvt postprocessor Makefile XCOMM make sure "all" is default target all:: XCOMM any special -D's or other flags for compiling DEFINES = XCOMM any special -I's for compiling INCLUDES = XCOMM libraries needed for linking LIBS = $(TCREADLIB) $(TCUNIXLIB) $(TCGENLIB) $(MEMMGRLIB) \ $(TSLIB) $(ETMLIB) $(PORTLIB) DEPLIBS = $(DEPTCREADLIB) $(DEPTCUNIXLIB) $(DEPTCGENLIB) $(DEPMEMMGRLIB) \ $(DEPTSLIB) $(DEPETMLIB) $(DEPPORTLIB) NULLSRCS = tc2null.c NULLOBJS = tc2null.o RTFSRCS = tc2rtf.c rtffont.c RTFOBJS = tc2rtf.o rtffont.o HTMLSRCS = tc2html.c HTMLOBJS = tc2html.o TEXTSRCS = tc2text.c TEXTOBJS = tc2text.o SRCS = $(NULLSRCS) $(RTFSRCS) $(HTMLSRCS) $(TEXTSRCS) OBJS = $(NULLOBJS) $(RTFOBJS) $(HTMLOBJS) $(TEXTOBJS) XCOMM general-purpose data files InstallDataFile(tcr-fonts,$(LIBDIR)) XCOMM troff2null stuff BuildProgram(tc2null,$(NULLSRCS),$(NULLOBJS),$(LIBS),$(DEPLIBS)) InstallProgram(tc2null,$(LOCALBINDIR)) /* ShScriptFromMsubTemplate(troff2null,troff2null.sh,NullArg) */ ScriptFromMsubTemplate($(PERLPATH),troff2null,troff2null.pl,NullArg) InstallScript(troff2null,$(LOCALBINDIR)) XCOMM troff2html stuff BuildProgram(tc2html,$(HTMLSRCS),$(HTMLOBJS),$(LIBS),$(DEPLIBS)) InstallProgram(tc2html,$(LOCALBINDIR)) ScriptFromMsubTemplate($(PERLPATH),tc2html-toc,tc2html-toc.pl,NullArg) InstallScript(tc2html-toc,$(LOCALBINDIR)) ScriptFromMsubTemplate($(PERLPATH),troff2html,troff2html.pl,NullArg) InstallScript(troff2html,$(LOCALBINDIR)) InstallDataFile(html-fonts,$(LIBDIR)) InstallDataFile(html-specials,$(LIBDIR)) XCOMM troff2rtf stuff BuildProgram(tc2rtf,$(RTFSRCS),$(RTFOBJS),$(LIBS),$(DEPLIBS)) InstallProgram(tc2rtf,$(LOCALBINDIR)) /* ShScriptFromMsubTemplate(troff2rtf,troff2rtf.sh,NullArg) */ ScriptFromMsubTemplate($(PERLPATH),troff2rtf,troff2rtf.pl,NullArg) InstallScript(troff2rtf,$(LOCALBINDIR)) InstallDataFile(rtf-fonts,$(LIBDIR)) InstallDataFile(rtf-spec-ansi,$(LIBDIR)) InstallDataFile(rtf-spec-mac,$(LIBDIR)) InstallDataFile(rtf-spec-pc,$(LIBDIR)) InstallDataFile(rtf-spec-pca,$(LIBDIR)) XCOMM unroff stuff BuildProgram(tc2text,$(TEXTSRCS),$(TEXTOBJS),$(LIBS),$(DEPLIBS)) InstallProgram(tc2text,$(LOCALBINDIR)) /* ShScriptFromMsubTemplate(unroff,unroff.sh,NullArg) */ ScriptFromMsubTemplate($(PERLPATH),unroff,unroff.pl,NullArg) InstallScript(unroff,$(LOCALBINDIR)) InstallDataFile(text-specials,$(LIBDIR)) InstallDataFile(text-8-specials,$(LIBDIR)) XCOMM other DependTarget() troffcvt-1.04/post/rtffont.c010066400017710000151000000053410633570302200176350ustar00junkyarddatamgmt00000400000027# include # ifndef STRING_H # define STRING_H # endif # include STRING_H # include "etm.h" # include "tokenscan.h" # include "memmgr.h" # include "tcgen.h" # include "tcread.h" # include "tc2rtf.h" /* * Read table for mapping typefaces onto names to use in \fonttbl */ int ReadFontInfo (filename) char *filename; { FILE *f; char buf[bufSiz]; TCRFont *fi; FTabInfo *ft; char *face, *ftabName, *p; int i; if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) return (0); while (TCRGetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') continue; TSScanInit (buf); if ((face = TSScan ()) == (char *) NULL) /* typeface */ continue; ftabName = (char *) NULL; /* names for each character set */ for (i = 0; i < maxCharSet; i++) { if ((p = TSScan ()) == (char *) NULL) break; if (i == charSet) ftabName = p; } if (ftabName == (char *) NULL) { ETMMsg ("can't find charset name for typeface <%s>", face); continue; } for (fi = tcrFontList; fi != (TCRFont *) NULL; fi = fi->nextTCRFont) { if (strcmp (fi->tcrTypeFace, face) == 0) break; } if (fi == (TCRFont *) NULL) { ETMMsg ("can't find info for typeface <%s>", face); continue; } ft = New (FTabInfo); ft->tcrInfo = fi; ft->rtfName = StrAlloc (ftabName); ft->nextFTabInfo = fTabList; fTabList = ft; } (void) fclose (f); return (1); } /* * Read special character list. Each line has the character name * and the RTF string to write out for a given RTF character set. * (Character sets being one of those things that makes RTF * "portability" suspect.) */ int ReadSpecials (filename) char *filename; { FILE *f; char buf[bufSiz]; SpChar *sp; char *name, *font, *value; if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) return (0); while (TCRGetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') continue; TSScanInit (buf); if ((name = TSScan ()) == (char *) NULL) /* char name */ continue; if ((font = index (name, '/')) != (char *) NULL) *font++ = '\0'; value = TSScan (); /* NULL if missing */ sp = New (SpChar); sp->spName = StrAlloc (name); if (font != (char *) NULL) sp->spFont = StrAlloc (font); else sp->spFont = (char *) NULL; /* * If value missing, make NULL; this will cause writer * to write "[[name]]" instead of dropping it. */ if (value == (char *) NULL) sp->spValue = (char *) NULL; else sp->spValue = StrAlloc (value); sp->spNext = spList; spList = sp; } (void) fclose (f); return (1); } SpChar * LookupSpecial (name) char *name; { SpChar *sp; for (sp = spList; sp != (SpChar *) NULL; sp = sp->spNext) { if (strcmp (name, sp->spName) == 0) break; } return (sp); /* NULL if not found */ } troffcvt-1.04/post/tc2null.c010066400017710000151000000261400634113622200175350ustar00junkyarddatamgmt00000400000027/* * tc2null - read output from troffcvt and do nothing with it. * * Actually, it's not quite true that nothing is done: unrecognized * tokens are flagged, so tc2null in a way serves as a diagnostic * program. * * The main use of this "translator" is to serve as a starting point * for building troffcvt postprocessors. * * The table-handling machinery doesn't actually generate any output, but * it does extract table information from the input stream and keep track * of the current position within the table. As such, this machinery * serves as an example for how other postprocessors might process tables. * Some modifications will likely be necessary, of course. See the exiting * postprocessors to get an idea of the kind of modifications that were * necessary for them. * * 20 Apr 92 Paul DuBois dubois@primate.wisc.edu * * 20 Apr 92 V1.00 * - Created. * 20 May 97 * - Added tblcvt support. */ # ifdef THINK_C # include # endif /* THINK_C */ # include # include # include "etm.h" # include "memmgr.h" # include "tcread.h" # include "tctbl.h" static void ReadFile (void); static void ControlLine (void); static void PlainText (void); static void SpecialText (void); static void CenterFillAdjust (void); static void TableBegin (short argc, char **argv); static void TableEnd (void); static void TableColumnInfo (short argc, char **argv); static void TableRowBegin (short argc, char **argv); static void TableRowEnd (void); static void TableRowLine (short argc, char **argv); static void TableCellInfo (short argc, char **argv); static void TableCellBegin (short argc, char **argv); static void TableCellEnd (void); static void TableEmptyCell (void); static void TableSpannedCell (void); static void TableCellLine (short argc, char **argv); static void CellHSpanInit (void); int echo = 0; /* * Per-table values */ static short tblCols = 0; /* number of columns in table */ static short tblRows = 0; /* number of rows in table */ static short centerTbl= 0; /* non-zero if table is centered */ /* * Per-column values */ static long colWidth[tblMaxCol]; /* column width */ static long colSep[tblMaxCol]; /* column separation */ static short colEqWidth[tblMaxCol]; /* column is equal-width? */ /* * Per-cell values. For the span stuff, the flag is set when in a span * (a set of > 1 cells that are merged together), the size is the number * of cells that the span comprises, and the idx is the index of the current * cell within the span (range is 0..size-1). */ static char cellType[tblMaxCol]; /* cell type */ static short cellVSpanFlag[tblMaxCol]; /* cell vspan flag */ static short cellVSpanSize[tblMaxCol]; /* cell vspan extent */ static short cellVSpanIdx[tblMaxCol]; /* cell vspan counter */ static short cellHSpan[tblMaxCol]; /* cell hspan extent */ static short cellHSpanFlag; /* cell hspan flag */ static short cellHSpanSize; /* cell hspan extent */ static short cellHSpanIdx; /* cell hspan counter */ static char cellVAdjust[tblMaxCol]; /* cell vertical adjust */ static short cellBorder[tblMaxCol]; /* cell borders */ /* * Counters for keeping track of position within table. * tblColIdx counts horizontally during processing of \table-column-info * lines, during \table-cell-info lines, and while processing each row of * table data. tblRowIdx counts rows of table data. */ static short tblColIdx = 0; static short tblRowIdx = 0; int main (int argc, char *argv[]) { ETMInit (NULL); # ifdef THINK_C argc = ccommand (&argv); # endif /* THINK_C */ --argc; ++argv; while (argc > 0 && argv[0][0] == '-') { if (strcmp (argv[0], "-E") == 0) echo = 1; else ETMPanic ("Unknown option: %s", argv[0]); --argc; ++argv; } TCRInit (); if (argc == 0) /* stdin */ ReadFile (); else while (argc > 0) { if (freopen (argv[0], "r", stdin) == (FILE *) NULL) ETMMsg ("Cannot open: %s", argv[0]); else ReadFile (); --argc; ++argv; } ETMEnd (); exit (0); /*NOTREACHED*/ } static void ReadFile (void) { int i; while (TCRGetToken () != tcrEOF) { if (echo) { printf ("class %d maj %d min %d <%s>\n", tcrClass, tcrMajor, tcrMinor, tcrArgv[0]); if (tcrClass == tcrControl || tcrClass == tcrSText) { for (i = 1; i < tcrArgc; i++) printf ("\t<%s>\n", tcrArgv[i]); } } switch (tcrClass) { case tcrControl: ControlLine (); break; case tcrText: PlainText (); break; case tcrSText: SpecialText (); break; default: ETMPanic ("ReadFile: unknown class %d", tcrClass); } } } static void ControlLine (void) { switch (tcrMajor) { default: ETMMsg ("ControlLine: bad control major code: %d <%s>", tcrMajor, tcrArgv[0]); break; case tcrCUnknown: ETMMsg ("ControlLine: unknown control token: <%s>", tcrArgv[0]); break; case tcrCFA: CenterFillAdjust (); break; case tcrComment: case tcrSetupBegin: case tcrSetupEnd: case tcrPass: case tcrInputLine: case tcrOther: case tcrResolution: case tcrBreak: case tcrFont: case tcrPointSize: case tcrSpacing: case tcrLineSpacing: case tcrOffset: case tcrIndent: case tcrTempIndent: case tcrLineLength: case tcrPageLength: case tcrPageNumber: case tcrTitleLength: case tcrTitleBegin: case tcrTitleEnd: case tcrSpace: case tcrUnderline: case tcrCUnderline: case tcrNoUnderline: case tcrULineFont: case tcrBracketBegin: case tcrBracketEnd: case tcrBreakSpread: case tcrExtraSpace: case tcrLine: case tcrMark: case tcrMotion: case tcrBeginOverstrike: case tcrOverstrikeEnd: case tcrBeginPage: case tcrZeroWidth: case tcrSpaceSize: case tcrConstantWidth: case tcrNoConstantWidth: case tcrNeed: case tcrEmbolden: case tcrSEmbolden: case tcrResetTabs: case tcrFirstTab: case tcrNextTab: case tcrHyphenate: case tcrDiversionBegin: case tcrDiversionAppend: case tcrDiversionEnd: case tcrTabChar: case tcrLeaderChar: break; case tcrTableBegin: TableBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrTableEnd: TableEnd (); break; case tcrColumnInfo: TableColumnInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowBegin: TableRowBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowEnd: TableRowEnd (); break; case tcrRowLine: TableRowLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellInfo: TableCellInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellBegin: TableCellBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellEnd: TableCellEnd (); break; case tcrCellLine: TableCellLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrEmptyCell: TableEmptyCell (); break; case tcrSpannedCell: TableSpannedCell (); break; } } static void PlainText (void) { if (tcrMajor != '\n' && tcrMajor != '\r') { /* do something with character */ } } /* * The switch below lists all the known builtin special characters. * Those that aren't builtin will have a major code of tcrSTUnknown; * this will include those characters listed in the actions file. * It may be just as easy to skip the switch and handle all special * characters uniformly, e.g., by looking up their name in a translation * table for an output sequence. */ static void SpecialText (void) { switch (tcrMajor) { default: printf ("bad special text major code: %d <%s>\n", tcrMajor, tcrArgv[0]); break; case tcrSTUnknown: /* handle non-builtin special characters here */ break; case tcrBackslash: case tcrAtSign: case tcrLSglQuote: case tcrRSglQuote: case tcrLDblQuote: case tcrRDblQuote: case tcrZeroSpace: case tcrTwelfthSpace: case tcrSixthSpace: case tcrDigitSpace: case tcrHardSpace: case tcrMinus: case tcrGraveAccent: case tcrAcuteAccent: case tcrBackspace: case tcrOptHyphen: case tcrTab: case tcrLeader: case tcrFieldBegin: case tcrFieldEnd: case tcrFieldPad: break; } } static void CenterFillAdjust (void) { switch (tcrMinor) { default: ETMMsg ("CenterFillAdjust: bad minor code %d <%s>", tcrMinor, tcrArgv[0]); break; case tcrCenter: case tcrNofill: case tcrAdjFull: case tcrAdjLeft: case tcrAdjRight: case tcrAdjCenter: break; } } /* * Table element routines */ static void TableBegin (short argc, char **argv) { if (argc != 8) ETMPanic ("TableBegin: wrong number of args: %hd", argc); tblCols = StrToShort (argv[tblColsArg]); tblRows = StrToShort (argv[tblRowsArg]); if (tblCols == 0) ETMPanic ("TableBegin: zero column table"); if (tblCols > tblMaxCol) ETMPanic ("TableBegin: too many table columns (%hd), max = %d", tblCols, tblMaxCol); /* determine whether or not to center the table */ centerTbl = argv[tblAlignArg][0] == 'C'? 1 : 0; tblColIdx = 0; tblRowIdx = 0; } static void TableEnd (void) { } static void TableColumnInfo (short argc, char **argv) { if (argc != 3) ETMPanic ("TableColumnInfo: wrong number of args: %hd", argc); if (tblColIdx >= tblMaxCol) ETMPanic ("TableColumnInfo: logic error"); /* * For separation and width, 0 means "none specified". */ colSep[tblColIdx] = StrToLong (argv[colSepArg]); colWidth[tblColIdx] = StrToLong (argv[colWidthArg]); colEqWidth[tblColIdx] = (argv[colEqWidthArg][0] == 'y' ? 1 : 0); ++tblColIdx; } /* * Begin a table row. */ static void TableRowBegin (short argc, char **argv) { /* * Reset tblColIdx for use by \table-cell-info controls */ tblColIdx = 0; } static void TableRowEnd (void) { ++tblRowIdx; /* done with row, bump counter */ } static void TableRowLine (short argc, char **argv) { ++tblRowIdx; /* done with row, bump counter */ } static void TableCellInfo (short argc, char **argv) { char buf[bufSiz]; short vspan; if (argc != 5) ETMPanic ("TableCellInfo: wrong number of args: %hd", argc); if (tblColIdx >= tblMaxCol) ETMPanic ("TableCellInfo: logic error"); cellType[tblColIdx] = argv[cellTypeArg][0]; vspan = StrToShort (argv[cellVSpanArg]); if (vspan == 1) /* not part of a vspan */ { cellVSpanFlag[tblColIdx] = 0; } else if (vspan > 1) /* part of a vspan -- first cell */ { cellVSpanFlag[tblColIdx] = 1; cellVSpanSize[tblColIdx] = vspan; cellVSpanIdx[tblColIdx] = 0; } else /* part of a vspan -- not first cell */ { ++cellVSpanIdx[tblColIdx]; } cellHSpan[tblColIdx] = StrToShort (argv[cellHSpanArg]); cellVAdjust[tblColIdx] = StrToShort (argv[cellVAdjustArg]); cellBorder[tblColIdx] = StrToShort (argv[cellBorderArg]); /* * Bump cell index. * Reset if we've reached the end, so it'll be correct for * \table-cell-begin, \table-empty-cell, \table-spanned-cell, * \table-cell-line. */ ++tblColIdx; if (tblColIdx >= tblCols) tblColIdx = 0; } static void TableCellBegin (short argc, char **argv) { CellHSpanInit (); } static void TableCellEnd (void) { ++tblColIdx; } static void TableEmptyCell (void) { CellHSpanInit (); ++tblColIdx; } static void TableSpannedCell (void) { CellHSpanInit (); ++tblColIdx; } static void TableCellLine (short argc, char **argv) { CellHSpanInit (); ++tblColIdx; } static void CellHSpanInit (void) { short hspan; hspan = cellHSpan[tblColIdx]; if (hspan == 1) /* not part of a hspan */ { cellHSpanFlag = 0; } else if (hspan > 1) /* part of a hspan -- first cell */ { cellHSpanFlag = 1; cellHSpanSize = hspan; cellHSpanIdx = 0; } else /* part of a hspan -- not first cell */ { ++cellHSpanIdx; } } troffcvt-1.04/post/tc2rtf.c010066400017710000151000000734700634137653700174050ustar00junkyarddatamgmt00000400000027/* * - Write } at end only if output is non-empty. * - Wrapper needs function to call during loop and termination value * to look for. * - Borders, esp. for spanned cells. * - Row-length lines break the table. Do something better. * - If can assume that merges can only be rectangular, can dispense with * horiz merge controls. */ /* * There needs to be a kludge option to turn off some stuff, like * WordPerfect's failure to understand \sl. (Some readers are dumb * and don't understand \lquote, \lsglquote, etc., so the hex * equivalents for the appropriate character set are written instead.) * * tc2rtf - read troffcvt output, convert to RTF * * Paragraph format values when \setup-end is seen are saved and * made the default style. During further processing, paragraph * format changes are made to an internally cached state. When it * comes time to write the first char of paragraph text, and differences * between the internal state and last written state are flushed out * to sync the internal and written states. * * (This implicitly means that para format changes WITHIN a paragraph * don't take effect until the next paragraph). * * 20 Apr 92 Paul DuBois dubois@primate.wisc.edu * * 29 Apr 92 V1.00. Created. */ #include #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "portlib.h" #include "etm.h" #include "memmgr.h" #include "tcgen.h" #include "tcunix.h" #include "tcread.h" #include "tctbl.h" #include "tc2rtf.h" #define twips 1440 #define Twips(n) ((long) (((double) (n) * twips) / (resolution))) /* * Minimum column width = 1 inch. * Setting it narrower (e.g., .5 inch) seemed to cause Word some problems. */ #define minColWidth 1440 static void WriterInit (void); static int BeginFile (void); static void ReadFile (void); static void ControlLine (void); static void Prolog (void); static void WriteParFmt (ParFmt *bpf, ParFmt *npf); static void SetFont (char *name); static void SetPointSize (long size); static void SetTempIndent (long val); static void SetMargins (long nOffset, long nIndent, long nLineLen); static void SetSpacing (long nSpacing, long nLineSpacing); static void PlainText (void); static void SpecialText (void); static void Para (void); static void DrawLine (long length, int direction); static void Motion (long motion, int direction); static void ResetTabs (void); static void SetTabStop (long pos, char type); static long StrToTwips (char *s); static long StrToHalfPoints (char *s); static void ControlOut (char *p); static void TextStrOut (char *p); static void TextChOut (int c); static void StrOut (char *p); static void ChOut (char c); /* int c? */ static int AllowOutput (int yesno); static void TableBegin (short argc, char **argv); static void TableEnd (void); static void TableColumnInfo (short argc, char **argv); static void TableRowBegin (short argc, char **argv); static void TableRowEnd (void); static void TableRowLine (short argc, char **argv); static void TableCellInfo (short argc, char **argv); static void TableCellBegin (short argc, char **argv); static void TableCellEnd (void); static void TableEmptyCell (void); static void TableSpannedCell (void); static void TableCellLine (short argc, char **argv); static void CellBegin (void); static void CellEnd (void); static int oAllow = 1; /* zero if output is throttled */ static int pCount = 0; /* text chars written to current paragraph */ static int lCount = 0; /* text chars written to current output line */ int charSet = macCharSet; /* default character set number */ char *charSetName = "mac"; /* default character set name */ FTabInfo *fTabList = (FTabInfo *) NULL; SpChar *spList = (SpChar *) NULL; /* * Four paragraph format states are maintained. * * rtfParFmt The standard RTF defaults. Reflects the para * state after \pard is done. Never modified. * intParFmt Internal para state. Para state changes are cached * between paras and flushed when the first text character * for a para needs to be written. * wrtParFmt Para state as last written to the output. * tblParFmt Used to save intParFmt during table processing. */ static ParFmt rtfParFmt = { (long) tcrAdjLeft, /* justification */ (long) 0, /* left indent */ (long) 0, /* right indent */ (long) 0, /* first indent */ (long) 0, /* space before paragraph */ (long) 0, /* space after paragraph */ (long) 1000, /* space between lines (automatic) */ (int) 0, /* number of tabstops */ { (long) 0 }, /* tabstop positions */ { (char) 'l' } /* tabstop types */ }; static ParFmt intParFmt; static ParFmt wrtParFmt; static ParFmt tblParFmt; /* Convenience pointers into state structures */ ParFmt *rpf = &rtfParFmt; ParFmt *ipf = &intParFmt; ParFmt *wpf = &wrtParFmt; ParFmt *tpf = &tblParFmt; int debug = 0; int echo = 0; /* * Set on a per-file basis */ static long resolution = 1440; /* troff values */ static long offset = 1 * twips; static long indent = 0; /*static long tempIndent = 0;*/ static long lineLen = 9360; /* 6.5 * twips */ static long spacing = 12 * 2; /* half-points */ static long lineSpacing = 1; static long spaceSize = 12; /* 12/36 em */ /* document format properties */ static long margl = 0; /* left/right margins fixed in Prolog() */ static long margr = 0; static long pageLen = 11 * twips; static long pageWid = 12240; /* 8.5 * twips */ /* character format properties */ /*static long fontNum = 1;*/ static long pointSize = 10 * 2; /* size is in half-points */ static TCRFont *curFInfo = (TCRFont *) NULL; static char curFont[30] = "R"; static long charUpDn = 0; /* super/subscript value, in half points */ /* * Per-table values */ static short tblCols = 0; /* number of columns in table */ static short tblRows = 0; /* number of rows in table */ static short centerTbl= 0; /* non-zero if table is centered */ /* * Per-column values * * The width and right-edge positions are maintained on a per-column * basis. There is only a single column separation value, even though tbl * allows column separation to be set on a per-column basis. That's * because RTF allows only a per-row value. The separation value for the * first column is used. */ static long colWidth[tblMaxCol]; /* column width */ static long colRtEdge[tblMaxCol]; /* column right edge */ static short colEqWidth[tblMaxCol]; /* column is equal-width? */ static long colSep; /* column separation */ /* * Per-cell values. For the span stuff, the flag is set when in a span * (a set of > 1 cells that are merged together), the size is the number * of cells that the span comprises, and the idx is the index of the current * cell within the span (range is 0..size-1). */ static char cellType[tblMaxCol]; /* cell type */ static short cellVSpanFlag[tblMaxCol]; /* cell vspan flag */ static short cellVSpanSize[tblMaxCol]; /* cell vspan extent */ static short cellVSpanIdx[tblMaxCol]; /* cell vspan counter */ static short cellHSpan[tblMaxCol]; /* cell hspan extent */ static short cellHSpanFlag; /* cell hspan flag */ static short cellHSpanSize; /* cell hspan extent */ static short cellHSpanIdx; /* cell hspan counter */ static char cellVAdjust[tblMaxCol]; /* cell vertical adjust */ static short cellBorder[tblMaxCol]; /* cell borders */ static short inTbl = 0; /* * Counters for keeping track of position within table. * tblColIdx counts horizontally during processing of \table-column-info * lines, during \table-cell-info lines, and while processing each row of * table data. tblRowIdx counts rows of table data. */ static short tblColIdx = 0; static short tblRowIdx = 0; int main (int argc, char *argv[]) { char buf[bufSiz]; int inc; ETMInit (NULL); UnixSetProgPath (argv[0]); TCRSetOpenLibFileProc (UnixOpenLibFile); --argc; ++argv; while (argc > 0 && argv[0][0] == '-') { inc = 1; if (strcmp (argv[0], "-D") == 0) debug = 0xffff; else if (strcmp (argv[0], "-E") == 0) echo = 1; else if (strcmp (argv[0], "-S") == 0) { if (argc < 2) ETMPanic ("Missing argument after -S"); inc = 2; if (strcmp (argv[1], "ansi") == 0) { charSetName = argv[1]; charSet = ansiCharSet; } else if (strcmp (argv[1], "mac") == 0) { charSetName = argv[1]; charSet = macCharSet; } else if (strcmp (argv[1], "pc") == 0) { charSetName = argv[1]; charSet = pcCharSet; } else if (strcmp (argv[1], "pca") == 0) { charSetName = argv[1]; charSet = pcaCharSet; } else ETMPanic ("Unknown character set: %s", argv[1]); } else ETMPanic ("Unknown option: %s", argv[0]); argc -= inc; argv += inc; } WriterInit (); if (argc == 0) /* stdin */ ReadFile (); else while (argc > 0) { if (freopen (argv[0], "r", stdin) == (FILE *) NULL) ETMMsg ("Cannot open: %s", argv[0]); else ReadFile (); --argc; ++argv; } StrOut ("}\n"); /* should only do if non-empty output! */ ETMEnd (); exit (0); /*NOTREACHED*/ } static void WriterInit (void) { if (!TCRReadFonts ("tcr-fonts")) ETMPanic ("cannot find tcr-fonts file"); if (!ReadFontInfo ("rtf-fonts")) ETMPanic ("cannot find rtf-fonts file"); } static int BeginFile (void) { char buf[bufSiz]; sprintf (buf, "rtf-spec-%s", charSetName); if (!ReadSpecials (buf)) ETMPanic ("cannot find %s file", buf); (void) AllowOutput (0); *wpf = *ipf = *rpf; /* sync all states to RTF defaults */ TCRInit (); return (1); } static void ReadFile (void) { int i; (void) BeginFile (); while (TCRGetToken () != tcrEOF) { if (echo) { ETMMsg ("class %d maj %d min %d <%s>", tcrClass, tcrMajor, tcrMinor, tcrArgv[0]); if (tcrClass == tcrControl || tcrClass == tcrSText) { for (i = 1; i < tcrArgc; i++) ETMMsg ("\t<%s>", tcrArgv[i]); } } switch (tcrClass) { case tcrControl: ControlLine (); break; case tcrText: PlainText (); break; case tcrSText: SpecialText (); break; default: ETMPanic ("ReadFile: unknown token %d <%s>", tcrClass, tcrArgv[0]); } } } static void ControlLine (void) { char *argv1 = tcrArgv[1]; char buf[bufSiz]; switch (tcrMajor) { default: ETMMsg ("ControlLine: bad control major code: %d <%s>", tcrMajor, tcrArgv[0]); break; case tcrCUnknown: ETMMsg ("ControlLine: unknown control token: <%s>", tcrArgv[0]); break; case tcrComment: break; case tcrSetupBegin: break; case tcrResolution: resolution = StrToLong (argv1); break; case tcrSetupEnd: (void) AllowOutput (1); Prolog (); break; case tcrPass: break; case tcrInputLine: break; case tcrOther: break; case tcrBreak: Para (); break; case tcrCFA: ipf->pJustify = tcrMinor; break; case tcrPageLength: break; case tcrPageNumber: break; case tcrFont: if (tcrArgc < 2) ETMMsg ("missing font on \\font line"); else SetFont (tcrArgv[1]); break; case tcrPointSize: SetPointSize (StrToHalfPoints (argv1)); break; case tcrSpacing: SetSpacing (StrToTwips (argv1), lineSpacing); break; case tcrLineSpacing: SetSpacing (spacing, StrToLong (argv1)); break; case tcrOffset: SetMargins (StrToTwips (argv1), indent, lineLen); break; case tcrIndent: SetMargins (offset, StrToTwips (argv1), lineLen); break; case tcrTempIndent: SetTempIndent (StrToTwips (argv1)); break; case tcrLineLength: SetMargins (offset, indent, StrToTwips (argv1)); break; case tcrTitleLength: break; case tcrTitleBegin: break; case tcrTitleEnd: break; case tcrSpace: /* * Begin new group and space to avoid changing params. * Negative param means exact spacing (positive means * "at least" spacing. */ if (pCount > 0) Para (); sprintf (buf, "{\\sl%ld\\sa0\\sb0\\par}\n", - StrToTwips (argv1)); StrOut (buf); break; case tcrUnderline: break; case tcrCUnderline: break; case tcrNoUnderline: break; case tcrULineFont: break; case tcrBracketBegin: TextStrOut ("BRACKET>"); break; case tcrBreakSpread: break; case tcrExtraSpace: break; case tcrLine: DrawLine (StrToTwips (argv1), tcrArgv[2][0]); break; case tcrMark: break; case tcrMotion: Motion (StrToTwips (argv1), tcrArgv[2][0]); break; case tcrBeginOverstrike: TextStrOut ("OVERSTRIKE>"); break; case tcrBeginPage: Para (); /* necessary? */ ControlOut ("page\n"); break; case tcrZeroWidth: break; case tcrSpaceSize: spaceSize = StrToLong (argv1); break; case tcrConstantWidth: break; case tcrNoConstantWidth: break; case tcrNeed: break; case tcrEmbolden: break; case tcrSEmbolden: break; case tcrResetTabs: ResetTabs (); break; case tcrFirstTab: ResetTabs (); /* fall through... */ case tcrNextTab: SetTabStop (StrToTwips (tcrArgv[1]), tcrArgv[2][0]); break; case tcrHyphenate: break; case tcrDiversionBegin: break; case tcrDiversionAppend: break; case tcrDiversionEnd: break; case tcrTabChar: break; case tcrLeaderChar: break; case tcrTableBegin: TableBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrTableEnd: TableEnd (); break; case tcrColumnInfo: TableColumnInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowBegin: TableRowBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowEnd: TableRowEnd (); break; case tcrRowLine: TableRowLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellInfo: TableCellInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellBegin: TableCellBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellEnd: TableCellEnd (); break; case tcrCellLine: TableCellLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrEmptyCell: TableEmptyCell (); break; case tcrSpannedCell: TableSpannedCell (); break; } } /* * The troffcvt setup section has now been seen, can write RTF prolog. * * margl and margr become the left and right margin values. Those * can only be set once (since they're document properties). They * become the zero-indent values. Changes to offset, indent or * line length afterwards map onto changes in \li or \ri (which * are paragraph properties). */ static void Prolog (void) { FTabInfo *fp; char buf[bufSiz]; margl = offset; margr = pageWid - offset - lineLen; SetMargins (offset, indent, lineLen); sprintf (buf, "{\\rtf1\\%s\\deff1\n", charSetName); StrOut (buf); StrOut ("{\\fonttbl\n"); for (fp = fTabList; fp != (FTabInfo *) NULL; fp = fp->nextFTabInfo) { sprintf (buf, "{\\f%d\\fnil %s;}\n", fp->tcrInfo->tcrFontNum, fp->rtfName); StrOut (buf); } StrOut ("}\n"); sprintf (buf, "\\paperh%ld \\paperw%ld\n", pageLen, pageWid); StrOut (buf); /*StrOut ("\\sectd\\sbknone\\linemod0\\linex0\\cols1\\endnhere\n");*/ sprintf (buf, "margl%ld ", margl); ControlOut (buf); sprintf (buf, "margr%ld ", margr); ControlOut (buf); ControlOut ("pard "); /*WriteParFmt (rpf, ipf);*/ /* * Act like the para state written to the output is the * same as the default state (because at the beginning of the * document, it is). */ *wpf = *rpf; /* flush out initial character format values */ SetFont (curFont); SetPointSize (pointSize); } /* * Draw a line (horizontal only). The implicit assumption is that * "-" is as wide as a space (all guesses are arbitrary since RTF has * no font metrics). */ static void DrawLine (long length, int direction) { long ssTwips; /* current space size in twips */ if (direction != 'h') /* ignore vertical lines */ return; ssTwips = (spaceSize * (pointSize * 10)) / 36; while (length > 0) { TextStrOut ("-"); length -= ssTwips; } } /* * Perform motion. For horizontal motion, the implicit assumption * is that \~ and backspace are as wide as a space (all guesses are * arbitrary since RTF has no font metrics). * * Vertical motion is in half-points. If there is any outstanding undone * vertical motion, it must be undone first to balance; some RTF readers * gag otherwise. */ static void Motion (long motion, int direction) { char buf[bufSiz]; long ssTwips; /* current space size in twips */ if (direction == 'h') { ssTwips = (spaceSize * (pointSize * 10)) / 36; if (motion > 0) { while (motion > 0) { ControlOut ("~"); motion -= ssTwips; } } else { while (motion < 0) { TextStrOut ("\b"); motion += ssTwips; } } } else if (direction == 'v') { /* convert value to half-points (20 twips/point)*/ motion /= 10; /* check for previous undone motion */ if (charUpDn != 0) { if (charUpDn < 0) ControlOut ("up0 "); else ControlOut ("dn0 "); /* Factor out just-undone motion from request. If this leaves motion=0, nothing more need be done. */ motion += charUpDn; charUpDn = 0; } if (motion == 0) return; else if (motion < 0) sprintf (buf, "up%ld ", -motion); else sprintf (buf, "dn%ld ", motion); ControlOut (buf); charUpDn = motion; } } static void ResetTabs (void) { ipf->pTabCount = 0; } static void SetTabStop (long pos, char type) { if (ipf->pTabCount < maxTabStops) { /* convert position to be relative to left indent */ pos += (offset + indent) - margl; ipf->pTabPos[ipf->pTabCount] = pos; ipf->pTabType[ipf->pTabCount] = type; ++ipf->pTabCount; } } /* * Map troff combination of offset, indent and linelength onto the * RTF equivalents of left and right indent (which are themselves * relative to the left and right margin). */ static void SetMargins (long nOffset, long nIndent, long nLineLen) { offset = nOffset; indent = nIndent; lineLen = nLineLen; ipf->pLIndent = (offset + indent) - margl; ipf->pRIndent = (pageWid - offset - lineLen) - margr; } /* * Map troff temporary indent onto RTF first-line indent. Also, * whereas troffcvt \temp-indent is an absolute value, RTF \fi * is relative to \li. */ static void SetTempIndent (long val) { ipf->pFIndent = val - indent; } /* * Set line spacing, which is a combination of the \spacing and * \line-spacing values. This translates into RTF space-between * and space-after. */ static void SetSpacing (long nSpacing, long nLineSpacing) { spacing = nSpacing; lineSpacing = nLineSpacing; ipf->pSpaceBetween = ipf->pSpaceAfter = spacing * lineSpacing; } /* * This generates more output than it needs to, but it * basically works, so too bad. */ static void SetFont (char *name) { TCRFont *fp; char buf[bufSiz]; if ((fp = TCRLookupFont (name)) == (TCRFont *) NULL) { ETMMsg ("no info for font <%s>", name); ControlOut ("f1\n"); /* default font */ return; } sprintf (buf, "\\f%d\\i0\\b0\n", fp->tcrFontNum); StrOut (buf); if (fp->tcrAtts & tcrItal) ControlOut ("i "); if (fp->tcrAtts & tcrBold) ControlOut ("b "); curFInfo = fp; (void) strcpy (curFont, name); } /* * Size is maintained in half-points. */ static void SetPointSize (long size) { char buf[bufSiz]; pointSize = size; sprintf (buf, "fs%ld ", pointSize); ControlOut (buf); } static void PlainText (void) { if (tcrMajor != '\n') { if (tcrMajor == '{' || tcrMajor == '}') TextChOut ('\\'); TextChOut (tcrMajor); } } static void SpecialText (void) { SpChar *sp; char buf[bufSiz]; int setFont = 0; char font[bufSiz]; TCRFont *fntInfo; if ((sp = LookupSpecial (&tcrArgv[0][1])) == (SpChar *) NULL || sp->spValue == (char *) NULL) { sprintf (buf, "[[%s]]", &tcrArgv[0][1]); TextStrOut (buf); } else { setFont = 0; if (sp->spFont != NULL && strcmp (sp->spFont, curFont) != 0) ++setFont; if (setFont) { StrOut ("{"); /* save info so can restore manually */ (void) strcpy (font, curFont); fntInfo = curFInfo; SetFont (sp->spFont); } TextStrOut (sp->spValue); if (setFont) { StrOut ("}"); (void) strcpy (curFont, font); curFInfo = fntInfo; } } } static void Para (void) { ControlOut ("par\n"); SetTempIndent (indent); pCount = 0; lCount = 0; } /* * Write out paragraph format properties that differ from some * baseline. bpf = base paragraph format, npf = new paragraph * format. */ static void WriteParFmt (ParFmt *bpf, ParFmt *npf) { char buf[bufSiz]; char *p; int c, i; if (bpf->pJustify != npf->pJustify) { p = (char *) NULL; switch (npf->pJustify) { default: ETMPanic ("WriteParFmt: bad justify code %d", npf->pJustify); case tcrCenter: case tcrAdjCenter: p = "qc "; break; case tcrNofill: case tcrAdjLeft: p = "ql "; break; case tcrAdjFull: p = "qj "; break; case tcrAdjRight: p = "qr "; break; } ControlOut (p); } if (bpf->pLIndent != npf->pLIndent) { sprintf (buf, "li%ld ", npf->pLIndent); ControlOut (buf); } if (bpf->pRIndent != npf->pRIndent) { sprintf (buf, "ri%ld ", npf->pRIndent); ControlOut (buf); } if (bpf->pFIndent != npf->pFIndent) { sprintf (buf, "fi%ld ", npf->pFIndent); ControlOut (buf); } if (bpf->pSpaceBetween != npf->pSpaceBetween) { sprintf (buf, "sl%ld ", npf->pSpaceBetween); ControlOut (buf); } /* Output looks better without this... if (bpf->pSpaceAfter != npf->pSpaceAfter) { sprintf (buf, "sa%ld ", npf->pSpaceAfter); ControlOut (buf); } */ /* if there are no explicit tabs, this writes nothing */ if (bpf->pTabCount != npf->pTabCount) { if (npf->pTabCount > 0) ChOut ('\n'); for (i = 0; i < npf->pTabCount; i++) { sprintf (buf, "tx%ld ", npf->pTabPos[i]); ControlOut (buf); if ((c = npf->pTabType[i]) == 'l') /* default */ continue; sprintf (buf, "tq%c ", c == 'c' ? 'c' : 'r'); ControlOut (buf); } if (npf->pTabCount > 0) ChOut ('\n'); } } /* * basic output routines * * ControlOut() - write control word. * TextStrOut() - write out a string of paragraph text. * TextChOut() - write out a character of paragraph text. * StrOut() - write out a string. * ChOut() - write out a character. ALL output (except ETM messages) * comes through this routine. * AllowOutput () - allow or throttle output. */ static void ControlOut (char *p) { if (p != (char *) NULL) { if (lCount > 0) { ChOut ('\n'); lCount = 0; } ChOut ('\\'); StrOut (p); } } static void TextStrOut (char *p) { if (p != (char *) NULL) { while (*p != '\0') TextChOut (*p++); } } /* * Write a character of paragraph text. If this is the first character * and the internally maintained paragraph format state is different * than the last one written out, put them in sync: write \pard to * reset to RTF defaults. If the internal state is then different * from that, write output to put it into effect. */ static void TextChOut (int c) { if (pCount == 0 && !ParFmtEq (wpf, ipf)) { ControlOut ("pard "); if (inTbl) ControlOut ("intbl "); *wpf = *rpf; if (!ParFmtEq (wpf, ipf)) { WriteParFmt (wpf, ipf); *wpf = *ipf; } } ChOut (c); ++pCount; /* break lines every now and then */ if (++lCount > 50 && c == ' ') { ChOut ('\n'); lCount = 0; } } static void StrOut (char *p) { if (p != (char *) NULL) { while (*p != '\0') ChOut (*p++); } } static void ChOut (char c) { if (oAllow && putc (c, stdout) == EOF) ETMPanic ("Write error, cannot continue"); } static int AllowOutput (int yesno) { int prev = oAllow; oAllow = yesno; return (prev); } /* * Convert a string representing basic units to twips */ static long StrToTwips (char *s) { return (Twips (StrToLong (s))); } /* * Convert a string representing points to half-points. */ static long StrToHalfPoints (char *s) { return (StrToLong (s) * 2); } /* * Table element routines * * Tables are written out in a group ({...}) to isolate formatting * changes made in the table from the surrounding part of the document. */ static void TableBegin (short argc, char **argv) { if (argc != 8) ETMPanic ("TableBegin: wrong number of args: %hd", argc); tblCols = StrToShort (argv[tblColsArg]); tblRows = StrToShort (argv[tblRowsArg]); if (tblCols == 0) ETMPanic ("TableBegin: zero column table"); if (tblCols > tblMaxCol) ETMPanic ("TableBegin: too many table columns (%hd), max = %d", tblCols, tblMaxCol); /* determine whether or not to center the table */ centerTbl = argv[tblAlignArg][0] == 'C'? 1 : 0; tblColIdx = 0; tblRowIdx = 0; inTbl = 1; /* put the table in a group */ ChOut ('{'); *tpf = *ipf; /* save current internal state */ *ipf = *rpf; /* set internal state to default */ WriteParFmt (wpf, ipf); /* sync written state to new internal state */ } static void TableEnd (void) { inTbl = 0; /* end the table group */ *ipf = *tpf; /* restore saved internal state */ WriteParFmt (wpf, ipf); /* sync written state to restored state */ ChOut ('}'); } static void TableColumnInfo (short argc, char **argv) { long width; long totWidth, defWidth; long rtEdge; short zeroes; short i; if (argc != 3) ETMPanic ("TableColumnInfo: wrong number of args: %hd", argc); if (tblColIdx >= tblMaxCol) ETMPanic ("TableColumnInfo: logic error"); /* * For separation and width, 0 means "none specified". RTF allows * only per-row separation, so use the first column separation value * for the first cell in the row. */ if (tblColIdx == 0) colSep = StrToTwips (argv[colSepArg]); colWidth[tblColIdx] = StrToTwips (argv[colWidthArg]); ++tblColIdx; if (tblColIdx < tblCols) return; /* * Have gotten all column info now. Figure out total width of columns * that had a width specified and how many didn't have any width * specified. Make the unspecified columns all the same width (a * hack, but I don't know how to figure out how wide they should be * without a lot of messing around). Do this by taking whatever's * left of the line width after subtracting the width of the specified * columns and dividing it among the unspecified columns. But don't * make them less than some minimum width. * * RTF column width values *include* the column separation, so the * right edge values calculated below will include that. */ if (colSep < 0) colSep = 0; totWidth = 0; zeroes = 0; for (i = 0; i < tblCols; i++) { if (colWidth[i]) totWidth += colWidth[i]; else ++zeroes; } defWidth = 0; if (totWidth - lineLen > 0 && zeroes > 0) defWidth = (totWidth - lineLen) / zeroes; if (defWidth < minColWidth) defWidth = minColWidth; /* now determine the right edge positions (including colSep) */ rtEdge = 0; for (i = 0; i < tblCols; i++) { if (colWidth[i]) colRtEdge[i] = rtEdge + colWidth[i] + colSep; else colRtEdge[i] = rtEdge + defWidth + colSep; rtEdge = colRtEdge[i]; } } /* * Begin a table row. */ static void TableRowBegin (short argc, char **argv) { /* * Reset tblColIdx for use by \table-cell-info controls */ tblColIdx = 0; } static void TableRowEnd (void) { if (tblColIdx != tblCols) /* paranoia check */ { ETMPanic ("columns in row %hd = %hd, should be %hd", tblRowIdx + 1, tblColIdx, tblCols); } ControlOut ("row "); ControlOut ("pard "); ++tblRowIdx; /* done with row, bump counter */ } /* * A row of a table should be a table-width line. Fake it by drawing * a short line in each column. */ static void TableRowLine (short argc, char **argv) { short i; /* * Can't do this without writing the regular other table row stuff! for (i = 0; i < tblCols; i++) TableCellLine (0, (char **) NULL); */ StrOut ("---"); ControlOut ("par"); ++tblRowIdx; /* done with row, bump counter */ } static void TableCellInfo (short argc, char **argv) { char buf[bufSiz]; short i; short vspan; if (argc != 5) ETMPanic ("TableCellInfo: wrong number of args: %hd", argc); cellType[tblColIdx] = argv[cellTypeArg][0]; vspan = StrToShort (argv[cellVSpanArg]); if (vspan == 1) /* not part of a span */ { cellVSpanFlag[tblColIdx] = 0; } else if (vspan > 1) /* part of a vspan -- first cell */ { cellVSpanFlag[tblColIdx] = 1; cellVSpanSize[tblColIdx] = vspan; cellVSpanIdx[tblColIdx] = 0; } else /* part of a vspan -- not first cell */ { ++cellVSpanIdx[tblColIdx]; } cellHSpan[tblColIdx] = StrToShort (argv[cellHSpanArg]); cellVAdjust[tblColIdx] = argv[cellVAdjustArg][0]; cellBorder[tblColIdx] = StrToShort (argv[cellBorderArg]); /* * Bump cell index. * Reset if we've reached the end, so it'll be correct for * \table-cell-begin, \table-empty-cell, \table-spanned-cell, * \table-cell-line. Also write out all the \cellx things * for the row since we now have all the necessary information. */ ++tblColIdx; if (tblColIdx < tblCols) return; tblColIdx = 0; ControlOut ("trowd"); sprintf (buf, "trgaph%ld", colSep / 2); ControlOut (buf); sprintf (buf, "trleft%ld", -colSep / 2); ControlOut (buf); ControlOut ("trkeep"); for (i = 0; i < tblCols; i++) { if (cellHSpan[i] > 1) /* first hspan cell */ ControlOut ("clmgf"); if (cellHSpan[i] == 0) ControlOut ("clmrg"); /* cell is hspanned */ if (cellVSpanFlag[i]) /* part of a vspan */ { if (cellVSpanIdx[i] == 0) /* first vspan cell */ ControlOut ("clvmgf"); else ControlOut ("clvmrg"); } sprintf (buf, "cellx%ld", colRtEdge[i]); ControlOut (buf); } } static void TableCellBegin (short argc, char **argv) { CellBegin (); switch (cellType[tblColIdx]) { default: break; /* don't do anything */ case 'C': ControlOut ("qc"); break; case 'R': case 'N': /* treat numeric as right-aligned */ ControlOut ("qr"); break; } } static void TableCellEnd (void) { CellEnd (); } static void TableEmptyCell (void) { CellBegin (); CellEnd (); } static void TableSpannedCell (void) { CellBegin (); CellEnd (); } /* * This is really poor. What's a better way? */ static void TableCellLine (short argc, char **argv) { CellBegin (); StrOut ("---"); CellEnd (); } static void CellBegin (void) { short hspan; hspan = cellHSpan[tblColIdx]; if (hspan == 1) /* not part of a hspan */ { cellHSpanFlag = 0; } else if (hspan > 1) /* part of a hspan -- first cell */ { cellHSpanFlag = 1; cellHSpanSize = hspan; cellHSpanIdx = 0; } else /* part of a hspan -- not first cell */ { ++cellHSpanIdx; } /* * Order is important here. \pard following \intbl seems to make * Word forget that it's in a cell. */ ControlOut ("pard "); ControlOut ("intbl "); } static void CellEnd (void) { ControlOut ("cell"); pCount = 0; lCount = 0; ++tblColIdx; } bufSiz]; char *p; int c, i; if (bpf->pJustify != npf->pJustify) { p = (char *) NULL; switch (npf->pJustify) { default: ETMPanic ("WriteParFmt: bad justify code %d", npf->pJustifytroffcvt-1.04/post/tc2text.c010066400017710000151000000603300634113671500175550ustar00junkyarddatamgmt00000400000027/* * To do: * - .sp doesn't pay attention to argument. * - Add Latin-1 encoding? * - TableCellLine() doesn't handle spans. Nor does TableEmptyCell(). * - Count unspecified-width cells, use line-length to improve guess. * - Why do I get a space before cell text? * - Maybe tblcvt could examine table data and make some guesses about * column widths... */ /* * * tc2text - read output from troffcvt and extract the text * * This troffcvt postprocessor is part of unroff - a smarter * version of deroff. For one thing, it can be configured to * do different things with special characters simply by editing * text-specials. * * - Doesn't handle table centering. * * 20 Apr 92 Paul DuBois dubois@primate.wisc.edu * * 20 Apr 92 V1.00. Created. */ #include #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "portlib.h" #include "etm.h" #include "memmgr.h" #include "tokenscan.h" #include "tcgen.h" #include "tcunix.h" #include "tcread.h" #include "tctbl.h" #define spCharFile "text-specials" #define spChar8File "text-8-specials" /* 8-bit output characters */ #define defResolution 432 #define charsPerInch 12 #define StrToChars(s) ((StrToLong(s) * charsPerInch) / resolution) #define maxTabStops 35 #define defColWidth 12 /* 12 characters */ #define defColSep 2 /* 2 characters */ /* * Adjustment types (there is no "adjust-both"; \adjust-full maps to adjLeft) */ #define adjLeft 0 /* left justify */ #define adjCenter 1 /* center */ #define adjRight 2 /* right justify */ /* * Special character structure */ typedef struct SpChar SpChar; struct SpChar { char *spName; unsigned char *spValue; SpChar *spNext; }; static void ReadFile (void); static void ControlLine (void); static void SpecialText (void); static void PlainText (void); static void ResetTabs (void); static void SetTabStop (long pos, char type); static void DrawLine (long length, int direction); static int ReadSpecials (char *filename); static SpChar *LookupSpecial (char *name); static void Break (void); static void Para (void); static long NextTabAmount (void); static void WrapLine (int trigger); static void FlushBuf (short addNewline); static void ChOut (int c); static void ChOutWrap (int c); static void ChOutNoWrap (int c); static void StrOut (char *s); static void TableBegin (short argc, char **argv); static void TableEnd (void); static void TableColumnInfo (short argc, char **argv); static void TableRowBegin (short argc, char **argv); static void TableRowEnd (void); static void TableRowLine (short argc, char **argv); static void TableCellInfo (short argc, char **argv); static void TableCellBegin (short argc, char **argv); static void TableCellEnd (void); static void TableEmptyCell (void); static void TableSpannedCell (void); static void TableCellLine (short argc, char **argv); static void TabToTableCol (void); static char *usage = "tc2text [ -E ] [ -J ] [ -8 ] [ file ] ..."; static SpChar *spList; static int split = 1; static int echo = 0; static int eightbit = 0; /* whether or not to include 8-bit chars */ static long resolution; /* * Stuff for managing output buffer used for line filling and breaking * * oBuf Output buffer * oPtr Pointer into buffer (no terminating null is used) * oPos Logical position into output line (even if buffer has gotten * full and has been flushed) * indentAmt Amount by which to indent current line when it gets flushed * * For best results, oBufSiz should be large (longer than any reasonable * expected output line length. The program simply panics if the buffer * overflows. */ #define oBufSiz 10240 static char oBuf[oBufSiz]; static char *oPtr; static long oPos; static long offset; static long indent; static long tmpIndent; static long indentAmt; static long lineLen; static short segment; static short adjust = adjLeft; /* line adjustment mode */ static short fill = 0; /* non-zero if fill mode on */ static short center = 0; /* non-zero if centering on */ static int tossWhite; static short tabPos[maxTabStops]; static char tabType[maxTabStops]; /* this is actually ignored */ static short tabCount = 0; /* * Per-table values */ static short tblCols = 0; /* number of columns in table */ static short tblRows = 0; /* number of rows in table */ static short tblWidth = 0; /* width of table */ /* * Per-column values */ static long colWidth[tblMaxCol]; /* column width */ static long colSep[tblMaxCol]; /* column separation */ static long colRtEdge[tblMaxCol]; /* column right edge */ static short colEqWidth[tblMaxCol]; /* column is equal-width? */ /* * Per-cell values. For the span stuff, the flag is set when in a span * (a set of > 1 cells that are merged together), the size is the number * of cells that the span comprises, and the idx is the index of the current * cell within the span (range is 0..size-1). */ static char cellType[tblMaxCol]; /* cell type */ static short cellVSpanFlag[tblMaxCol]; /* cell vspan flag */ static short cellVSpanSize[tblMaxCol]; /* cell vspan extent */ static short cellVSpanIdx[tblMaxCol]; /* cell vspan counter */ static short cellHSpan[tblMaxCol]; /* cell hspan extent */ /* * Counters for keeping track of position within table. * tblColIdx counts horizontally during processing of \table-column-info * lines, during \table-cell-info lines, and while processing each row of * table data. tblRowIdx counts rows of table data. */ static short tblColIdx = 0; static short tblRowIdx = 0; int main (int argc, char *argv[]) { char *p; int inc; ETMInit (NULL); UnixSetProgPath (argv[0]); TCRSetOpenLibFileProc (UnixOpenLibFile); --argc; ++argv; while (argc > 0 && argv[0][0] == '-') { inc = 1; if (strcmp (argv[0], "-E") == 0) echo = 1; else if (strcmp (argv[0], "-J") == 0) split = 0; else if (strcmp (argv[0], "-8") == 0) eightbit = 1; else { ETMMsg ("Unknown option: %s", argv[0]); ETMPanic ("%s", usage); } argc -= inc; argv += inc; } /* * Read special character definitions. Then add to those the * definitions for 8-bit Latin-1 characters if they were requested * from the command line. */ if (!ReadSpecials (spCharFile)) ETMPanic ("cannot find %s file", spCharFile); if (eightbit && !ReadSpecials (spChar8File)) ETMPanic ("cannot find %s file", spChar8File); if (argc == 0) /* stdin */ ReadFile (); else while (argc > 0) { if (freopen (argv[0], "r", stdin) == (FILE *) NULL) ETMMsg ("Cannot open: %s", argv[0]); else ReadFile (); --argc; ++argv; } ETMEnd (); exit (0); /*NOTREACHED*/ } static int BeginFile (void) { resolution = defResolution; lineLen = (long) (6.5 * charsPerInch); offset = 0; /* this isn't really used */ oPtr = oBuf; oPos = 0; segment = 1; indentAmt = 0; tossWhite = 0; return (1); } static void ReadFile (void) { int i; TCRInit (); (void) BeginFile (); while (TCRGetToken () != tcrEOF) { if (echo) { ETMMsg ("class %d maj %d min %d <%s>", tcrClass, tcrMajor, tcrMinor, tcrArgv[0]); if (tcrClass == tcrControl || tcrClass == tcrSText) { for (i = 1; i < tcrArgc; i++) ETMMsg (" <%s>", tcrArgv[i]); } } switch (tcrClass) { case tcrControl: ControlLine (); break; case tcrText: PlainText (); break; case tcrSText: SpecialText (); break; default: ETMPanic ("ReadFile: unknown class %d", tcrClass); } } } static void ControlLine (void) { switch (tcrMajor) { default: ETMMsg ("ControlLine: bad control major code: %d <%s>", tcrMajor, tcrArgv[0]); break; case tcrCUnknown: ETMMsg ("ControlLine: unknown control token: <%s>", tcrArgv[0]); break; case tcrBreak: Break (); break; case tcrSpace: /* pay attention to argument? */ Break (); ChOut ('\n'); break; case tcrCFA: switch (tcrMinor) { case tcrNofill: fill = 0; break; case tcrCenter: center = 1; break; case tcrAdjFull: case tcrAdjLeft: center = 0; fill = 1; adjust = adjLeft; break; case tcrAdjRight: center = 0; fill = 1; adjust = adjRight; break; case tcrAdjCenter: center = 1; break; } break; case tcrComment: break; case tcrSetupBegin: break; case tcrSetupEnd: break; case tcrResolution: resolution = StrToLong (tcrArgv[1]); break; case tcrPass: break; case tcrInputLine: break; case tcrOther: break; case tcrFont: break; case tcrPointSize: break; case tcrSpacing: break; case tcrLineSpacing: break; case tcrOffset: offset = StrToChars (tcrArgv[1]); break; case tcrIndent: tmpIndent = indent = StrToChars (tcrArgv[1]); break; case tcrTempIndent: tmpIndent = StrToChars (tcrArgv[1]); break; case tcrLineLength: /* * If the output line length goes above the length of the line * collection buffer, there will be trouble. Clip the length * if necessary. */ lineLen = StrToChars (tcrArgv[1]); if (lineLen > sizeof (oBuf)) { lineLen = sizeof (oBuf); ETMMsg ("unroff: line length clipped to %ld chars", lineLen); } break; case tcrPageLength: break; case tcrPageNumber: break; case tcrTitleLength: break; case tcrTitleBegin: break; case tcrTitleEnd: break; case tcrUnderline: break; case tcrCUnderline: break; case tcrNoUnderline: break; case tcrULineFont: break; case tcrBracketBegin: break; case tcrBracketEnd: break; case tcrBreakSpread: break; case tcrExtraSpace: break; case tcrLine: DrawLine (StrToLong (tcrArgv[1]), tcrArgv[2][0]); break; case tcrMark: break; case tcrMotion: break; case tcrBeginOverstrike: break; case tcrOverstrikeEnd: break; case tcrBeginPage: break; case tcrZeroWidth: break; case tcrSpaceSize: break; case tcrConstantWidth: break; case tcrNoConstantWidth: break; case tcrNeed: break; case tcrEmbolden: break; case tcrSEmbolden: break; case tcrResetTabs: ResetTabs (); break; case tcrFirstTab: ResetTabs (); /* fall through... */ case tcrNextTab: SetTabStop (StrToLong (tcrArgv[1]), tcrArgv[2][0]); break; case tcrHyphenate: break; case tcrDiversionBegin: break; case tcrDiversionAppend: break; case tcrDiversionEnd: break; case tcrTabChar: break; case tcrLeaderChar: break; case tcrTableBegin: TableBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrTableEnd: TableEnd (); break; case tcrColumnInfo: TableColumnInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowBegin: TableRowBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowEnd: TableRowEnd (); break; case tcrRowLine: TableRowLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellInfo: TableCellInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellBegin: TableCellBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellEnd: TableCellEnd (); break; case tcrCellLine: TableCellLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrEmptyCell: TableEmptyCell (); break; case tcrSpannedCell: TableSpannedCell (); break; } } static void PlainText (void) { if (tcrMajor != '\n' && tcrMajor != '\r') ChOut (tcrMajor); } /* * Draw a line (horizontal only). The number of - characters to * write is just a guess appropriate for terminals; probably should * be a way of controlling with a command line argument. */ static void DrawLine (long length, int direction) { if (tcrArgv[2][0] != 'h') /* ignore vertical lines */ return; length = length * charsPerInch / resolution; while (length-- > 0) ChOut ('-'); } static void SpecialText (void) { SpChar *sp; if ((sp = LookupSpecial (&tcrArgv[0][1])) == (SpChar *) NULL) { StrOut ("[["); StrOut (&tcrArgv[0][1]); StrOut ("]]"); } else StrOut ((char *) sp->spValue); } /* * Read special character list. Character codes may be specified numerically * as #nnn where nnn is the decimal value. To specify a literal #, use ##. */ static int ReadSpecials (char *filename) { TSScanner scanner; FILE *f; char buf[bufSiz]; SpChar *sp; unsigned char *name, *value; unsigned char *p, *p2, c; if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) return (0); TSGetScanner (&scanner); /* want default scanner */ TSSetScanner ((TSScanner *) NULL); /* behavior */ while (TCRGetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') continue; TSScanInit (buf); if ((name = (unsigned char *) TSScan ()) == (unsigned char *) NULL) continue; if ((value = (unsigned char *) TSScan ()) == (unsigned char *) NULL) value = (unsigned char *) ""; /* * convert #nnn to a single char with value decimal nnn, * #x (x anything else) to just x. */ p = p2 = value; while (*p2 != '\0') { if ((c = *p2++) == '#' && *p2 != '\0') { if (!isdigit (*p2) || !isdigit (*(p2+1)) || !isdigit (*(p2+2))) { c = *p2++; } else { c = (*p2 - '0') * 100 + (*(p2+1) - '0') * 10 + (*(p2+2) - '0'); p2 += 3; } } *p++ = c; } *p = '\0'; /* * If char hasn't been defined yet, allocate a new structure * for it; otherwise reuse the structure by deallocating * the existing name and value fields. */ if ((sp = LookupSpecial ((char *) name)) == (SpChar *) NULL) { sp = New (SpChar); sp->spNext = spList; spList = sp; } else { Free (sp->spName); Free (sp->spValue); } sp->spName = StrAlloc (name); sp->spValue = (unsigned char *) StrAlloc ((char *) value); } (void) fclose (f); TSSetScanner (&scanner); return (1); } static SpChar * LookupSpecial (char *name) { SpChar *sp; for (sp = spList; sp != (SpChar *) NULL; sp = sp->spNext) { if (strcmp (name, sp->spName) == 0) break; } return (sp); /* NULL if not found */ } static void ResetTabs (void) { tabCount = 0; } static void SetTabStop (long pos, char type) { if (tabCount >= maxTabStops) { ETMMsg ("too many tabstops"); return; } /* * Assume charsPerInch characters/inch */ tabPos[tabCount] = (pos * charsPerInch) / resolution; tabType[tabCount] = type; ++tabCount; } /* * Return the number of spaces to put out to reach the next tab stop, taking * into account the indent for the current output line. Always returns a * value of at least 1. If there are no tabstops past the current output * position, act as though there are tabs every 8 characters from that point * on. * * Tabs are calculated relative to the page offset, which is considered the * origin. */ static long NextTabAmount (void) { int i; long curPos; curPos = indentAmt + oPos; for (i = 0; i < tabCount; i++) { if (tabPos[i] > curPos) return (tabPos[i] - curPos); } return (8 - (curPos % 8)); } static void Break (void) { if (oPos) /* force out output line if there is one */ Para (); } static void Para (void) { ChOut ('\n'); } static void StrOut (char *s) { while (*s != '\0') ChOut (*s++); } static void ChOut (int c) { if (split) ChOutWrap (c); else ChOutNoWrap (c); } /* * The normal case (no -J option) is to write characters and wrap lines * at the right border unless in no-fill mode. */ static void ChOutWrap (int c) { long advance; /* ignore whitespace after line wrapping to avoid extraneous indents */ if (tossWhite && (c == ' ' || c == '\t')) return; /* not a whitespace character; can stop tossing white */ tossWhite = 0; /* * Before writing out first char of output line, calculate the indent * to use when the line is finally forced out. (This must be done * BEFORE tab expansion.) */ if (oPos == 0) indentAmt = tmpIndent; /* * End of line means we know we've seen the end of the current word. * Check whether line needs wrapping and flush. */ if (c == '\n') /* end of line */ { if (fill && indentAmt + oPos >= lineLen) WrapLine ('\n'); else FlushBuf (1); return; } if (c == '\t') /* do tab expansion */ { advance = NextTabAmount (); while (advance-- > 0) ChOut (' '); return; } if (oPtr >= oBuf + sizeof (oBuf)) { FlushBuf (1); ETMPanic ("unroff: output buffer capacity exceeded"); } /* * If the character is a space and the output line has reached * or exceeded the desired line length, wrap the line. WrapLine() * takes care of adding the space. */ if (c == ' ' && fill && indentAmt + oPos >= lineLen) WrapLine (' '); else { *oPtr++ = c; ++oPos; /* increment logical line position */ } } /* * Write out characters, but don't do line wrapping at the right border. * This makes paragraphs appear in the output on a single line, which is * more appropriate when moving the resulting document to a word processor * that treats paragraphs internally as one line. */ static void ChOutNoWrap (int c) { long advance; /* * Before writing out first char of output line, calculate the indent * to use when the line is finally forced out. (This must be done * BEFORE tab expansion.) */ if (oPos == 0) indentAmt = tmpIndent; if (c == '\n') /* end of line */ { FlushBuf (1); return; } if (c == '\t') /* do tab expansion */ { advance = NextTabAmount (); while (advance-- > 0) ChOut (' '); return; } if (oPtr >= oBuf + sizeof (oBuf)) FlushBuf (0); *oPtr++ = c; ++oPos; /* increment logical line position */ } /* * Flush output line currently being collected, without line wrapping. * Since a paragraph may be a single line output line, the line may need * to be flushed in segments. * * addNewline is nonzero if a newline should be written after flushing * the buffer. This will be zero if the buffer was discovered to have * filled up and another character needs to be added to it. Always call * this routine with addNewline = 1 for the line-wrapping case. */ static void FlushBuf (short addNewline) { char *p; long i; /* can perform centering only if entire output line is in buffer */ if (center && segment == 1 && addNewline) { i = (lineLen - oPos) / 2; while (i-- > 0) putchar (' '); } /* discard any trailing whitespace on the line (if last segment) */ if (addNewline) { while (oPtr > oBuf && *(oPtr-1) == ' ') --oPtr; } if (oPtr > oBuf) /* if line not empty, write contents */ { if (segment == 1) /* add indent only to first segment */ { for (i = 0; i < indentAmt; i++) putchar (' '); } for (p = oBuf; p < oPtr; p++) putchar (*p); } /* write final newline */ if (addNewline) { putchar ('\n'); /* * Reinitialize line-collection variables */ oPtr = oBuf; oPos = 0; tossWhite = 0; tmpIndent = indent; segment = 1; } else { oPtr = oBuf; ++segment; } } /* * Handle line wrapping. This occurs when the end of a word is found (which * is known by encountering whitespace or newline) and the output line length * reaches or exceeds the desired line length. Flush out as many words from * the current buffer as will fit within the line length, then shove the * remainder to the beginning of the buffer; that remainder becomes the * beginning of the next output line. * * Don't call this routine in nofill mode * * trigger is the character that was seen that triggered the call to * WrapLine() (space, tab, or newline). If the entire buffer is flushed, * the trigger is discarded. Otherwise, after moving down any trailing part * of the buffer, the trigger is rerouted through ChOut(). */ static void WrapLine (int trigger) { char *p, *oPtrSave; /* * If line is exactly the desired length, flush it and discard * the trigger character. */ if (indentAmt + oPos == lineLen) { FlushBuf (1); return; } /* * Line is longer than desired length. Split off the last word, * flush the stuff preceding it, then move the word down to the * beginning of the beginning of the buffer, and add the trigger * character after the word. * SPECIAL CASE: if the entire buffer is a single word, it can't * be split. Flush it all and discard the trigger, just as if the * line were exactly the right length. */ p = oPtr; while (p > oBuf && *(p-1) != ' ') /* seek last space */ --p; if (p == oBuf) /* entire buffer is one word! */ { FlushBuf (1); return; } /* * p points to beginning of final word. Save value of oPtr for * later, move it back to the beginning of the word and flush that * much of the buffer. */ oPtrSave = oPtr; oPtr = p; FlushBuf (1); /* * Now re-add the last word to the (beginning of the) buffer. This * is tricky, because we're adding characters to the beginning of * the buffer that come from later in the buffer. */ while (p < oPtrSave) ChOut (*p++); /* * Add trigger character. If this is a newline, it will cause the * final word to be flushed on its own line. Otherwise it'll just * add whitespace after the word on the (new) current line. */ ChOut (trigger); } /* * Table element routines */ static void TableBegin (short argc, char **argv) { if (argc != 8) ETMPanic ("TableBegin: wrong number of args: %hd", argc); tblRows = StrToShort (argv[tblRowsArg]); tblCols = StrToShort (argv[tblColsArg]); if (tblCols == 0) ETMPanic ("TableBegin: zero column table"); if (tblCols > tblMaxCol) ETMPanic ("TableBegin: too many table columns (%hd), max = %d", tblCols, tblMaxCol); tblColIdx = 0; tblRowIdx = 0; Break (); } static void TableEnd (void) { Break (); } static void TableColumnInfo (short argc, char **argv) { short i; if (argc != 3) ETMPanic ("TableColumnInfo: wrong number of args: %hd", argc); if (tblColIdx >= tblMaxCol) ETMPanic ("TableColumnInfo: logic error"); /* * For separation and width, 0 means "none specified". */ colSep[tblColIdx] = StrToChars (argv[colSepArg]); colWidth[tblColIdx] = StrToChars (argv[colWidthArg]); colEqWidth[tblColIdx] = (argv[colEqWidthArg][0] == 'y' ? 1 : 0); ++tblColIdx; if (tblColIdx < tblCols) return; /* * Have gotten information for all columns now. Determine the * right edges and total table width. This is a very simplistic * algorithm. */ tblWidth = 0; for (i = 0; i < tblCols; i++) { if (colWidth[i] == 0) colWidth[i] = defColWidth; if (colSep[i] == 0) colSep[i] = defColSep; tblWidth += colWidth[i] + colSep[i]; colRtEdge[i] = tblWidth; /* ETMMsg ("col %hd, edge %hd", i, colRtEdge[i]); */ } /* probably could expand widths here if table should be expanded */ } /* * Begin a table row. */ static void TableRowBegin (short argc, char **argv) { /* * Reset tblColIdx for use by \table-cell-info controls */ tblColIdx = 0; } static void TableRowEnd (void) { Break (); ++tblRowIdx; /* done with row, bump counter */ } static void TableRowLine (short argc, char **argv) { short i; for (i = 0; i < colRtEdge[tblCols-1]; i++) ChOut ('-'); Break (); ++tblRowIdx; /* done with row, bump counter */ } static void TableCellInfo (short argc, char **argv) { char buf[bufSiz]; short vspan; if (argc != 5) ETMPanic ("TableCellInfo: wrong number of args: %hd", argc); if (tblColIdx >= tblMaxCol) ETMPanic ("TableCellInfo: logic error"); cellType[tblColIdx] = argv[cellTypeArg][0]; vspan = StrToShort (argv[cellVSpanArg]); if (vspan == 1) /* not part of a vspan */ { cellVSpanFlag[tblColIdx] = 0; } else if (vspan > 1) /* part of a vspan -- first cell */ { cellVSpanFlag[tblColIdx] = 1; cellVSpanSize[tblColIdx] = vspan; cellVSpanIdx[tblColIdx] = 0; } else /* part of a vspan -- not first cell */ { ++cellVSpanIdx[tblColIdx]; } cellHSpan[tblColIdx] = StrToShort (argv[cellHSpanArg]); /* vertical adjust is ignored */ /* borders are ignored */ /* * Bump cell index. * Reset if we've reached the end, so it'll be correct for * \table-cell-begin, \table-empty-cell, \table-spanned-cell, * \table-cell-line. */ ++tblColIdx; if (tblColIdx >= tblCols) tblColIdx = 0; } static void TableCellBegin (short argc, char **argv) { TabToTableCol (); } static void TableCellEnd (void) { ++tblColIdx; } static void TableEmptyCell (void) { ++tblColIdx; } static void TableSpannedCell (void) { ++tblColIdx; } /* * Draw a line as wide as the current cell and any following cells that * it spans horizontally. */ static void TableCellLine (short argc, char **argv) { short prevRtEdge, i; TabToTableCol (); prevRtEdge = (tblColIdx == 0 ? 0 : colRtEdge[tblColIdx-1]); i = colRtEdge[tblColIdx + cellHSpan[tblColIdx] - 1] - prevRtEdge; while (i-- > 0) ChOut ('-'); ++tblColIdx; } /* * Space over to the beginning of the current table column. (Do nothing * for first column.) */ static void TabToTableCol (void) { short i; if (tblColIdx > 0) { /* ETMMsg ("currently at %ld, tab to %hd", oPos, colRtEdge[tblColIdx-1]); */ i = colRtEdge[tblColIdx-1] - oPos; while (i-- > 0) ChOut (' '); } } oPos; for (i = 0; i < tabCount; i++) { if (tabPos[i] > curPos) return (tabPos[i] - curPos); } return (8 - (curPos % 8)); } static void Break (void) { if (oPos) /* force out output line if there is one */ Para (); } static void Para (void) { ChOut ('\n'); } static void StrOuttroffcvt-1.04/post/tc2rtf.h010066400017710000151000000033460626662671200174040ustar00junkyarddatamgmt00000400000027# if !defined(SYSV) && !defined(SVR4) # define memcmp bcmp /* assume BSD close-equivalent available */ # endif /* Compare paragraph formats (passed by address) */ # define ParFmtEq(a,b) \ (memcmp ((char *) a,(char *) b,(int) sizeof (ParFmt)) == 0) # define maxTabStops 35 # define maxCharSet 4 /* Character sets - must be zero-based and sequential */ # define ansiCharSet 0 # define macCharSet 1 # define pcCharSet 2 # define pcaCharSet 3 /* FTabInfo - information to map the TCR typeface names onto the names to use in \fonttbl. */ typedef struct FTabInfo FTabInfo; struct FTabInfo { TCRFont *tcrInfo; /* info maintained by reader */ char *rtfName; /* rtf name per charset */ FTabInfo *nextFTabInfo; }; /* Special character structure */ typedef struct SpChar SpChar; struct SpChar { char *spName; char *spFont; char *spValue; SpChar *spNext; }; /* Paragraph formatting properties. All positional values are in twips. */ typedef struct ParFmt ParFmt; struct ParFmt { long pJustify; /* justification */ long pLIndent; /* left indent */ long pRIndent; /* right indent */ long pFIndent; /* first indent */ long pSpaceBefore; /* space before paragraph */ long pSpaceAfter; /* space after paragraph */ long pSpaceBetween; /* space between lines */ int pTabCount; /* number of tabstops */ long pTabPos[maxTabStops]; /* tabstop positions */ char pTabType[maxTabStops]; /* tabstop types */ }; /* Character formatting properties (not used properly yet) */ typedef struct CharFmt CharFmt; struct CharFmt { int dummy; }; int ReadFontInfo (); int ReadSpecials (); FTabInfo *LookupFont (); SpChar *LookupSpecial (); extern FTabInfo *fTabList; extern SpChar *spList; extern int charSet; extern char *charSetName; troffcvt-1.04/post/Makefile010066400017710000151000000503170634136770700174670ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./post # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # troffcvt postprocessor Makefile # make sure "all" is default target all:: # any special -D's or other flags for compiling DEFINES = # any special -I's for compiling INCLUDES = # libraries needed for linking LIBS = $(TCREADLIB) $(TCUNIXLIB) $(TCGENLIB) $(MEMMGRLIB) \ $(TSLIB) $(ETMLIB) $(PORTLIB) DEPLIBS = $(DEPTCREADLIB) $(DEPTCUNIXLIB) $(DEPTCGENLIB) $(DEPMEMMGRLIB) \ $(DEPTSLIB) $(DEPETMLIB) $(DEPPORTLIB) NULLSRCS = tc2null.c NULLOBJS = tc2null.o RTFSRCS = tc2rtf.c rtffont.c RTFOBJS = tc2rtf.o rtffont.o HTMLSRCS = tc2html.c HTMLOBJS = tc2html.o TEXTSRCS = tc2text.c TEXTOBJS = tc2text.o SRCS = $(NULLSRCS) $(RTFSRCS) $(HTMLSRCS) $(TEXTSRCS) OBJS = $(NULLOBJS) $(RTFOBJS) $(HTMLOBJS) $(TEXTOBJS) # general-purpose data files install:: i.tcr-fonts help_aux:: @echo "'make "i.tcr-fonts"' to "install tcr-fonts i.tcr-fonts:: tcr-fonts @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tcr-fonts $(LIBDIR)/tcr-fonts # troff2null stuff all:: tc2null help_aux:: @echo "'make "tc2null"' to "build tc2null tc2null: $(NULLOBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(NULLOBJS) $(LDOPTS) $(LIBS) $(EXTRA_LDLIBS) clean:: $(RM) tc2null lint:: lint.tc2null lint.tc2null: $(LINT) $(LINTFLAGS) $(NULLSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.tc2null"' to "lint sources for tc2null install:: i.tc2null help_aux:: @echo "'make "i.tc2null"' to "install tc2null i.tc2null:: tc2null @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTPROGFLAGS) tc2null $(LOCALBINDIR)/tc2null all:: troff2null troff2null:: troff2null.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) troff2null.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) troff2null help_aux:: @echo "'make "troff2null"' to "build the troff2null script install:: i.troff2null help_aux:: @echo "'make "i.troff2null"' to "install troff2null i.troff2null:: troff2null @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTSCRIPTFLAGS) troff2null $(LOCALBINDIR)/troff2null # troff2html stuff all:: tc2html help_aux:: @echo "'make "tc2html"' to "build tc2html tc2html: $(HTMLOBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(HTMLOBJS) $(LDOPTS) $(LIBS) $(EXTRA_LDLIBS) clean:: $(RM) tc2html lint:: lint.tc2html lint.tc2html: $(LINT) $(LINTFLAGS) $(HTMLSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.tc2html"' to "lint sources for tc2html install:: i.tc2html help_aux:: @echo "'make "i.tc2html"' to "install tc2html i.tc2html:: tc2html @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTPROGFLAGS) tc2html $(LOCALBINDIR)/tc2html all:: tc2html-toc tc2html-toc:: tc2html-toc.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) tc2html-toc.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) tc2html-toc help_aux:: @echo "'make "tc2html-toc"' to "build the tc2html-toc script install:: i.tc2html-toc help_aux:: @echo "'make "i.tc2html-toc"' to "install tc2html-toc i.tc2html-toc:: tc2html-toc @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTSCRIPTFLAGS) tc2html-toc $(LOCALBINDIR)/tc2html-toc all:: troff2html troff2html:: troff2html.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) troff2html.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) troff2html help_aux:: @echo "'make "troff2html"' to "build the troff2html script install:: i.troff2html help_aux:: @echo "'make "i.troff2html"' to "install troff2html i.troff2html:: troff2html @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTSCRIPTFLAGS) troff2html $(LOCALBINDIR)/troff2html install:: i.html-fonts help_aux:: @echo "'make "i.html-fonts"' to "install html-fonts i.html-fonts:: html-fonts @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) html-fonts $(LIBDIR)/html-fonts install:: i.html-specials help_aux:: @echo "'make "i.html-specials"' to "install html-specials i.html-specials:: html-specials @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) html-specials $(LIBDIR)/html-specials # troff2rtf stuff all:: tc2rtf help_aux:: @echo "'make "tc2rtf"' to "build tc2rtf tc2rtf: $(RTFOBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(RTFOBJS) $(LDOPTS) $(LIBS) $(EXTRA_LDLIBS) clean:: $(RM) tc2rtf lint:: lint.tc2rtf lint.tc2rtf: $(LINT) $(LINTFLAGS) $(RTFSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.tc2rtf"' to "lint sources for tc2rtf install:: i.tc2rtf help_aux:: @echo "'make "i.tc2rtf"' to "install tc2rtf i.tc2rtf:: tc2rtf @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTPROGFLAGS) tc2rtf $(LOCALBINDIR)/tc2rtf all:: troff2rtf troff2rtf:: troff2rtf.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) troff2rtf.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) troff2rtf help_aux:: @echo "'make "troff2rtf"' to "build the troff2rtf script install:: i.troff2rtf help_aux:: @echo "'make "i.troff2rtf"' to "install troff2rtf i.troff2rtf:: troff2rtf @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTSCRIPTFLAGS) troff2rtf $(LOCALBINDIR)/troff2rtf install:: i.rtf-fonts help_aux:: @echo "'make "i.rtf-fonts"' to "install rtf-fonts i.rtf-fonts:: rtf-fonts @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) rtf-fonts $(LIBDIR)/rtf-fonts install:: i.rtf-spec-ansi help_aux:: @echo "'make "i.rtf-spec-ansi"' to "install rtf-spec-ansi i.rtf-spec-ansi:: rtf-spec-ansi @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) rtf-spec-ansi $(LIBDIR)/rtf-spec-ansi install:: i.rtf-spec-mac help_aux:: @echo "'make "i.rtf-spec-mac"' to "install rtf-spec-mac i.rtf-spec-mac:: rtf-spec-mac @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) rtf-spec-mac $(LIBDIR)/rtf-spec-mac install:: i.rtf-spec-pc help_aux:: @echo "'make "i.rtf-spec-pc"' to "install rtf-spec-pc i.rtf-spec-pc:: rtf-spec-pc @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) rtf-spec-pc $(LIBDIR)/rtf-spec-pc install:: i.rtf-spec-pca help_aux:: @echo "'make "i.rtf-spec-pca"' to "install rtf-spec-pca i.rtf-spec-pca:: rtf-spec-pca @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) rtf-spec-pca $(LIBDIR)/rtf-spec-pca # unroff stuff all:: tc2text help_aux:: @echo "'make "tc2text"' to "build tc2text tc2text: $(TEXTOBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(TEXTOBJS) $(LDOPTS) $(LIBS) $(EXTRA_LDLIBS) clean:: $(RM) tc2text lint:: lint.tc2text lint.tc2text: $(LINT) $(LINTFLAGS) $(TEXTSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.tc2text"' to "lint sources for tc2text install:: i.tc2text help_aux:: @echo "'make "i.tc2text"' to "install tc2text i.tc2text:: tc2text @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTPROGFLAGS) tc2text $(LOCALBINDIR)/tc2text all:: unroff unroff:: unroff.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) unroff.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) unroff help_aux:: @echo "'make "unroff"' to "build the unroff script install:: i.unroff help_aux:: @echo "'make "i.unroff"' to "install unroff i.unroff:: unroff @if [ -d $(LOCALBINDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALBINDIR)); fi $(INSTALL) $(INSTSCRIPTFLAGS) unroff $(LOCALBINDIR)/unroff install:: i.text-specials help_aux:: @echo "'make "i.text-specials"' to "install text-specials i.text-specials:: text-specials @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) text-specials $(LIBDIR)/text-specials install:: i.text-8-specials help_aux:: @echo "'make "i.text-8-specials"' to "install text-8-specials i.text-8-specials:: text-8-specials @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) text-8-specials $(LIBDIR)/text-8-specials # other depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE tc2null.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h tc2null.o: /usr/include/ctype.h /usr/local/include/etm.h tc2null.o: /usr/local/include/memmgr.h .././h/tcread.h .././h/tctbl.h tc2rtf.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h tc2rtf.o: /usr/include/ctype.h /usr/include/string.h tc2rtf.o: /usr/local/include/portlib.h /usr/local/include/etm.h tc2rtf.o: /usr/local/include/memmgr.h .././h/tcgen.h .././h/tcunix.h tc2rtf.o: .././h/tcread.h .././h/tctbl.h tc2rtf.h rtffont.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h rtffont.o: /usr/include/string.h /usr/local/include/etm.h rtffont.o: /usr/local/include/tokenscan.h /usr/local/include/memmgr.h rtffont.o: .././h/tcgen.h .././h/tcread.h tc2rtf.h tc2html.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h tc2html.o: /usr/include/ctype.h /usr/include/string.h tc2html.o: /usr/local/include/portlib.h /usr/local/include/etm.h tc2html.o: /usr/local/include/memmgr.h /usr/local/include/tokenscan.h tc2html.o: .././h/tcgen.h .././h/tcunix.h .././h/tcread.h .././h/tctbl.h tc2html.o: tc2html.h tc2text.o: /usr/include/stdio.h /usr/include/sys/feature_tests.h tc2text.o: /usr/include/ctype.h /usr/include/string.h tc2text.o: /usr/local/include/portlib.h /usr/local/include/etm.h tc2text.o: /usr/local/include/memmgr.h /usr/local/include/tokenscan.h tc2text.o: .././h/tcgen.h .././h/tcunix.h .././h/tcread.h .././h/tctbl.h tcr-fonts"' to "install tcr-fonts i.tcr-fonts:: tcr-fonts @if [ -d $(LIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LIBDIR)); fi $(INSTALL) $(INSTDATFLAGS) tcr-fonts $(LIBDIR)/tcr-fonts # troff2null stuff all:: tc2null help_aux:: @echo "'make "tc2null"' to "build tc2null tc2null: $(NULLOBJtroffcvt-1.04/post/troff2null.pl010066400017710000151000000040350631361134500204420ustar00junkyarddatamgmt00000400000027 # Script type: perl # troff2null - invoke troffcvt preprocessor and tc2null postprocessor # Understands the usual troffcvt and tc2null arguments. In addition, # understands the following options: # -n no execution, just show commands that would be executed # -p don't run the postprocessor tc2null # Adds in redefinition files according to any macro package that is named # in the command-line arguments. For example, if "-ms" is specified on the # command line, troff2null passes "-ms -a tc.ms" to troffcvt. # 17 Mar 97 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 17 Mar 97 V1.00 # - Created. ($prog = $0) =~ s|.*//||; # get script name for messages $troffcvt = "troffcvt"; $postproc = "tc2null"; $noexec = 0; $nopostproc = 0; $preargs = ""; $postargs = ""; while (@ARGV) { $_ = shift (@ARGV); # get next argument if ($_ eq "-n") # recognize and delete -n { $noexec = 1; next; } if ($_ eq "-p") # recognize and delete -p { $nopostproc = 1; next; } if (!/^-./) # not a flag, just a filename or "-" { $preargs .= " $_"; next; } ($opt, $rest) = /^-(.)(.*)/; if ($opt eq "m") # -mxx macro package argument { die "$prog: -m requires macro package name\n" if $rest eq ""; $preargs .= " -m$rest -a 'tc.m$rest'"; next; } if ($opt =~ /^[ACl]$/) # troffcvt arguments that stand alone { $preargs .= " -$opt"; next; } if ($opt =~ /^[adrt]$/) # troffcvt arguments that require an { # additional argument if ($rest eq "") { die "$prog: -$opt requires following argument\n" if @ARGV == 0; $rest = shift (@ARGV); } $preargs .= " -$opt '$rest'"; next; } if ($opt =~ /^[E]$/) # tc2null arguments that stand alone { $postargs .= " -$opt"; next; } warn ("Bad argument: -$opt\n"); } if ($nopostproc) { # basic translation $cmd = "$troffcvt $preargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } else { # basic translation $cmd = "$troffcvt $preargs | $postproc $postargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } exit (0); troffcvt-1.04/post/text-specials010066400017710000151000000034300634137562000205220ustar00junkyarddatamgmt00000400000027# special characters for troffcvt -> text writer # field meaning # ----- ------- # 1 special character name # 2 string to write for name # If string is explicitly empty ("") nothing will be written. This makes # any occurrences of the special character in the input disappear from # the output! (This is useful for things like opthyphen.) # If a special character definition is missing completely, the # character name itself will be written in the form "[[name]]". # This way the character won't be dropped if you forget to define # it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. # name value backslash \\ at @ quoteleft "'" quoteright "'" quotedblleft '"' quotedblright '"' # these are deleted from the output zerospace "" sixthspace "" twelfthspace "" digitspace " " hardspace " " backspace " " emdash -- minus - # don't really know what to do with these yet... fieldbegin "" fieldend "" fieldpad " " leader " " tab " " # want this to disappear opthyphen "" hyphen - bullet * fi fi fl fl ff ff ffi ffi ffl ffl registered "(reg.)" copyright "(c)" trademark "(tm)" plusmath + minusmath - equalmath = asteriskmath * minute "'" numbersign ## second '"' asciicircum ^ asciitilde ~ tilde ~ acute \' grave \` ul _ slash / greaterequal >= lessequal <= arrowright -> arrowleft <- arrowboth <-> arrowdblboth <=> arrowdblleft <= arrowdblright => arrowhorizex -- multiply x divide "/" plusminus "+/-" bar | br | bv | ae ae AE AE oe oe OE OE angleleft < angleright > braceleft { braceright } bracketleft [ bracketright ] circumflex ^ dollar $ endash - ru _ troffcvt-1.04/post/rtf-fonts010066400017710000151000000007010626662671200176640ustar00junkyarddatamgmt00000400000027# map typeface names to RTF names for \fonttbl, for each character set # I don't really know any except the Macintosh names so the others # are a guess. # The typeface names must match those in the tcr-fonts file. # typeface \ansi \mac \pc \pca Times TmsRmn Times TmsRmn TmsRmn Helvetica x Helvetica Helvetica x Courier x Courier Courier x Symbol x Symbol Symbol x Palatino x Palatino Palatino x Bookman x Bookman Bookman x troffcvt-1.04/post/rtf-fonts.orig010066400017710000151000000006430626662671200206300ustar00junkyarddatamgmt00000400000027# map typeface names to RTF names for \fonttbl, for each character set # I don't really know any except the Macintosh names so the others # are a guess. # The typeface names must match those in the tcr-fonts file. # typeface \ansi \mac \pc \pca Times TmsRmn Times TmsRmn TmsRmn Helvetica x Helvetica x x Courier x Courier x x Symbol x Symbol x x Palatino x Palatino x x Bookman x Bookman x x troffcvt-1.04/post/rtf-spec-ansi010066400017710000151000000065300634140115400204040ustar00junkyarddatamgmt00000400000027# ANSI character set special characters for troffcvt -> RTF writer # field meaning # ----- ------- # 1 special character name # 2 rtf string to write for character # Special character names should match those used in the action # file used with troffcvt to generate the input to the RTF writer. # If the name is followed by "/F" then font F will be used to write # the character. # If string is explicitly empty ("") nothing will be written. If # a special character definition is missing completely # the character name itself will be written in the form "[[name]]". # (This is also true if the definition is missing for a particular # character set and output is being written for that set.) This # way the character won't be dropped if you forget to define it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. # This table is woefully incomplete # name \ansi backslash \\\\ at @ # these could be written portably as \lquote, \rquote, \ldblquote, # \rdblquote if certain readers (e.g., WordPerfect) understood those. quoteleft "\\'91" quoteright "\\'92" quotedblleft "\\'93" quotedblright "\\'94" zerospace "" sixthspace "" twelfthspace "" # not really correct digitspace " " hardspace \\~ # backspace emdash "\\'96" minus - # don't really know what to do with these yet... fieldbegin "" fieldend "\\tab " fieldpad "" leader "\\tab " tab "\\tab " # want this to disappear opthyphen "" bullet "\\'95" # square # ru # onequarter # onehalf # threequarters fi fi fl fl ff ff ffi ffi ffl ffl # degree # dagger # minute # cent registered "(reg.)" copyright "(c)" plusmath + minusmath - equalmath = asteriskmath * # section acute \' grave \` ul _ slash / # radical # radicalex greaterequal >= lessequal <= # equivalence # approxequal # similar # notequal # arrowright # arrowleft # arrowup # arrowdown multiply/S "\\'b4" divide/S "/" plusminus "+/-" # union # intersection # propersubset # propersuperset # reflexsubset # reflexsuperset # infinity # partialdiff # gradient # logicalnot # integral # proportional # emptyset # element # br # daggerdbl # handright # handleft # bell # bar # circle # bracelefttp # braceleftbt # bracerighttp # bracerightbt # braceleftmid # bracerightmid # bv # bracketleftbt # bracketrightbt # bracketlefttp # bracketrighttp alpha/S a beta/S b gamma/S g delta/S d epsilon/S e zeta/S z eta/S y theta/S h iota/S i kappa/S k lambda/S l mu/S m nu/S n xi/S c omicron/S o pi/S p rho/S r sigma/S s sigma1/S V tau/S t upsilon/S u phi/S f chi/S x psi/S q omega/S w Alpha/S A Beta/S B Gamma/S G Delta/S D Epsilon/S E Zeta/S Z Eta/S Y Theta/S H Iota/S I Kappa/S K Lambda/S L Mu/S M Nu/S N Xi/S C Omicron/S O Pi/S P Rho/S R Sigma/S S Tau/S T Upsilon/S U Phi/S F Chi/S X Psi/S Q Omega/S W AE AE ae ae angleleft < angleright > arrowboth <-> arrowdblboth <=> arrowdblleft <= arrowdblright => arrowhorizex -- arrowleft <- arrowright -> asciicircum ^ asciitilde ~ bar | br | bv | braceleft { braceright } bracketleft [ bracketright ] circumflex ^ dollar $ endash - hyphen - minute ' numbersign # oe oe quotesingle ' ru _ second '' tilde ~ trademark (tm) will be used to write # the character. # If string is explicitly empty ("") nothing will be written. If # a special character definition is missing completely # the ctroffcvt-1.04/post/rtf-spec-mac010066400017710000151000000103350634140133700202130ustar00junkyarddatamgmt00000400000027# Macintosh character set special characters for troffcvt -> RTF writer # field meaning # ----- ------- # 1 special character name # 2 rtf string to write for character # Special character names should match those used in the action # file used with troffcvt to generate the input to the RTF writer. # If the name is followed by "/F" then font F will be used to write # the character. # If string is explicitly empty ("") nothing will be written. If # a special character definition is missing completely # the character name itself will be written in the form "[[name]]". # (This is also true if the definition is missing for a particular # character set and output is being written for that set.) This # way the character won't be dropped if you forget to define it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. backslash \\\\ at @ # these could be written portably as \lquote, \rquote, \ldblquote, # \rdblquote if certain readers (e.g., WordPerfect) understood those. quoteleft "\\'d4" quoteright "\\'d5" quotedblleft "\\'d2" quotedblright "\\'d3" zerospace "" sixthspace "" twelfthspace "" # not really correct digitspace " " hardspace \\~ # backspace emdash "\\'d1" minus "\\'d0" # don't really know what to do with these yet... fieldbegin "" fieldend "\\tab " fieldpad "" leader "\\tab " tab "\\tab " # want this to disappear opthyphen "" bullet "\\'a5" # square # ru # onequarter # onehalf # threequarters fi fi fl fl ff ff ffi ffi ffl ffl degree "\\'a1" dagger "\\'a0" # minute cent "\\'a2" registered "\\'a8" copyright "\\'a9" plusmath + minusmath - equalmath = asteriskmath * section "\\'a4" acute \' grave \` ul _ slash / # radical # radicalex greaterequal "\\'b3" lessequal "\\'b2" equivalence/S "\\'ba" # approxequal # similar notequal "\\'ad" arrowright/S "\\'ae" arrowleft/S "\\'ac" arrowup/S "\\'ad" arrowdown/S "\\'af" multiply/S "\\'b4" divide/S "\\'b8" plusminus "\\'b1" # union # intersection # propersubset # propersuperset # reflexsubset # reflexsuperset # infinity # partialdiff # gradient # logicalnot # integral # proportional # emptyset # element # br daggerdbl "\\'e0" # handright # handleft # bell # bar # circle # bracelefttp # braceleftbt # bracerighttp # bracerightbt # braceleftmid # bracerightmid # bv # bracketleftbt # bracketrightbt # bracketlefttp # bracketrighttp O-slash "\\'af" o-slash "\\'bf" adieresis "\\'8a" edieresis "\\'91" idieresis "\\'95" odieresis "\\'9a" udieresis "\\'9f" ydieresis "\\'d8" Adieresis "\\'80" Edieresis "\\'e8" Idieresis "\\'ec" Odieresis "\\'85" Udieresis "\\'86" Ydieresis "\\'d9" aacute "\\'87" eacute "\\'8e" iacute "\\'92" oacute "\\'97" uacute "\\'9c" yacute "\\'08" Aacute "\\'e7" Eacute "\\'83" Iacute "\\'ea" Oacute "\\'ee" Uacute "\\'f2" Yacute "\\'07" agrave "\\'88" egrave "\\'8f" igrave "\\'93" ograve "\\'98" ugrave "\\'9d" Agrave "\\'cb" Egrave "\\'e9" Igrave "\\'ed" Ograve "\\'f1" Ugrave "\\'f4" acircumflex "\\'89" ecircumflex "\\'90" icircumflex "\\'94" ocircumflex "\\'99" ucircumflex "\\'9e" Acircumflex "\\'e5" Ecircumflex "\\'e6" Icircumflex "\\'eb" Ocircumflex "\\'ef" Ucircumflex "\\'f3" ntilde "\\'96" alpha/S a beta/S b gamma/S g delta/S d epsilon/S e zeta/S z eta/S y theta/S h iota/S i kappa/S k lambda/S l mu/S m nu/S n xi/S c omicron/S o pi/S p rho/S r sigma/S s sigma1/S V tau/S t upsilon/S u phi/S f chi/S x psi/S q omega/S w Alpha/S A Beta/S B Gamma/S G Delta/S D Epsilon/S E Zeta/S Z Eta/S Y Theta/S H Iota/S I Kappa/S K Lambda/S L Mu/S M Nu/S N Xi/S C Omicron/S O Pi/S P Rho/S R Sigma/S S Tau/S T Upsilon/S U Phi/S F Chi/S X Psi/S Q Omega/S W AE AE ae ae angleleft < angleright > arrowboth <-> arrowdblboth <=> arrowdblleft <= arrowdblright => arrowhorizex -- asciicircum ^ asciitilde ~ bar | br | bv | braceleft { braceright } bracketleft [ bracketright ] circumflex ^ dollar $ endash - hyphen - minute ' numbersign # oe oe quotesingle ' ru _ second '' tilde ~ trademark (tm) troffcvt-1.04/post/rtf-spec-pc010066400017710000151000000064640634140116700200660ustar00junkyarddatamgmt00000400000027# PC character set special characters for troffcvt -> RTF writer # field meaning # ----- ------- # 1 special character name # 2 rtf string to write for character # Special character names should match those used in the action # file used with troffcvt to generate the input to the RTF writer. # If the name is followed by "/F" then font F will be used to write # the character. # If string is explicitly empty ("") nothing will be written. If # a special character definition is missing completely # the character name itself will be written in the form "[[name]]". # (This is also true if the definition is missing for a particular # character set and output is being written for that set.) This # way the character won't be dropped if you forget to define it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. # This table is woefully incomplete # name \ansi backslash \\\\ at @ # these could be written portably as \lquote, \rquote, \ldblquote, # \rdblquote if certain readers (e.g., WordPerfect) understood those. quoteleft \` quoteright \' quotedblleft \" quotedblright \" zerospace "" sixthspace "" twelfthspace "" # not really correct digitspace " " hardspace \\~ # backspace emdash - minus - # don't really know what to do with these yet... fieldbegin "" fieldend "\\tab " fieldpad "" leader "\\tab " tab "\\tab " # want this to disappear opthyphen "" # bullet # square # ru # onequarter # onehalf # threequarters fi fi fl fl ff ff ffi ffi ffl ffl # degree # dagger # minute # cent registered "(reg.)" copyright "(c)" plusmath + minusmath - equalmath = asteriskmath * # section acute \' grave \` ul _ slash / # radical # radicalex greaterequal >= lessequal <= # equivalence # approxequal # similar # notequal # arrowright # arrowleft # arrowup # arrowdown multiply/S "\\'b4" divide/S "/" plusminus "+/-" # union # intersection # propersubset # propersuperset # reflexsubset # reflexsuperset # infinity # partialdiff # gradient # logicalnot # integral # proportional # emptyset # element # br # daggerdbl # handright # handleft # bell # bar # circle # bracelefttp # braceleftbt # bracerighttp # bracerightbt # braceleftmid # bracerightmid # bv # bracketleftbt # bracketrightbt # bracketlefttp # bracketrighttp alpha/S a beta/S b gamma/S g delta/S d epsilon/S e zeta/S z eta/S y theta/S h iota/S i kappa/S k lambda/S l mu/S m nu/S n xi/S c omicron/S o pi/S p rho/S r sigma/S s sigma1/S V tau/S t upsilon/S u phi/S f chi/S x psi/S q omega/S w Alpha/S A Beta/S B Gamma/S G Delta/S D Epsilon/S E Zeta/S Z Eta/S Y Theta/S H Iota/S I Kappa/S K Lambda/S L Mu/S M Nu/S N Xi/S C Omicron/S O Pi/S P Rho/S R Sigma/S S Tau/S T Upsilon/S U Phi/S F Chi/S X Psi/S Q Omega/S W AE AE ae ae angleleft < angleright > arrowboth <-> arrowdblboth <=> arrowdblleft <= arrowdblright => arrowhorizex -- arrowleft <- arrowright -> asciicircum ^ asciitilde ~ bar | br | bv | braceleft { braceright } bracketleft [ bracketright ] circumflex ^ dollar $ endash - hyphen - minute ' numbersign # oe oe quotesingle ' ru _ second '' tilde ~ trademark (tm) troffcvt-1.04/post/rtf-spec-pca010066400017710000151000000064640634140117400202250ustar00junkyarddatamgmt00000400000027# PCA character set special characters for troffcvt -> RTF writer # field meaning # ----- ------- # 1 special character name # 2 rtf string to write for character # Special character names should match those used in the action # file used with troffcvt to generate the input to the RTF writer. # If the name is followed by "/F" then font F will be used to write # the character. # If string is explicitly empty ("") nothing will be written. If # a special character definition is missing completely # the character name itself will be written in the form "[[name]]". # (This is also true if the definition is missing for a particular # character set and output is being written for that set.) This # way the character won't be dropped if you forget to define it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. # This table is woefully incomplete # name \ansi backslash \\\\ at @ # these could be written portably as \lquote, \rquote, \ldblquote, # \rdblquote if certain readers (e.g., WordPerfect) understood those. quoteleft \` quoteright \' quotedblleft \" quotedblright \" zerospace "" sixthspace "" twelfthspace "" # not really correct digitspace " " hardspace \\~ # backspace emdash - minus - # don't really know what to do with these yet... fieldbegin "" fieldend "\\tab " fieldpad "" leader "\\tab " tab "\\tab " # want this to disappear opthyphen "" # bullet # square # ru # onequarter # onehalf # threequarters fi fi fl fl ff ff ffi ffi ffl ffl # degree # dagger # minute # cent registered "(reg.)" copyright "(c)" plusmath + minusmath - equalmath = asteriskmath * # section acute \' grave \` ul _ slash / # radical # radicalex greaterequal >= lessequal <= # equivalence # approxequal # similar # notequal # arrowright # arrowleft # arrowup # arrowdown multiply/S "\\'b4" divide/S "/" plusminus "+/-" # union # intersection # propersubset # propersuperset # reflexsubset # reflexsuperset # infinity # partialdiff # gradient # logicalnot # integral # proportional # emptyset # element # br # daggerdbl # handright # handleft # bell # bar # circle # bracelefttp # braceleftbt # bracerighttp # bracerightbt # braceleftmid # bracerightmid # bv # bracketleftbt # bracketrightbt # bracketlefttp # bracketrighttp alpha/S a beta/S b gamma/S g delta/S d epsilon/S e zeta/S z eta/S y theta/S h iota/S i kappa/S k lambda/S l mu/S m nu/S n xi/S c omicron/S o pi/S p rho/S r sigma/S s sigma1/S V tau/S t upsilon/S u phi/S f chi/S x psi/S q omega/S w Alpha/S A Beta/S B Gamma/S G Delta/S D Epsilon/S E Zeta/S Z Eta/S Y Theta/S H Iota/S I Kappa/S K Lambda/S L Mu/S M Nu/S N Xi/S C Omicron/S O Pi/S P Rho/S R Sigma/S S Tau/S T Upsilon/S U Phi/S F Chi/S X Psi/S Q Omega/S W AE AE ae ae angleleft < angleright > arrowboth <-> arrowdblboth <=> arrowdblleft <= arrowdblright => arrowhorizex -- arrowleft <- arrowright -> asciicircum ^ asciitilde ~ bar | br | bv | braceleft { braceright } bracketleft [ bracketright ] circumflex ^ dollar $ endash - hyphen - minute ' numbersign # oe oe quotesingle ' ru _ second '' tilde ~ trademark (tm) troffcvt-1.04/post/tcr-fonts010066400017710000151000000022610626662671300176650ustar00junkyarddatamgmt00000400000027# troffcvt reader font information - modify on per-site basis # This is used to map troff font names (which vary quite a bit, # depending on what's locally available) to a more abstract form # which should be more stable, and can be extended without modifying # the reader or postprocessors. # field meaning # ----- ------- # 1 troff font name # 2 typeface name (family of which font is a member) # 3 attributes of font, relative to plain font in typeface # First typeface family listed should probably be the default # font. # *X fonts added by Dave Davey R Times I Times italic B Times bold BI Times bold italic H Helvetica HR Helvetica # oblique/italic are same font in helv. HI Helvetica italic HO Helvetica italic HB Helvetica bold HX Helvetica bold italic C Courier CW Courier CR Courier CI Courier italic CO Courier italic CB Courier bold CX Courier bold italic S Symbol PR Palatino PI Palatino italic PB Palatino bold PX Palatino bold italic # xroff uses "Liberal" to mean Times, "Malibu" for Palatino LR Times LI Times italic LB Times bold MR Palatino MI Palatino italic MB Palatino bold K Bookman KR Bookman KO Bookman italic KB Bookman bold KX Bookman bold italic troffcvt-1.04/post/unroff.pl010066400017710000151000000040360634070172700176510ustar00junkyarddatamgmt00000400000027 # Script type: perl # unroff - invoke troffcvt preprocessor and tc2text postprocessor # Understands the usual troffcvt and tc2text arguments. In addition, # understands the following options: # -n no execution, just show commands that would be executed # -p don't run the postprocessor tc2text # Adds in redefinition files according to any macro package that is named # in the command-line arguments. For example, if "-ms" is specified on the # command line, unroff passes "-ms -a tc.ms" to troffcvt. # 17 Mar 97 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 17 Mar 97 V1.00 # - Created. ($prog = $0) =~ s|.*//||; # get script name for messages $troffcvt = "troffcvt"; $postproc = "tc2text"; $noexec = 0; $nopostproc = 0; $preargs = "-tnroff"; $postargs = ""; while (@ARGV) { $_ = shift (@ARGV); # get next argument if ($_ eq "-n") # recognize and delete -n { $noexec = 1; next; } if ($_ eq "-p") # recognize and delete -p { $nopostproc = 1; next; } if (!/^-./) # not a flag, just a filename or "-" { $preargs .= " $_"; next; } ($opt, $rest) = /^-(.)(.*)/; if ($opt eq "m") # -mxx macro package argument { die "$prog: -m requires macro package name\n" if $rest eq ""; $preargs .= " -m$rest -a 'tc.m$rest'"; next; } if ($opt =~ /^[ACl]$/) # troffcvt arguments that stand alone { $preargs .= " -$opt"; next; } if ($opt =~ /^[adrt]$/) # troffcvt arguments that require an { # additional argument if ($rest eq "") { die "$prog: -$opt requires following argument\n" if @ARGV == 0; $rest = shift (@ARGV); } $preargs .= " -$opt '$rest'"; next; } if ($opt =~ /^[EJ8]$/) # tc2text arguments that stand alone { $postargs .= " -$opt"; next; } warn ("Bad argument: -$opt\n"); } if ($nopostproc) { # basic translation $cmd = "$troffcvt $preargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } else { # basic translation $cmd = "$troffcvt $preargs | $postproc $postargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } exit (0); troffcvt-1.04/post/tc2html.c010066400017710000151000001445250634113621400175400ustar00junkyarddatamgmt00000400000027/* * - Empty and line-drawing cells might span, but that's not handled. * - Need to handle table cell spacing. But that's a table attribute in * HTML and a column attribute in tbl. * - Perhaps tags to use for headers should be read from file to allow * better user-level style configuration. * - SetCFA() doesn't do much with center/adjust interaction. * - Need a FileInfo() equivalent here for error messages. * - Need to set initial style when the body starts? * - Wrapper needs function to call during loop and termination value * to look for. * - Size changes - ignore in title? * - Should be able to override the fonts file, both at compile time, and * from the command line. Of course, since fonts are currently ignored, * this doesn't matter much yet. */ /* * tc2html - read troffcvt output, convert to HTML * * Syntax: tc2html [-D] [-E] [-T title] [file] ... * * -D enable debug code * -E echo tokens as they are read * -T specify document title * * The main trick for this postprocessor is to get troffcvt to write * output that's useful for determining where HTML entities like titles, * paragraphs, and lists begin and/or end. For figuring out these * higher-level constructs, it doesn't do much good to know just * low-level things like breaks and font changes. The way to do this * is to use an action file with troffcvt that maps macro calls to * "\html xxx" lines, where xxx is an HTML entity name. * * 03 Jan 97 Paul DuBois dubois@primate.wisc.edu * * 03 Jan 97 * - Created */ #include #include #ifndef STRING_H #define STRING_H #endif #include STRING_H #include "portlib.h" #include "etm.h" #include "memmgr.h" #include "tokenscan.h" #include "tcgen.h" #include "tcunix.h" #include "tcread.h" #include "tctbl.h" #include "tc2html.h" static void WriterInit (void); static int BeginFile (void); static void ReadFile (void); static void ControlLine (void); static void SetFont (char *name, short inDisplay); static void SetCFA (short newCenter, short newFill, short newAdjust); static void PlainText (void); static void SpecialText (void); static void ResetTabs (void); static void SetTabStop (long pos, char type); static int ReadSpecials (char *filename); static SpChar *LookupSpecial (char *name); static KeyMap *LookupKey (char *p); static void DoAnchor (short newAnchor, short argc, char **argv); static void DoElement (short newElt, short argc, char **argv); static void BeginDocHead (void); static void BeginDocBody (void); static void TerminateDefList (void); static void FlushTOC (void); static void PushElt (short eltType, short misc); static void PopElt (void); static void AddBreak (void); static void AddPara (void); static void AddLine (long length, short direction); static void AddStr (char *p); static void AddLitStr (char *p); static void AddChar (char c); static void AddTitleChar (char c); static void AddHeaderChar (char c); static void AddTOCChar (char c); static void StrAddStr (char *buf, int size, char *str); static void TableBegin (short argc, char **argv); static void TableEnd (void); static void TableRowBegin (short argc, char **argv); static void TableRowEnd (void); static void TableRowLine (short argc, char **argv); static void TableCellInfo (short argc, char **argv); static void TableCellBegin (short argc, char **argv); static void TableCellEnd (void); static void TableEmptyCell (void); static void TableSpannedCell (void); static void TableCellLine (short argc, char **argv); static void CellBegin (char type, short vspan, short hspan, char vadjust); static void ControlOut (char *p, short brkBefore, short brkAfter); static void TextStrOut (char *p); static void TextChOut (int c); static void HTMLChOut (char *p); static void StrOut (char *p); static void ChOut (int c); static void Flush (void); static char *CharToHTML (int c); static int AllowOutput (int yesno); static int ReadFonts (char *filename); static Font *LookupFont (char *name); static KeyMap keyMap[] = { { "anchor-href", keyAnchor, anchorHref }, { "anchor-name", keyAnchor, anchorName }, { "anchor-toc", keyAnchor, anchorTOC }, { "anchor-end", keyAnchor, anchorEnd }, { "title", keyElement, eltTitle }, { "para", keyElement, eltPara }, { "display", keyElement, eltDisplay }, { "display-end", keyElement, eltDisplayEnd }, { "display-indent", keyElement, eltDisplayIndent }, { "list", keyElement, eltList }, { "list-end", keyElement, eltListEnd }, { "list-item", keyElement, eltListItem }, { "header", keyElement, eltHeader }, { "header-end", keyElement, eltHeaderEnd }, { "blockquote", keyElement, eltBlockquote }, { "blockquote-end", keyElement, eltBlockquoteEnd }, { "definition-term", keyElement, eltDefTerm }, { "definition-desc", keyElement, eltDefDesc }, { "shift-right", keyElement, eltShiftRight }, { "shift-left", keyElement, eltShiftLeft }, { NULL, keyUnknown, 0 } }; static int allowOutput = 1; /* zero if output is throttled */ static long resolution = 432; /* * cCount is the number of characters on the current output line. It's * incremented at the lowest output level, in ChOut(). tCount is the number * of text (non-tag) characters on the line. It's used to determine when to * ignore leading spaces in TextChOut(). (Ignore when character to write * is a space and tCount is zero.) etCount is the "effective" number of * text characters on a line. For instance, ">" is written as ">" -- this * increments tCount by 4, but etCount by only 1. etCount is needed for * doing spacing for tabstops. */ static int cCount = 0; static int tCount = 0; static int etCount = 0; static Font *fontList = (Font *) NULL; static Font *curFont = (Font *) NULL; static SpChar *spList = (SpChar *) NULL; static int debug = 0; static int echo = 0; /* * docPart indicates which part of the document is being collected: * - inHead = document HEAD part * - inBody = document BODY part * - inNone = uninitialized * * bodyElt indicates which body element is being collected. It's * irrelevant unless docPart is inBody. * * If output is ready to be written while docPart is inNone, the part is * initialized to inBody, using the default element of "generic paragraph." */ static short docPart = inNone; static short bodyElt = eltUnknown; static Elt eltStack[maxElt]; /* element stack */ static short eltTop = -1; /* initially stack is empty */ static short listDepth = 0; /* list nesting depth */ static short displayFlag = 0; /* non-zero if in display */ static short displayIndent = 0; /* display indent */ static short blockquoteFlag = 0; /* non-zero if in block quote */ static short anchorFlag = 0; /* non-zero if in (turned on */ /* by ahref, aname, or atoc) */ /* * This is non-NULL is an an href anchor is pending (collected from the * input but not yet output). This is used to "float" an anchor past any * whitespace that may follow it to the next non-white character. (The * reason this is done is to avoid leading underlined whitespace, which is * ugly.) */ static char *pendingAnchor = (char *) NULL; /* * Table-of-contents stuff */ static TOC *tocHead = (TOC *) NULL; /* list of TOC entries */ static TOC *tocTail = (TOC *) NULL; static char tocBuf[maxTOC] = ""; /* text of current TOC entry */ static short tocCount = 0; /* TOC entry index */ static short tocLevel = 0; /* level of current entry */ /* * Title text is saved in a buffer because it's used both for the document * title in the document head and for the initial heading in the document * body. When tc2html detects that the document head -> document body * transition has been crossed, it writes the document head, writes the * beginning of the document body, and writes the initial header. * * Text intended for other structural elements of the body is written to the * output as soon as it has been seen. * * cmdLineTitle is non-null if a -T option is given on the command line to * override any document title found in the document. (Mainly useful when * NO title is present in the document.) */ static char title[maxTitle] = ""; static char header[maxHeader] = ""; static char *cmdLineTitle = (char *) NULL; /* * Definition-list stuff. Definition lists are terminated implicitly * by most structural markers except definition-list markers themselves. * * defListFlag values: * 0 not in a definition list * 1 collecting a term * 2 collecting a description * * emptyDefTerm is used during definition term collection to specify whether * or not any text has been found in the term. If not, then a
is written * when the term is closed to force a little whitespace. */ static short defListFlag = 0; static short emptyDefTerm = 0; /* right/left shift level */ static short shiftLevel = 0; /* * Per-table values */ static short tblCols = 0; /* number of columns in table */ static short tblRows = 0; /* number of rows in table */ static short centerTbl= 0; /* non-zero if table is centered */ /* * Per-cell values. */ static char cellType[tblMaxCol]; /* cell type */ static short cellVSpan[tblMaxCol]; /* cell vspan flag */ static short cellHSpan[tblMaxCol]; /* cell hspan extent */ static char cellVAdjust[tblMaxCol]; /* cell vertical adjust */ static short cellBorder[tblMaxCol]; /* cell borders */ /* * Counters for keeping track of position within table. * tblColIdx counts horizontally during processing of \table-column-info * lines, during \table-cell-info lines, and while processing each row of * table data. tblRowIdx counts rows of table data. */ static short tblColIdx = 0; static short tblRowIdx = 0; static short adjust = adjLeft; /* line adjustment mode */ static short fill = 0; /* non-zero if fill mode on */ static short center = 0; /* non-zero if centering on */ static short underline = 0; /* non-zero if underlining on */ static short tabPos[maxTabStops]; static char tabType[maxTabStops]; static short tabCount = 0; int main (int argc, char *argv[]) { int inc; ETMInit (NULL); UnixSetProgPath (argv[0]); TCRSetOpenLibFileProc (UnixOpenLibFile); --argc; ++argv; while (argc > 0 && argv[0][0] == '-') { inc = 1; if (strcmp (argv[0], "-D") == 0) debug = 0xffff; else if (strcmp (argv[0], "-E") == 0) echo = 1; else if (strncmp (argv[0], "-T", 2) == 0) { if (argv[0][2] != '\0') /* -Ttitle */ cmdLineTitle = &argv[0][2]; else if (argc < 1) ETMPanic ("Missing title after -T"); else { cmdLineTitle = argv[1]; argc -= inc; argv += inc; } } else ETMPanic ("Unknown option: %s", argv[0]); argc -= inc; argv += inc; } if (debug || echo) { /* don't want output order mixed up by buffering */ setbuf (stdout, (char *) NULL); setbuf (stderr, (char *) NULL); } WriterInit (); if (argc > 1) ETMPanic ("Only one input file allowed"); if (argc == 0) /* stdin */ ReadFile (); else { if (freopen (argv[0], "r", stdin) == (FILE *) NULL) ETMMsg ("Cannot open: %s", argv[0]); else ReadFile (); } ETMEnd (); exit (0); /*NOTREACHED*/ } static void WriterInit (void) { if (!ReadFonts (defaultFontFile)) ETMPanic ("cannot find %s file", defaultFontFile); if (!ReadSpecials (specialCharFile)) ETMPanic ("cannot find %s file", specialCharFile); } static int BeginFile (void) { (void) AllowOutput (1); ControlOut ("HTML", 1, 1); ControlOut ("!-- this file was generated by troffcvt and tc2html --", 1, 1); /* initialize font info to initial font */ /*SetFont ("R", 0);*/ (void) AllowOutput (0); TCRInit (); return (1); } static void ReadFile (void) { int i; (void) BeginFile (); while (TCRGetToken () != tcrEOF) { if (echo) { ETMMsg ("class %d maj %d min %d <%s>", tcrClass, tcrMajor, tcrMinor, tcrArgv[0]); if (tcrClass == tcrControl || tcrClass == tcrSText) { for (i = 1; i < tcrArgc; i++) ETMMsg ("\t<%s>", tcrArgv[i]); } } switch (tcrClass) { case tcrControl: ControlLine (); break; case tcrText: PlainText (); break; case tcrSText: SpecialText (); break; default: ETMPanic ("ReadFile: unknown token %d <%s>", tcrClass, tcrArgv[0]); } } /* * If document contains HEAD part only, write a fake paragraph * to force HEAD flush */ if (docPart == inHead) DoElement (eltPara, 0, (char **) NULL); /* * Terminate final font setting * Close any dangling style attributes * Close any dangling anchor * Close any open definition list * Undo any pending right shifts * Close any open BODY elements * Flush table of contents if there is one * Close document BODY part */ if (docPart == inBody) { if (curFont != (Font *) NULL) StrOut (curFont->endTag); if (underline) ControlOut ("/UNDER", 1, 1); if (anchorFlag) DoAnchor (anchorEnd, 0, (char **) NULL); TerminateDefList (); while (shiftLevel-- > 0) ControlOut ("/UL", 1, 1); while (eltTop >= 0) PopElt (); SetCFA (0, 1, adjLeft); FlushTOC (); ControlOut ("/BODY", 1, 1); } ControlOut ("/HTML", 1, 1); } /* * Read special character list. Each line has the character name * and the HTML string to write out for a given special character. */ static int ReadSpecials (char *filename) { FILE *f; char buf[bufSiz]; SpChar *sp; char *name, *value; if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) return (0); while (TCRGetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') continue; TSScanInit (buf); if ((name = TSScan ()) == (char *) NULL) /* char name */ continue; value = TSScan (); /* NULL if missing */ sp = New (SpChar); sp->spName = StrAlloc (name); /* * If value missing, make NULL; this will cause writer * to write "[[name]]" instead of dropping it. */ if (value == (char *) NULL) sp->spValue = (char *) NULL; else sp->spValue = StrAlloc (value); sp->spNext = spList; spList = sp; } (void) fclose (f); return (1); } static SpChar * LookupSpecial (char *name) { SpChar *sp; for (sp = spList; sp != (SpChar *) NULL; sp = sp->spNext) { if (strcmp (name, sp->spName) == 0) break; } return (sp); /* NULL if not found */ } static KeyMap * LookupKey (char *p) { KeyMap *kp; for (kp = keyMap; kp->name != (char *) NULL; kp++) { if (strcmp (p, kp->name) == 0) return (kp); } return ((KeyMap *) NULL); } static void ControlLine (void) { KeyMap *kp; char buf[bufSiz]; short newCenter, newFill, newAdjust; double d; switch (tcrMajor) { default: ETMMsg ("ControlLine: bad control major code: %d <%s>", tcrMajor, tcrArgv[0]); break; case tcrCUnknown: /* * Special \html controls are handled here */ if (strcmp (tcrArgv[0], "\\html") == 0) { kp = LookupKey (tcrArgv[1]); if (kp == (KeyMap *) NULL) ETMMsg ("unknown \\html key: %s", tcrArgv[1]); else { switch (kp->type) { default: ETMPanic ("ControlLine: logic error"); case keyAnchor: DoAnchor (kp->subtype, tcrArgc - 2, &tcrArgv[2]); break; case keyElement: DoElement (kp->subtype, tcrArgc - 2, &tcrArgv[2]); break; } } } else { ETMMsg ("ControlLine: unknown control token: <%s>", tcrArgv[0]); } break; case tcrComment: break; case tcrSetupBegin: break; case tcrResolution: resolution = StrToLong (tcrArgv[1]); break; case tcrSetupEnd: (void) AllowOutput (1); break; case tcrInputLine: break; case tcrPass: /* * \pass lines indicate information that should be passed * straight through to the output */ Flush (); StrOut (tcrArgv[1]); Flush (); break; case tcrOther: break; case tcrBreak: AddBreak (); break; case tcrCFA: newCenter = center; newFill = fill; newAdjust = adjust; switch (tcrMinor) { case tcrNofill: newFill = 0; break; case tcrCenter: newCenter = 1; break; case tcrAdjFull: case tcrAdjLeft: newCenter = 0; newFill = 1; newAdjust = adjLeft; break; case tcrAdjRight: newCenter = 0; newFill = 1; newAdjust = adjRight; break; case tcrAdjCenter: newCenter = 1; break; } SetCFA (newCenter, newFill, newAdjust); break; case tcrPageLength: break; case tcrPageNumber: break; case tcrFont: if (tcrArgc < 2) ETMMsg ("missing font on \\font line"); else SetFont (tcrArgv[1], displayFlag); break; case tcrPointSize: break; case tcrSpacing: break; case tcrLineSpacing: break; case tcrOffset: break; case tcrIndent: break; case tcrTempIndent: break; case tcrLineLength: break; case tcrTitleLength: break; case tcrTitleBegin: break; case tcrTitleEnd: break; case tcrSpace: /* * For multi-line spacing, put out
's for all but last * line. If the spacing amount is less than a full line, * ignore it. * * Assume 6 lines/inch in the calculation below. */ d = (StrToDouble (tcrArgv[1]) * 6.0 ) / resolution; while (d > 1) { AddBreak; --d; } if (d >= 1) AddPara(); break; case tcrUnderline: break; case tcrCUnderline: break; case tcrNoUnderline: break; case tcrULineFont: break; case tcrBracketBegin: AddStr ("BRACKET>"); break; case tcrBreakSpread: break; case tcrExtraSpace: break; case tcrLine: AddLine (StrToLong (tcrArgv[1]), tcrArgv[2][0]); break; case tcrMark: break; case tcrMotion: break; case tcrBeginOverstrike: AddStr ("OVERSTRIKE>"); break; case tcrBeginPage: AddPara (); break; case tcrZeroWidth: break; case tcrSpaceSize: break; case tcrConstantWidth: break; case tcrNoConstantWidth: break; case tcrNeed: break; case tcrEmbolden: break; case tcrSEmbolden: break; case tcrResetTabs: ResetTabs (); break; case tcrFirstTab: ResetTabs (); /* fall through... */ case tcrNextTab: SetTabStop (StrToLong (tcrArgv[1]), tcrArgv[2][0]); break; case tcrHyphenate: break; case tcrDiversionBegin: break; case tcrDiversionAppend: break; case tcrDiversionEnd: break; case tcrTabChar: break; case tcrLeaderChar: break; case tcrTableBegin: TableBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrTableEnd: TableEnd (); break; case tcrColumnInfo: /* ignore this */ break; case tcrRowBegin: TableRowBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrRowEnd: TableRowEnd (); break; case tcrRowLine: TableRowLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellInfo: TableCellInfo (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellBegin: TableCellBegin (tcrArgc - 1, &tcrArgv[1]); break; case tcrCellEnd: TableCellEnd (); break; case tcrCellLine: TableCellLine (tcrArgc - 1, &tcrArgv[1]); break; case tcrEmptyCell: TableEmptyCell (); break; case tcrSpannedCell: TableSpannedCell (); break; } } static void ResetTabs (void) { tabCount = 0; } static void SetTabStop (long pos, char type) { if (tabCount >= maxTabStops) { ETMMsg ("too many tabstops"); return; } /* * Assume charsPerInch characters/inch */ tabPos[tabCount] = (pos * charsPerInch) / resolution; tabType[tabCount] = type; ++tabCount; } /* * Set the font. The tags to use depend on whether or not we're currently * in a display. */ static void SetFont (char *name, short inDisplay) { Font *fp; /* do nothing if font hasn't changed */ if (curFont != (Font *) NULL && strcmp (curFont->fontName, name) == 0 && curFont->inDisplay == inDisplay) return; if (docPart == inHead) /* ignore title font changes */ return; if (docPart == inNone) /* part unknown - set to default */ DoElement (eltPara, 0, (char **) NULL); if ((fp = LookupFont (name)) == (Font *) NULL) { ETMMsg ("no info for font <%s>", name); return; } /* turn off previous font, if one is known */ if (curFont != (Font *) NULL) { if (!curFont->inDisplay) StrOut (curFont->endTag); else StrOut (curFont->dispEndTag); } /* switch to new font and turn it on */ curFont = fp; curFont->inDisplay = inDisplay; if (!curFont->inDisplay) StrOut (curFont->beginTag); else StrOut (curFont->dispBeginTag); } static void SetCFA (short newCenter, short newFill, short newAdjust) { char buf[bufSiz]; if (docPart == inNone) /* just remember values, no output */ { center = newCenter; fill = newFill; adjust = newAdjust; return; } buf[0] = '\0'; if (center && !newCenter) /* turn off centering */ (void) strcat (buf, ""); if (!center && newCenter) /* turn on centering */ (void) strcat (buf, "
"); center = newCenter; fill = newFill; adjust = newAdjust; if (buf[0] == '\0') /* no output to write */ return; switch (docPart) { default: ETMPanic ("SetCFA: logic error"); case inHead: StrAddStr (header, sizeof (header), buf); break; case inBody: Flush (); StrOut (buf); Flush (); break; } } static void PlainText (void) { /* * Line breaks are indicated explicitly by \break, so ignore * linefeeds. */ if (tcrMajor != lf) { if (docPart == inNone) /* part unknown - set to default */ DoElement (eltPara, 0, (char **) NULL); AddChar (tcrMajor); } } static void SpecialText (void) { SpChar *sp; char buf[bufSiz]; if (docPart == inNone) /* part unknown - set to default */ DoElement (eltPara, 0, (char **) NULL); if ((sp = LookupSpecial (&tcrArgv[0][1])) == (SpChar *) NULL || sp->spValue == (char *) NULL) { sprintf (buf, "[[%s]]", &tcrArgv[0][1]); AddStr (buf); } else AddLitStr (sp->spValue); } /* * Have a new anchor tag */ static void DoAnchor (short newAnchor, short argc, char **argv) { TOC *tp; char buf[bufSiz]; short misc; if (!allowOutput) return; if (newAnchor == anchorUnknown) /* can't tell what to do, */ return; /* so do nothing */ if (docPart == inNone) /* part unknown - set to default */ DoElement (eltPara, 0, (char **) NULL); switch (newAnchor) { case anchorHref: if (argc == 0) { ETMMsg ("problem: missing anchor link text"); break; } if (anchorFlag) { ETMMsg ("problem: nested anchor, ignored"); break; } sprintf (buf, "", argv[0]); switch (docPart) { default: ETMPanic ("DoAnchor: logic error 1"); case inHead: StrAddStr (header, sizeof (header), buf); StrAddStr (header, sizeof (header), "\n"); break; case inBody: pendingAnchor = StrAllocNP (buf); if (pendingAnchor == (char *) NULL) ETMPanic ("DoAnchor: cannot allocate anchor"); break; } anchorFlag = 1; break; case anchorName: if (argc == 0) { ETMMsg ("problem: missing anchor name text"); break; } if (anchorFlag) { ETMMsg ("problem: nested anchor, ignored"); break; } sprintf (buf, "", argv[0]); switch (docPart) { default: ETMPanic ("DoAnchor: logic error 2"); case inHead: StrAddStr (header, sizeof (header), buf); StrAddStr (header, sizeof (header), "\n"); break; case inBody: Flush (); StrOut (buf); Flush (); break; } anchorFlag = 1; break; case anchorTOC: if (argc == 0) { ETMMsg ("problem: TOC entry with no level found, ignored"); break; } if (anchorFlag) { ETMMsg ("problem: nested anchor, ignored"); break; } /* * Set up to collect the text and allocate a TOC strutcure. * Terminate any current definition list; this assumes a * TOC entry won't meaningfully occur in the middle of such. */ TerminateDefList (); tocBuf[0] = '\0'; tp = (TOC *) AllocNP (sizeof (TOC)); tp->tocNext = (TOC *) NULL; tp->tocStr = (char *) NULL; if (tp == (TOC *) NULL) ETMPanic ("DoAnchor: cannot allocate TOC entry"); tocLevel = StrToShort (argv[0]); if (tocLevel < 1) tocLevel = 1; tp->tocLevel = tocLevel; if (tocHead == (TOC *) NULL) tocHead = tp; else tocTail->tocNext = tp; tocTail = tp; sprintf (buf, "", ++tocCount); switch (docPart) { default: ETMPanic ("DoAnchor: logic error 3"); case inHead: StrAddStr (header, sizeof (header), buf); StrAddStr (header, sizeof (header), "\n"); break; case inBody: Flush (); StrOut (buf); Flush (); break; } anchorFlag = 1; break; case anchorEnd: if (!anchorFlag) { ETMMsg ("problem: unbalanced anchor-end, ignored"); break; } switch (docPart) { default: ETMPanic ("DoAnchor: logic error 4"); case inHead: StrAddStr (header, sizeof (header), "\n"); break; case inBody: /* * If there is a pending anchor here, there will be * an empty sequence; warn about it. */ if (pendingAnchor != (char *) NULL) ETMMsg ("problem: empty HREF anchor"); ControlOut ("/A", 0, 0); break; } /* If tocLevel > 0, we were collecting a TOC entry */ if (tocLevel > 0) { if (tocBuf[0] == '\0') ETMMsg ("problem: empty TOC entry"); tocTail->tocStr = StrAllocNP (tocBuf); if (tocTail->tocStr == (char *) NULL) ETMPanic ("DoAnchor: cannot allocate TOC entry text"); tocLevel = 0; } anchorFlag = 0; break; } } /* * Begin a new HTML element. newElt is the type of element, and argc * and argv are the rest of the argument vector from the \html input * line. * * This has to detect structured element changes, shut down any current * element that's being collected that no longer is, and open up any element * that's now being collected that wasn't before. * * When the document head -> document body transition is crossed, flush the * document title and initial header. */ static void DoElement (short newElt, short argc, char **argv) { short misc; if (!allowOutput) return; if (newElt == eltUnknown) /* can't tell what to do, */ return; /* so do nothing */ /* * First check for title -- it's the only HEAD element. If it's * present, this will cause the document HEAD part to contain a * title and the text will also be used for the initial BODY part * heading. */ if (newElt == eltTitle) { switch (docPart) { default: ETMPanic ("DoElement: logic error 1"); case inNone: BeginDocHead (); docPart = inHead; break; case inHead: /* title occurred after one was already seen */ ETMMsg ("multiple titles found?"); break; case inBody: /* title occurred after body began? */ ETMMsg ("out of place title found"); break; } return; } /* * All other elements are BODY elements. If new element is the * first body element we've seen, the HEAD part needs to be flushed * and the BODY part needs to begin. Shove a paragraph element on * the stack right away to make sure the element stack is non-empty; * this eliminates a lot of checking against that condition later. */ if (docPart != inBody) { BeginDocBody (); docPart = inBody; PushElt (eltPara, listNone); if (newElt == eltPara) /* we just handled it! */ return; } switch (newElt) { default: ETMPanic ("DoElement: logic error 2, element = %hd", newElt); case eltPara: TerminateDefList (); AddPara (); /* add para to current element */ break; case eltDisplay: /*TerminateDefList ();*/ if (displayFlag) ETMMsg ("problem: display inside display"); PushElt (eltDisplay, listNone); break; case eltDisplayEnd: if (eltStack[eltTop].eltType != eltDisplay) ETMMsg ("problem: display-end not inside display"); else PopElt (); break; case eltDisplayIndent: if (argc == 0) displayIndent = 0; else displayIndent = StrToShort (argv[0]); break; case eltList: TerminateDefList (); if (displayFlag) ETMMsg ("problem: list inside display"); PushElt (eltList, listUnordered); break; case eltListEnd: if (displayFlag) ETMMsg ("problem: list-end inside display"); if (eltStack[eltTop].eltType != eltList) ETMMsg ("problem: list-end not inside list"); else PopElt (); break; case eltListItem: if (displayFlag) ETMMsg ("problem: list-item inside display"); if (listDepth == 0) ETMMsg ("problem: list-item not inside list"); ControlOut ("LI", 1, 1); break; case eltHeader: TerminateDefList (); if (argc == 0) { ETMMsg ("header with no level found, ignored"); break; } else misc = StrToShort (argv[0]); if (bodyElt == eltHeader) ETMMsg ("problem: nested headers found"); if (displayFlag) ETMMsg ("problem: header inside display"); if (listDepth) ETMMsg ("problem: header inside list"); PushElt (eltHeader, misc); break; case eltHeaderEnd: if (eltStack[eltTop].eltType != eltHeader) ETMMsg ("problem: header-end w/o matching header, ignored"); else PopElt (); break; case eltBlockquote: TerminateDefList (); if (blockquoteFlag) ETMMsg ("problem: nested blockquotes found"); if (displayFlag) ETMMsg ("problem: blockquote inside display"); PushElt (eltBlockquote, 0); break; case eltBlockquoteEnd: if (eltStack[eltTop].eltType != eltBlockquote) ETMMsg ("problem: blockquote-end w/o matching blockquote, ignored"); else PopElt (); break; case eltDefTerm: /* begin new definition term */ if (displayFlag) ETMMsg ("problem: definition list inside display"); if (listDepth) ETMMsg ("problem: definition list inside list"); switch (defListFlag) { case defListNone: /* * Start new list, new term */ ControlOut ("DL", 1, 1); ControlOut ("DT", 1, 1); break; case defListTerm: break; /* ?? */ case defListDesc: /* * Close current description, start new term */ ControlOut ("/DD", 1, 1); ControlOut ("DT", 1, 1); break; } defListFlag = defListTerm; emptyDefTerm = 1; break; case eltDefDesc: /* begin new definition description */ if (displayFlag) ETMMsg ("problem: definition list end inside display"); if (listDepth) ETMMsg ("problem: definition list end inside list"); switch (defListFlag) { case defListNone: /* * Start new list, put out empty term, start new * description.
in the term forces a little * space between this item and the previous. */ ControlOut ("DL", 1, 1); ControlOut ("DT", 1, 0); ControlOut ("BR", 0, 0); ControlOut ("/DT", 0, 1); ControlOut ("DD", 1, 1); break; case defListTerm: /* * Close current term, start new description. */ if (emptyDefTerm) ControlOut ("BR", 0, 1); ControlOut ("/DT", 1, 1); ControlOut ("DD", 1, 1); break; case defListDesc: break; /* ??? */ } defListFlag = defListDesc; break; /* * Right and left shift are implemented by
    and
, which is * no doubt a terrible way to do it. It'll have to do until there's * a better way. */ case eltShiftRight: TerminateDefList (); ControlOut ("UL", 1, 1); ++shiftLevel; break; case eltShiftLeft: if (shiftLevel > 0) { TerminateDefList (); ControlOut ("/UL", 1, 1); --shiftLevel; } break; } } /* * Begin the document HEAD part. Set up to start saving text in the title * and header buffers. (Two buffers are used because line breaks and lines * are written to the header buffer as is, but as spaces and '/' characters * in the title -- this keeps the title all on a single line.) When the * document BODY part begins, the title buffer is flushed to the document * HEAD part and the header buffer is written as the initial heading of the * BODY part. * * Should only be called from DoElement(). */ static void BeginDocHead (void) { title[0] = '\0'; header[0] = '\0'; /* if centering is on, add
to header */ if (center) StrAddStr (header, sizeof (header), "
\n"); /* if underlining is on, add to header */ if (underline) StrAddStr (header, sizeof (header), "\n\n"); } /* * Begin the document BODY part. First flush out the HEAD part, including * the document title if there is one. Then put out the BODY tag and write * the initial header if there is one. * * Should only be called from DoElement(). * * cmdLineTitle, if set, overrides any title that was found in the body. * However, if there is a title and it was found to be centered and/or * underlined, the command-line title will also be centered and/or * underlined. */ static void BeginDocBody (void) { char *p; /* drop trailing spaces on title */ p = title + strlen (title) - 1; while (p > title && *(p-1) == ' ') *--p = '\0'; /* put out HEAD if title isn't empty */ if (cmdLineTitle != (char *) NULL || title[0] != '\0') { ControlOut ("HEAD", 1, 1); ControlOut (titleTag, 1, 1); if (cmdLineTitle != (char *) NULL) { for (p = cmdLineTitle; *p != '\0'; p++) StrOut (CharToHTML (*p)); } else StrOut (title); ControlOut (endTitleTag, 1, 1); ControlOut ("/HEAD", 1, 1); } title[0] = '\0'; ControlOut ("BODY", 1, 1); if (cmdLineTitle != (char *) NULL) { ControlOut (headerTag, 1, 1); if (center) ControlOut ("CENTER", 1, 1); if (underline) ControlOut ("UNDER", 1, 1); for (p = cmdLineTitle; *p != '\0'; p++) StrOut (CharToHTML (*p)); if (center) ControlOut ("/CENTER", 1, 1); if (underline) ControlOut ("/UNDER", 1, 1); ControlOut (endHeaderTag, 1, 1); } else if (header[0] != '\0') { /* * If centering is on, add an end-centering marker to the * header. Any following text in the body will get its * own begin-centering marker. Ditto for underlining. */ ControlOut (headerTag, 1, 1); StrOut (header); if (center) ControlOut ("/CENTER", 1, 1); if (underline) ControlOut ("/UNDER", 1, 1); ControlOut (endHeaderTag, 1, 1); } header[0] = '\0'; if (center) ControlOut ("CENTER", 1, 1); if (underline) ControlOut ("UNDER", 1, 1); } static void TerminateDefList (void) { switch (defListFlag) { default: ETMPanic ("TerminateDefList: logic error"); case defListNone: /* no current definition list - nothing to do */ break; case defListTerm: /* * Close current term, write empty description, close list. *
in the term forces a little space between this item * and the previous in case the term is empty. */ if (emptyDefTerm) ControlOut ("BR", 0, 1); ControlOut ("/DT", 1, 1); ControlOut ("DD", 1, 0); ControlOut ("/DD", 0, 1); ControlOut ("/DL", 1, 1); break; case defListDesc: /* * Close current description, close list */ ControlOut ("/DD", 0, 1); ControlOut ("/DL", 1, 1); break; } defListFlag = defListNone; } static void FlushTOC (void) { TOC *tp; short level = 0; char buf[bufSiz]; if (tocHead == (TOC *) NULL) /* no TOC */ return; ControlOut ("!-- TOC BEGIN --", 1, 1); tocCount = 0; for (tp = tocHead; tp != (TOC *) NULL; tp = tp->tocNext) { /* * If current level doesn't match entry level, decrease or * increase current level to match. */ while (level > tp->tocLevel) { ControlOut ("/UL", 1, 1); --level; } while (level < tp->tocLevel) { ControlOut ("UL", 1, 1); ++level; } ControlOut ("LI", 1, 1); sprintf (buf, "A HREF=#TOC_%d", ++tocCount); ControlOut (buf, 0, 0); StrOut (tp->tocStr); ControlOut ("/A", 0, 1); } while (level > 0) { ControlOut ("/UL", 1, 1); --level; } ControlOut ("!-- TOC END --", 1, 1); } static void PushElt (short eltType, short misc) { char buf[bufSiz]; if (++eltTop > maxElt - 1) ETMPanic ("PushElt: element stack overflow"); eltStack[eltTop].eltType = eltType; eltStack[eltTop].eltFont = curFont; eltStack[eltTop].eltMisc = misc; bodyElt = eltType; /* set current body element type */ /* begin new element */ switch (bodyElt) { default: ETMPanic ("PushElt: logic error, type = %hd", bodyElt); case eltPara: ControlOut ("P", 1, 1); /* AddPara()??? */ break; case eltDisplay: displayFlag = 1; SetFont (displayFont, displayFlag); ControlOut ("PRE", 1, 1); break; case eltList: ControlOut ("UL", 1, 1); /* DEPENDS ON TYPE */ ++listDepth; break; case eltHeader: sprintf (buf, "H%hd", misc); /* misc = header level */ ControlOut (buf, 1, 1); break; case eltBlockquote: ControlOut ("BLOCKQUOTE", 1, 1); ++blockquoteFlag; break; break; } } static void PopElt (void) { char buf[bufSiz]; if (eltTop < 0) ETMPanic ("PopElt: element stack underflow"); /* reset font, style if necessary */ /* close current element */ switch (eltStack[eltTop].eltType) { default: ETMPanic ("PopElt: logic error, type = %hd", eltStack[eltTop].eltType); case eltPara: /* nothing to do */ break; case eltDisplay: ControlOut ("/PRE", 1, 1); displayFlag = 0; SetFont ("R", displayFlag); break; case eltList: ControlOut ("/UL", 1, 1); /* DEPENDS ON TYPE */ --listDepth; break; case eltHeader: /* eltMisc = header level */ sprintf (buf, "/H%hd", eltStack[eltTop].eltMisc); ControlOut (buf, 1, 1); break; case eltBlockquote: ControlOut ("/BLOCKQUOTE", 1, 1); --blockquoteFlag; break; } eltTop--; bodyElt = eltStack[eltTop].eltType; /* restore previous type */ curFont = eltStack[eltTop].eltFont; /* * SHOULD I DO THIS? if (curFont != (Font *) NULL) SetFont (curFont->fontName); */ } /* * Perform a break. The action to take here depends on the current state. */ static void AddBreak (void) { if (docPart == inNone) { ETMMsg ("leading break skipped"); return; } if (docPart == inHead) { AddTitleChar (' '); StrAddStr (header, sizeof (header), "
\n"); return; } /* handle body elements */ switch (bodyElt) { default: ETMPanic ("AddBreak: logic error, part %d", bodyElt); case eltPara: case eltList: case eltHeader: case eltBlockquote: ControlOut ("BR", 0, 1); break; case eltDisplay: TextChOut (lf); break; } if (tocLevel > 0) /* TOC entry is being collected */ StrAddStr (tocBuf, sizeof (tocBuf), "
\n"); } /* * This should only be called from DoElement(). */ static void AddPara (void) { if (docPart == inNone) { ETMMsg ("leading space skipped"); return; } if (docPart == inHead) { AddTitleChar (' '); /* keep title all on one line */ StrAddStr (header, sizeof (header), "

\n"); return; } /* handle body elements */ switch (bodyElt) { default: ETMPanic ("AddPara: logic error, elt %d", bodyElt); case eltPara: case eltList: case eltHeader: case eltBlockquote: ControlOut ("P", 1, 1); break; case eltDisplay: TextChOut (lf); break; } if (tocLevel > 0) /* TOC entry is being collected */ StrAddStr (tocBuf, sizeof (tocBuf), "

\n"); } /* * Draw a line (horizontal only; ignore vertical). */ static void AddLine (long length, short direction) { if (direction != 'h') return; if (docPart == inNone) /* part unknown - set to default */ DoElement (eltPara, 0, (char **) NULL); if (docPart == inHead) { AddTitleChar ('/'); /* keep title all on one line */ StrAddStr (header, sizeof (header), "


\n"); return; } /* handle body elements */ switch (bodyElt) { default: ETMPanic ("AddLine: logic error, elt %d", bodyElt); case eltPara: case eltList: case eltHeader: case eltDisplay: case eltBlockquote: ControlOut ("HR", 1, 1); break; } /* don't collect anything for TOC here */ } /* * Add a string literally to the output. (No escaping of characters * that are special to HTML like & or < or >.) len is the effective * length of the string, i.e., the number of characters what would be * displayed in a browser. For example, the effective length of a * string like "Á" is one. */ static void AddLitStr (char *p) { char *p1, *p2; char c; if (p == (char *) NULL) return; switch (docPart) { default: ETMPanic ("AddLitStr: logic error"); case inHead: StrAddStr (title, sizeof (title), p); StrAddStr (header, sizeof (header), p); break; case inBody: /* * This is the ugly part. Write characters of the string * one by one. If a "&" is seen, assume it's part of a "&xxx;" * sequence and pass it to HTMLChOut() all at once. * Be careful about sequences that may have the terminating * ";" missing. */ p1 = p; while (*p1 != '\0') { if (*p1 != '&') /* not a "&xxx;" sequence */ TextChOut (*p1++); else { /* save beginning of "&xxx;" and find end */ p2 = p1++; while (*p1 != ';' && *p1 != '\0') ++p1; if (*p1 == ';') { c = *(++p1); /* save next char */ *p1 = '\0'; HTMLChOut (p2); *p1 = c; } else /* *p1 is '\0' */ { ETMMsg ("malformed sequence, missing semicolon: <%s>", p2); HTMLChOut (p2); /* supply the missing semicolon */ TextChOut (';'); } } } break; } if (tocLevel > 0) StrAddStr (tocBuf, sizeof (tocBuf), p); } /* * Add a string to the output. Escaping is done of characters * that are special to HTML like & or < or >. */ static void AddStr (char *p) { if (p == (char *) NULL) return; while (*p != '\0') AddChar (*p++); } /* * Add a character to the output. Escaping is done of characters * that are special to HTML like & or < or >. */ static void AddChar (char c) { switch (docPart) { default: ETMPanic ("AddChar: logic error"); case inHead: AddTitleChar (c); AddHeaderChar (c); break; case inBody: TextChOut (c); if (defListFlag == defListTerm) emptyDefTerm = 0; break; } if (tocLevel > 0) /* TOC entry is being collected */ AddTOCChar (c); } static void AddTitleChar (char c) { StrAddStr (title, sizeof (title), CharToHTML (c)); } static void AddHeaderChar (char c) { StrAddStr (header, sizeof (header), CharToHTML (c)); } static void AddTOCChar (char c) { StrAddStr (tocBuf, sizeof (tocBuf), CharToHTML (c)); } static void StrAddStr (char *buf, int size, char *str) { /* check whether or not str can be added to buf */ if (strlen (buf) + strlen (str) + 1 > size) ETMPanic ("StrAddStr: buffer overflow"); (void) strcat (buf, str); } /* * Table element routines */ static void TableBegin (short argc, char **argv) { if (docPart == inNone) /* part unknown - set to default */ DoElement (eltPara, 0, (char **) NULL); if (argc != 8) ETMPanic ("TableBegin: wrong number of args: %hd", argc); tblCols = StrToShort (argv[tblColsArg]); tblRows = StrToShort (argv[tblRowsArg]); if (tblCols == 0) ETMPanic ("TableBegin: zero column table"); if (tblCols > tblMaxCol) ETMPanic ("TableBegin: too many table columns (%hd), max = %d", tblCols, tblMaxCol); ControlOut ("BR", 1, 1); if (argv[tblAlignArg][0] == 'C') /* center the table */ { ControlOut ("CENTER", 1, 1); centerTbl = 1; } Flush (); StrOut ("'); Flush (); } static void TableEnd (void) { ControlOut ("/TABLE", 1, 1); if (centerTbl) { ControlOut ("/CENTER", 1, 1); centerTbl = 0; } ControlOut ("BR", 1, 1); } static void TableRowBegin (short argc, char **argv) { ControlOut ("TR", 1, 1); tblColIdx = 0; } static void TableRowEnd (void) { ControlOut ("/TR", 1, 1); ++tblRowIdx; } static void TableRowLine (short argc, char **argv) { ControlOut ("TR", 1, 1); printf ("\n", tblCols); ControlOut ("/TR", 1, 1); ++tblRowIdx; } static void TableCellInfo (short argc, char **argv) { short vspan, hspan; if (argc != 5) ETMPanic ("TableCellInfo: wrong number of args: %hd", argc); cellType[tblColIdx] = argv[cellTypeArg][0]; cellVSpan[tblColIdx] = StrToShort (argv[cellVSpanArg]); cellHSpan[tblColIdx] = StrToShort (argv[cellHSpanArg]); cellVAdjust[tblColIdx] = argv[cellVAdjustArg][0]; /* border value is ignored */ ++tblColIdx; if (tblColIdx >= tblCols) tblColIdx = 0; } static void TableCellBegin (short argc, char **argv) { CellBegin (cellType[tblColIdx], cellVSpan[tblColIdx], cellHSpan[tblColIdx], cellVAdjust[tblColIdx]); } static void TableCellEnd (void) { ControlOut ("/TD", 1, 1); ++tblColIdx; } static void TableEmptyCell (void) { CellBegin (cellType[tblColIdx], cellVSpan[tblColIdx], cellHSpan[tblColIdx], cellVAdjust[tblColIdx]); ControlOut ("BR", 0, 0); ControlOut ("/TD", 0, 1); ++tblColIdx; } static void TableSpannedCell (void) { ++tblColIdx; } /* * This is really poor. What's a better way? */ static void TableCellLine (short argc, char **argv) { /* override type with 'C' to force centering of the line */ CellBegin ('C', cellVSpan[tblColIdx], cellHSpan[tblColIdx], cellVAdjust[tblColIdx]); StrOut ("---"); ControlOut ("/TD", 1, 1); ++tblColIdx; } static void CellBegin (char type, short vspan, short hspan, char vadjust) { Flush (); StrOut (" 1) printf (" ROWSPAN=%hd", vspan); if (hspan > 1) printf (" COLSPAN=%hd", hspan); ChOut ('>'); Flush (); } /* * basic output routines * * ControlOut() - write control word. * TextStrOut() - write out a string of paragraph text. Does HTML escaping. * TextChOut() - write out a character of paragraph text. Does HTML escaping. * StrOut() - write out a string. * ChOut() - write out a character. ALL output (except ETM messages) * comes through this routine. * AllowOutput () - allow or throttle output. */ static void ControlOut (char *p, short brkBefore, short brkAfter) { if (p != (char *) NULL) { if (brkBefore) /* break if not already */ Flush (); /* at beginning of line */ ChOut ('<'); StrOut (p); ChOut ('>'); if (brkAfter) Flush (); } } static void TextStrOut (char *p) { if (p != (char *) NULL) { while (*p != '\0') TextChOut (*p++); } } /* * HTML-ize a character and return pointer to resulting string. * This keeps characters like < and > from being interpreted * specially by Web browsers. Return value is a pointer into a * static buffer, and should be copied if the caller needs to hang * onto it for a while. */ static char * CharToHTML (int c) { static char buf[7]; switch (c) { default: buf[0] = c; buf[1] = '\0'; break; case '&': (void) strcpy (buf, "&"); break; case '<': (void) strcpy (buf, "<"); break; case '>': (void) strcpy (buf, ">"); break; case '"': (void) strcpy (buf, """); break; } return (buf); } /* * Write a character of document text. */ static void TextChOut (int c) { HTMLChOut (CharToHTML (c)); } /* * Write a character of document text. The character is passed in as * a string, which is assumed to be the HTML representation of a single * character (e.g., "x" for x, "&" for &. * - Sets tCount to the number of text (non-tag) characters on the line. * - Sets etCount to the number of effective text (non-tag) characters. * - Sets cCount to the number of characters on the line (via ChOut ()). * - Does line wrapping if not in a display or in fill mode. * - Handles display indent. * * Characters written to produce display indent are not included in the * tCount or etCount line output character counts. Tabbing in displays is * thus relative to the indent, not to the document left margin. */ static void HTMLChOut (char *p) { int len; int i; /* * Check to make sure this is either a single character string or * that it begins with &. */ if (*p == '\0' || (*p != '&' && *(p+1) != '\0')) ETMPanic ("HTMLChOut: logic error (%s)", p); /* * Don't do line wrapping if collecting a display or * in nofill mode. */ if (displayFlag || fill == 0) { /* * If this is the start of a display line, put out spaces to * add the leading indent. Exception: if the character is a * linefeed, the line is blank, so there's no need for leading * spaces. */ if (displayFlag && tCount == 0 && *p != lf) { for (i = 0; i < displayIndent; i++) ChOut (' '); /* * tCount and etCount are deliberately NOT set here, * so tabs in displays are relative to the indent, * not to the left margin. */ } if (*p == tab) /* print a tab */ { /* * Assume worst case (that all tabstops are too small), * in which case only print a single space. If an * appropriate tabstop is found, use it. */ len = 1; for (i = 0; i < tabCount; i++) { if (tabPos[i] > etCount) { len = tabPos[i] - etCount; break; } } for (i = 0; i < len; i++) ChOut (' '); tCount += len; etCount += len; } else /* not a tab */ { StrOut (p); if (*p != lf) { tCount += strlen (p); ++etCount; } } return; } /* * Not in display or fill mode. Do line wrapping to keep output * lines from becoming really long. When that's done, it also * becomes useful to ignore leading spaces that occur at the * beginning of the next line. Tabs are not processed if line * wrapping occurs - just print a space. */ if (*p == tab) *p = ' '; if (*p == ' ' && tCount == 0) /* leading space */ return; if (*p == ' ' && cCount > 60) /* break line */ Flush (); /* (sets cCount, tCount to zero */ else { StrOut (p); tCount += strlen (p); ++etCount; } } /* * StrOut() and ChOut() result in cCount being set. If a linefeed is * printed, both cCount and tCount are set to zero. */ static void StrOut (char *p) { if (p != (char *) NULL) { while (*p != '\0') ChOut (*p++); } } static void ChOut (int c) { if (!allowOutput) return; if (c != ' ' && pendingAnchor != (char *) NULL) { if (fputs (pendingAnchor, stdout) == EOF) ETMPanic ("Write error, cannot continue"); cCount += strlen (pendingAnchor); Free (pendingAnchor); pendingAnchor = (char *) NULL; } if (putc (c, stdout) == EOF) ETMPanic ("Write error, cannot continue"); ++cCount; if (c == lf) { cCount = 0; tCount = 0; etCount = 0; } } static void Flush (void) { if (cCount > 0) ChOut (lf); } static int AllowOutput (int yesno) { int prev = allowOutput; allowOutput = yesno; return (prev); } /* * Read font information file. Format of lines is * * troff-font-name begin-tag end-tag begin-tag2 end-tag2 * * begin-tag2 and end-tag2 are used when in displays * * For example: * R "" "" "" "" * I * B * CW "" "" */ static int ReadFonts (char *filename) { FILE *f; char buf[bufSiz]; Font *fp; char *name, *begin, *end, *dbegin, *dend; if ((f = TCROpenLibFile (filename, "r")) == (FILE *) NULL) return (0); while (TCRGetLine (buf, (int) sizeof (buf), f)) { if (buf[0] == '#') /* skip comments */ continue; TSScanInit (buf); name = TSScan (); begin = TSScan (); end = TSScan (); dbegin = TSScan (); dend = TSScan (); if (dend == (char *) NULL) continue; fp = New (Font); fp->fontName = StrAlloc (name); fp->beginTag = StrAlloc (begin); fp->endTag = StrAlloc (end); fp->dispBeginTag = StrAlloc (dbegin); fp->dispEndTag = StrAlloc (dend); fp->inDisplay = 0; fp->next = fontList; fontList = fp; } (void) fclose (f); return (1); } static Font * LookupFont (char *name) { Font *fp; for (fp = fontList; fp != (Font *) NULL; fp = fp->next) { if (strcmp (name, fp->fontName) == 0) break; } return (fp); /* NULL if not found */ } ry is being collected */ AddTOCChar (c); } static void AddTitleChar (char c) { StrAddStr (title, sizeof (title), CharToHTML (c)); } static void AddHeaderChar (char troffcvt-1.04/post/tc2html.h010066400017710000151000000061570634014077600175520ustar00junkyarddatamgmt00000400000027#define defaultFontFile "html-fonts" #define specialCharFile "html-specials" #define charsPerInch 10 #define maxTabStops 35 #define lf '\n' /* linefeed */ #define tab '\t' /* tab */ #define maxElt 20 /* max depth of element stack */ #define maxTitle 2048 /* title buffer size */ #define maxHeader 2048 /* header buffer size */ #define maxTOC 4096 /* TOC entry size */ #define titleTag "TITLE" #define endTitleTag "/TITLE" #define headerTag "H1" #define endHeaderTag "/H1" #define tocTitleTag "H2" #define endTocTitleTag "/H2" #define displayFont "CW" /* * Document parts */ #define inNone 0 /* not in any document part */ #define inHead 1 /* in document HEAD part */ #define inBody 2 /* in document BODY part */ /* * Keyword types */ #define keyUnknown 0 #define keyAnchor 1 #define keyElement 2 /* * Anchor types */ #define anchorUnknown 0 #define anchorHref 1 #define anchorName 2 #define anchorTOC 3 #define anchorEnd 4 /* * Document structural elements */ #define eltUnknown 0 #define eltTitle 1 #define eltPara 2 #define eltDisplay 3 /* i.e., preformatted text */ #define eltDisplayEnd 4 #define eltDisplayIndent 5 #define eltList 6 #define eltListEnd 7 #define eltListItem 8 #define eltHeader 9 #define eltHeaderEnd 10 #define eltBlockquote 11 #define eltBlockquoteEnd 12 #define eltDefTerm 13 #define eltDefDesc 14 #define eltShiftRight 15 #define eltShiftLeft 16 /* * List types */ #define listNone 0 #define listUnordered 1 #define listOrdered 2 /* * Definition-list states */ #define defListNone 0 #define defListTerm 1 #define defListDesc 2 /* * Adjustment types (there is no "adjust-both"; \adjust-full maps to adjLeft) */ #define adjLeft 0 /* left justify */ #define adjCenter 1 /* center */ #define adjRight 2 /* right justify */ /* * Font information structure */ typedef struct Font Font; struct Font { char *fontName; char *beginTag; char *endTag; char *dispBeginTag; char *dispEndTag; short inDisplay; Font *next; }; /* * Structure for mapping the keywords on \html control lines * to type/subtype codes. */ typedef struct KeyMap KeyMap; struct KeyMap { char *name; short type; short subtype; }; /* * Structure for maintaining an HTML element stack */ typedef struct Elt Elt; struct Elt { short eltType; /* type of element */ Font *eltFont; /* current font/style when element entered */ short eltMisc; /* list type, header level, etc. */ Elt *eltNext; }; /* * Structure for maintaining the table-of-contents list */ typedef struct TOC TOC; struct TOC { short tocLevel; /* indentation level of entry */ char *tocStr; /* text of entry */ TOC *tocNext; /* next entry in list */ }; /* * FTabInfo - information to map the TCR typeface names onto the * names to use in \fonttbl. */ typedef struct FTabInfo FTabInfo; struct FTabInfo { TCRFont *tcrInfo; /* info maintained by reader */ char *rtfName; /* rtf name per charset */ FTabInfo *nextFTabInfo; }; /* * Special character structure */ typedef struct SpChar SpChar; struct SpChar { char *spName; /* name in troffcvt output */ char *spValue; /* value to output for character */ SpChar *spNext; }; troffcvt-1.04/post/troff2html.pl010066400017710000151000000053430631337616400204460ustar00junkyarddatamgmt00000400000027 # Script type: perl # troff2html - invoke troffcvt preprocessor and tc2html postprocessor # Understands the usual troffcvt and tc2html arguments. In addition, # understands the following options: # -n no execution, just show commands that would be executed # -p don't run the postprocessors tc2html or tc2html-toc # Adds the action file "actions-html" at the front of the argument list. # Adds in redefinition files according to any macro package that is named # in the command-line arguments. For example, if "-ms" is specified on the # command line, troff2html passes "-ms -a tc.ms -a tc.ms-html" to troffcvt. # 03 Feb 97 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 03 Feb 97 V1.00 # - Created. ($prog = $0) =~ s|.*//||; # get script name for messages $troffcvt = "troffcvt"; $postproc = "tc2html"; $postproctoc = "tc2html-toc"; $noexec = 0; $nopostproc = 0; $tmp = "$(TMPDIR)/tc2html$$"; # temporary filename $preargs = "-a actions-html"; $postargs = ""; while (@ARGV) { $_ = shift (@ARGV); # get next argument if ($_ eq "-n") # recognize and delete -n { $noexec = 1; next; } if ($_ eq "-p") # recognize and delete -p { $nopostproc = 1; next; } if (!/^-./) # not a flag, just a filename or "-" { $preargs .= " $_"; next; } ($opt, $rest) = /^-(.)(.*)/; if ($opt eq "m") # -mxx macro package argument { die "$prog: -m requires macro package name\n" if $rest eq ""; $preargs .= " -m$rest -a 'tc.m$rest' -a 'tc.m$rest-html'"; next; } if ($opt =~ /^[ACl]$/) # troffcvt arguments that stand alone { $preargs .= " -$opt"; next; } if ($opt =~ /^[adrt]$/) # troffcvt arguments that require an { # additional argument if ($rest eq "") { die "$prog: -$opt requires following argument\n" if @ARGV == 0; $rest = shift (@ARGV); } $preargs .= " -$opt '$rest'"; next; } if ($opt =~ /^[DE]$/) # tc2html arguments that stand alone { $postargs .= " -$opt"; next; } if ($opt =~ /^[T]$/) # tc2html arguments that require an { # additional argument if ($rest eq "") { die "$prog: -$opt requires following argument\n" if @ARGV == 0; $rest = shift (@ARGV); } $postargs .= " -$opt '$rest'"; next; } warn ("Bad argument: -$opt\n"); } if ($nopostproc) { # basic translation $cmd = "$troffcvt $preargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } else { # basic translation $cmd = "$troffcvt $preargs | $postproc $postargs > $tmp"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; # move TOC to proper spot if there is one $cmd = "$postproctoc $tmp"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; # clobber temp file $cmd = "$(RM) $tmp"; warn "$cmd\n" if $noexec; unlink ($tmp) if !$noexec; } exit (0); troffcvt-1.04/post/Old/004077500017710000151000000000000634137666700165475ustar00junkyarddatamgmt00000400000027troffcvt-1.04/post/Old/troff2null.sh010064400017710000151000000007340626662671200211720ustar00junkyarddatamgmt00000400000027 # Script type: Bourne shell # troff2null - "convert" troff documents to nothing # 12 May 92 Paul DuBois dubois@primate.wisc.edu # 12 May 92 V1.00. Created args= for a in "$@"; do case $1 in -m*) macro=`echo $1|sed -e 's/^..//'` redefs=m$macro-redefs args="$args $1 -a $redefs" shift ;; -*) args="$args $1" shift ;; *) break ;; esac done if [ $# -eq 0 ]; then files="-" else files="$@" fi troffcvt $args $files | tc2null $rargs troffcvt-1.04/post/Old/troff2rtf.sh010064400017710000151000000011740630211607200207720ustar00junkyarddatamgmt00000400000027 # Script type: Bourne shell # troff2rtf - convert troff documents to RTF format. # 07 May 92 Paul DuBois dubois@primate.wisc.edu # 07 May 92 V1.00. Created args= rargs= for a in "$@"; do case $1 in -m*) macro=`echo $1|sed -e 's/^..//'` redefs=m$macro-redefs args="$args $1 -a $redefs" shift ;; -cs) if [ $# -lt 2 ]; then echo "Missing charset after -cs" 1>&2 exit 1 fi rargs="$rargs -cs $2" shift; shift ;; -*) args="$args $1" shift ;; *) break ;; esac done if [ $# -eq 0 ]; then files="-" else files="$@" fi troffcvt -ttroff -r1440 $args $files | tc2rtf $rargs troffcvt-1.04/post/Old/unroff.sh010064400017710000151000000013060630211603400203460ustar00junkyarddatamgmt00000400000027 # Script type: Bourne shell # unroff - convert troff documents to text (smart deroff) # 12 May 92 Paul DuBois dubois@primate.wisc.edu # 12 May 92 V1.00. Created args= pargs= for a in "$@"; do case $1 in -m*) macro=`echo $1|sed -e 's/^..//'` redefs=m$macro-redefs args="$args $1 -a $redefs" shift ;; -join|-split?*) pargs="$pargs $1" shift ;; -split) pargs="$pargs $1" shift if [ $# -gt 0 ]; then case $1 in [0-9]*) pargs="$pargs $1" shift ;; esac fi ;; -*) args="$args $1" shift ;; *) break ;; esac done if [ $# -eq 0 ]; then files="-" else files="$@" fi troffcvt -tnroff $args $files | tc2text $pargs troffcvt-1.04/post/Old/rtf-specials010066400017710000151000000106420634111552400210450ustar00junkyarddatamgmt00000400000027# special characters for troffcvt -> RTF writer # field meaning # ----- ------- # 1 special character name # 2-5 rtf string to write for different character sets # Special character names should match those used in the action # file used with troffcvt to generate the input to the RTF writer. # If the name is followed by "/F" then font F will be used to write # the character. This is really wrong, since the font needed might # be different for different character sets possibly. # If string is explicitly empty ("") nothing will be written. This makes # any occurrences of the special character in the input disappear from # the output! (This is useful for things like opthyphen.) # If a special character definition is missing completely or is "NULL", # the character name itself will be written in the form "[[name]]". # (This is also true if the definition is missing for a particular # character set and output is being written for that set.) This # way the character won't be dropped if you forget to define it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one." # This table is woefully complete for all but Macintosh special # characters. # name \ansi \mac \pc \pca backslash \\\\ \\\\ \\\\ \\\\ at @ @ @ @ # these could be written portably as \lquote, \rquote, \ldblquote, # \rdblquote if certain readers (e.g., WordPerfect) understood those. quoteleft \` "\\'d4" \` \` quoteright \' "\\'d5" \' \' quotedblleft \" "\\'d2" \" \" quotedblright \" "\\'d3" \" \" zerospace "" "" "" "" sixthspace "" "" "" "" twelfthspace "" "" "" "" # not really correct digitspace " " " " " " " " hardspace \\~ \\~ \\~ \\~ # backspace emdash - "\\'d1" - - minus - - - - # don't really know what to do with these yet... fieldbegin "" "" "" "" fieldend "\\tab " "\\tab " "\\tab " "\\tab " fieldpad "" "" "" "" leader "\\tab " "\\tab " "\\tab " "\\tab " tab "\\tab " "\\tab " "\\tab " "\\tab " # want this to disappear opthyphen "" "" "" "" bullet NULL "\\'a5" NULL NULL # square # ru # onequarter # onehalf # threequarters fi fi fi fi fi fl fl fl fl fl ff ff ff ff ff ffi ffi ffi ffi ffi ffl ffl ffl ffl ffl degree NULL "\\'a1" NULL NULL dagger NULL "\\'a0" NULL NULL # minute cent NULL "\\'a2" NULL NULL registered "(reg.)" "\\'a8" "(reg.)" "(reg.)" copyright "(c)" "\\'a9" "(c)" "(c)" plusmath + + + + minusmath - - - - equalmath = = = = asteriskmath * * * * section NULL "\\'a4" NULL NULL acute \' \' \' \' grave \` \` \` \` ul _ _ _ _ slash / / / / # radical # radicalex greaterequal >= "\\'b3" >= >= lessequal <= "\\'b2" <= <= # equivalence # approxequal # similar notequal NULL "\\'ad" NULL NULL # arrowright # arrowleft # arrowup # arrowdown multiply/S "\\'b4" "\\'b4" "\\'b4" "\\'b4" divide/S "/" "\\'b8" "/" "/" plusminus "+/-" "\\'b1" "+/-" "+/-" # union # intersection # propersubset # propersuperset # reflexsubset # reflexsuperset # infinity # partialdiff # gradient # logicalnot # integral # proportional # emptyset # element # br daggerdbl NULL "\\'e0" NULL NULL # handright # handleft # bell # bar # circle # bracelefttp # braceleftbt # bracerighttp # bracerightbt # braceleftmid # bracerightmid # bv # bracketleftbt # bracketrightbt # bracketlefttp # bracketrighttp alpha/S a a a a beta/S b b b b gamma/S g g g g delta/S d d d d epsilon/S e e e e zeta/S z z z z eta/S y y y y theta/S h h h h iota/S i i i i kappa/S k k k k lambda/S l l l l mu/S m m m m nu/S n n n n xi/S c c c c omicron/S o o o o pi/S p p p p rho/S r r r r sigma/S s s s s sigma1/S V V V V tau/S t t t t upsilon/S u u u u phi/S f f f f chi/S x x x x psi/S q q q q omega/S w w w w Alpha/S A A A A Beta/S B B B B Gamma/S G G G G Delta/S D D D D Epsilon/S E E E E Zeta/S Z Z Z Z Eta/S Y Y Y Y Theta/S H H H H Iota/S I I I I Kappa/S K K K K Lambda/S L L L L Mu/S M M M M Nu/S N N N N Xi/S C C C C Omicron/S O O O O Pi/S P P P P Rho/S R R R R Sigma/S S S S S Tau/S T T T T Upsilon/S U U U U Phi/S F F F F Chi/S X X X X Psi/S Q Q Q Q Omega/S W W W W troffcvt-1.04/post/html-specials010066400017710000151000000102560634137446100205100ustar00junkyarddatamgmt00000400000027# special characters for troffcvt -> HTML writer # field meaning # ----- ------- # 1 special character name # 2 HTML string to write for character # Special character names should match those used in the action # file used with troffcvt to generate the input to the HTML writer. # If string is explicitly empty ("") nothing will be written. This makes # any occurrences of the special character in the input disappear from # the output! (This is useful for things like zerospace.) # If a special character definition is missing completely, the # character name itself will be written in the form "[[name]]". # This way the character won't be dropped if you forget to define # it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. backslash \\ at @ quoteleft "\'" quoteright "\'" quotedblleft "\"" quotedblright "\"" zerospace "" sixthspace "" twelfthspace "" digitspace " " emdash "--" minus "-" # don't really know what to do with these yet... fieldbegin "" fieldend "" fieldpad " " leader " " tab " " bullet "*" fi fi fl fl ff ff ffi ffi ffl ffl plusmath + minusmath - equalmath = asteriskmath * grave \` ul _ slash / greaterequal >= lessequal <= equivalence == notequal != arrowright -> arrowleft <- arrowdblright => arrowdblleft <= arrowboth <-> arrowdblboth <=> arrowhorizex -- angleleft < angleright > asciicircum ^ asciitilde ~ tilde ~ bar | br | bv | braceleft { braceright } bracketleft [ bracketright ] dollar $ endash - hyphen - minute "'" second "''" numbersign # ru _ trademark (tm) # These list the &name; form in addition to the &#nnn form, although # only the first is used... hardspace     exclamdown ¡ ¡ cent ¢ ¢ sterling £ £ currency ¤ ¤ yen ¥ ¥ brokenbar ¦ ¦ section § § dieresis ¨ ¨ copyright © © ordfeminine ª ª guillemotleft « « logicalnot ¬ ¬ opthyphen ­ ­ registered ® ® macron ¯ ¯o; degree ° ° plusminus ± ± twosuperior ² ² threesuperior ³ ³ acute ´ ´ mu µ µ paragraph ¶ ¶ dotmath · · cedilla ¸ ¸ onesuperior ¹ ¹ ordmasculine º º guillemotright » » onequarter ¼ ¼ onehalf ½ ½ threequarters ¾ ¾ questiondown ¿ ¿ Agrave À À Aacute Á Á Acircumflex   Atilde à à Adieresis Ä Ä Aring Å Å AE Æ Æ Ccedilla Ç Ç Egrave È È Eacute É É Ecircumflex Ê Ê Edieresis Ë Ë Igrave Ì Ì Iacute Í Í Icircumflex Î Î Idieresis Ï Ï Eth Ð Ð Ntilde Ñ Ñ Ograve Ò Ò Oacute Ó Ó Ocircumflex Ô Ô Otilde Õ Õ Odieresis Ö Ö #multiply × multiply "x" Oslash Ø Ø Ugrave Ù Ù Uacute Ú Ú Ucircumflex Û Û Udieresis Ü Ü Yacute Ý Ý Thorn Þ Þ germandbls ß ß agrave à à aacute á á acircumflex â â atilde ã ã adieresis ä ä aring å å ae æ æ ccedilla ç ç egrave è è eacute é é ecircumflex ê ê edieresis ë ë igrave ì ì iacute í í icircumflex î î idieresis ï ï eth ð ð ntilde ñ ñ ograve ò ò oacute ó ó ocircumflex ô ô otilde õ õ odieresis ö ö divide ÷ ÷ oslash ø ø ugrave ù ù uacute ú ú ucircumflex û û udieresis ü ü yacute ý ý thorn þ þ ydieresis ÿ ÿ "*" fi fi fl fl ff ff ffi ffi ffl ffl plusmath + minusmath - equalmath = asteriskmath * grave \` ul _ slash / greaterequal >= lessequal <= equivalence == notequal != arrowright -> arrowleft <- arrowdblright => arrowdblleft <= arrowboth <-> arrowdblboth <=> arrowhorizex -- angleleft < angleright > asciicircum ^troffcvt-1.04/post/html-fonts010066400017710000151000000011260631214335400200230ustar00junkyarddatamgmt00000400000027# html-fonts # Column 1: troff font name # Column 2: tag to put out to begin font when not in display # Column 3: tag to put out to end font when not in display # Column 4: tag to put out to begin font when in display # Column 5: tag to put out to end font when in display R "" "" "" "" I B BI C "" "" CW "" "" CI CO CB CBI CBO troffcvt-1.04/post/tc2html-toc.pl010066400017710000151000000047170630322274100205110ustar00junkyarddatamgmt00000400000027 # Script type: perl # tc2html-toc - examine tc2html output for a table of contents and move # it to the correct location. # The TOC is indicated by two HTML comments: # # # The location to which the TOC should be moved may be specified explicitly # in the troff input files by invoking the .H*toc*title request, which writes # the title and this HTML comment: # # Macro package redefinitions can make a guess about where the TOC should be # located in the absence of an explicit location marker. To do so, the # redefinition should write the following advisory marker comment: # # 20 Feb 97 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 20 Feb 97 V1.00 # - Created. ($prog = $0) =~ s|.*//||; # get script name for messages @line = <>; # slurp entire input @toc = (); $bodyloc = -1; # line number of $tocloc = -1; # line number of TOC location marker $tocloc2 = -1; # line number of advisory TOC location marker $tocbegin = -1; # beginning line number of TOC $tocend = -1; # ending line number of TOC $lno = -1; foreach (@line) { ++$lno; if (/^/) { $bodyloc = $lno; next; } next unless /^/) { $tocloc = $lno; } elsif (/^/) { $tocloc2 = $lno; } elsif (/^/) { $tocbegin = $lno; } elsif (/^/) { $tocend = $lno; } } # use advisory location if no explicit location was found # (if no advisory was found, either, move to the beginning of # the document body.) $tocloc = $tocloc2 if $tocloc < 0; $tocloc = $bodyloc if $tocloc < 0; # Die if there is a TOC but the TOC location cannot be determined if ($tocbegin >= 0 && tocloc < 0) { die "$prog: cannot determine where to move TOC\n"; } # Check some anomalous conditions (which should not occur) if ($tocloc > $tocbegin && $tocloc < $tocend) { die "$prog: TOC location marker is in middle of TOC!\n"; } # Move TOC to desired location if one was found. (If none was found, # the input is written to the output unchanged.) if ($tocbegin >= 0) { # extract TOC from document @toc = splice (@line, $tocbegin, $tocend - $tocbegin + 1); # adjust location if desired location follows TOC $tocloc -= scalar (@toc) if $tocloc > $tocbegin; # reinsert TOC at correct location splice (@line, $tocloc+1, 0, @toc); } print @line; exit (0); troffcvt-1.04/post/troff2rtf.pl010066400017710000151000000044450631366645600203050ustar00junkyarddatamgmt00000400000027 # Script type: perl # troff2rtf - invoke troffcvt preprocessor and tc2rtf postprocessor # Understands the usual troffcvt and tc2rtf arguments. In addition, # understands the following options: # -n no execution, just show commands that would be executed # -p don't run the postprocessor tc2rtf # Adds in redefinition files according to any macro package that is named # in the command-line arguments. For example, if "-ms" is specified on the # command line, troff2rtf passes "-ms -a tc.ms" to troffcvt. # 17 Mar 97 # Paul DuBois # dubois@primate.wisc.edu # http://www.primate.wisc.edu/people/dubois # 17 Mar 97 V1.00 # - Created. ($prog = $0) =~ s|.*//||; # get script name for messages $troffcvt = "troffcvt"; $postproc = "tc2rtf"; $noexec = 0; $nopostproc = 0; $preargs = "-ttroff -r1440"; $postargs = ""; while (@ARGV) { $_ = shift (@ARGV); # get next argument if ($_ eq "-n") # recognize and delete -n { $noexec = 1; next; } if ($_ eq "-p") # recognize and delete -p { $nopostproc = 1; next; } if (!/^-./) # not a flag, just a filename or "-" { $preargs .= " $_"; next; } ($opt, $rest) = /^-(.)(.*)/; if ($opt eq "m") # -mxx macro package argument { die "$prog: -m requires macro package name\n" if $rest eq ""; $preargs .= " -m$rest -a 'tc.m$rest'"; next; } if ($opt =~ /^[ACl]$/) # troffcvt arguments that stand alone { $preargs .= " -$opt"; next; } if ($opt =~ /^[adrt]$/) # troffcvt arguments that require an { # additional argument if ($rest eq "") { die "$prog: -$opt requires following argument\n" if @ARGV == 0; $rest = shift (@ARGV); } $preargs .= " -$opt '$rest'"; next; } if ($opt =~ /^[DE]$/) # tc2rtf arguments that stand alone { $postargs .= " -$opt"; next; } if ($opt =~ /^[S]$/) # tc2rtf arguments that require an { # additional argument if ($rest eq "") { die "$prog: -$opt requires following argument\n" if @ARGV == 0; $rest = shift (@ARGV); } $postargs .= " -$opt '$rest'"; next; } warn ("Bad argument: -$opt\n"); } if ($nopostproc) { # basic translation $cmd = "$troffcvt $preargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } else { # basic translation $cmd = "$troffcvt $preargs | $postproc $postargs"; warn "$cmd\n" if $noexec; system $cmd if !$noexec; } exit (0); troffcvt-1.04/post/text-8-specials010066400017710000151000000043620634137570300206760ustar00junkyarddatamgmt00000400000027# 8-bit special characters for troffcvt -> text writer # field meaning # ----- ------- # 1 special character name # 2 string to write for name # If string is explicitly empty ("") nothing will be written. This makes # any occurrences of the special character in the input disappear from # the output! (This is useful for things like opt-hyphen.) # If a special character definition is missing completely, the # character name itself will be written in the form "[[name]]". # This way the character won't be dropped if you forget to define # it here. # backslashes should be doubled if you want them to appear in the # output. Don't forget to quote if you want to include whitespace. # Don't forget a trailing space if a control word needs one. # To specify a character with decimal value nnn, use #nnn. # name value hardspace #160 exclamdown #161 cent #162 sterling #163 currency #164 yen #165 brokenbar #166 section #167 dieresis #168 copyright #169 ordfeminine #170 guillemotleft #171 logicalnot #172 opthyphen #173 registered #174 macron #175 degree #176 plusminus #177 twosuperior #178 threesuperior #179 acute #180 mu #181 paragraph #182 dotmath #183 cedilla #184 onesuperior #185 ordmasculine #186 guillemotright #187 onequarter #188 onehalf #189 threequarters #190 questiondown #191 Agrave #192 Aacute #193 Acircumflex #194 Atilde #195 Adieresis #196 Aring #197 AE #198 Ccedilla #199 Egrave #200 Eacute #201 Ecircumflex #202 Edieresis #203 Igrave #204 Iacute #205 Icircumflex #206 Idieresis #207 Eth #208 Ntilde #209 Ograve #210 Oacute #211 Ocircumflex #212 Otilde #213 Odieresis #214 multiply #215 Oslash #216 Ugrave #217 Uacute #218 Ucircumflex #219 Udieresis #220 Yacute #221 Thorn #222 germandbls #223 agrave #224 aacute #225 acircumflex #226 atilde #227 adieresis #228 aring #229 ae #230 ccedilla #231 egrave #232 eacute #233 ecircumflex #234 edieresis #235 igrave #236 iacute #237 icircumflex #238 idieresis #239 eth #240 ntilde #241 ograve #242 oacute #243 ocircumflex #244 otilde #245 odieresis #246 divide #247 oslash #248 ugrave #249 uacute #250 ucircumflex #251 udieresis #252 yacute #253 thorn #254 ydieresis #255 troffcvt-1.04/misc/004077500017710000151000000000000634140161300157535ustar00junkyarddatamgmt00000400000027troffcvt-1.04/misc/Imakefile010064400017710000151000000013170634070561400175700ustar00junkyarddatamgmt00000400000027XCOMM troffcvt miscellaneous stuff Makefile XCOMM make sure "all" is default target all:: XCOMM any special -D's or other flags for compiling DEFINES = XCOMM any special -I's for compiling INCLUDES = XCOMM Build an HTML file listing &#nnn; codes ScriptFromMsubTemplate($(PERLPATH),list-html-codes,list-html-codes.pl,NullArg) FakeInstallFile(list-html-codes) XCOMM Read actions file and generate troff-able list of special characters ScriptFromMsubTemplate($(PERL5PATH),list-specials,list-specials.pl,NullArg) FakeInstallFile(list-specials) XCOMM Check postprocessor special-char list for missing entries ScriptFromMsubTemplate($(PERL5PATH),chk-specials,chk-specials.pl,NullArg) FakeInstallFile(chk-specials) troffcvt-1.04/misc/Makefile010066400017710000151000000276770634136770100174440ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # Set the OS name and version macros if imake has defined them # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit sun.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit sun.cf to change # platform: sun.cf 96/06/21 # operating system: SunOS 5.5 Generic sun4u # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change LIBDIR = $(LOCALUSRLIBDIR)/troffcvt PROJLIBDIR = $(LIBDIR) MACROLIBDIR = $(USRLIBDIR)/tmac MACROFILEPREFIX = STRING_H = STRING_H_DEFINES = -D'STRING_H=$(STRING_H)' INCLUDESRC = $(TOP)/h LIBSRC = $(TOP)/lib LIBUNIXSRC = $(TOP)/libunix LIBMACSRC = $(TOP)/libmac UTILSRC = $(TOP)/util DOCSRC = $(TOP)/doc MANSRC = $(TOP)/man TCGENLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcgen.a DEPTCGENLIB = $(LIBSRC)/libtcgen.a TCREADLIB = $(LOADERLIBPREFIX)$(LIBSRC)/libtcread.a DEPTCREADLIB = $(LIBSRC)/libtcread.a TCUNIXLIB = $(LOADERLIBPREFIX)$(LIBUNIXSRC)/libtcunix.a DEPTCUNIXLIB = $(LIBUNIXSRC)/libtcunix.a # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / SHELL = /bin/sh VARARGS_DEFINES = -DSTDARG -DVARARGS TOP = ../. CURRENT_DIR = ./misc # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 11 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = troffcvt PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 04 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /usr/tmp SPOOLROOTDIR = /var/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar cq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -bh LINTLIBS = LN = ln -s MAKE = make MV = mv CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat COL = col SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -Dsun -DSVR4 STD_LDLIBS = -lsocket -lnsl -lw STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = -I. -I$(INCLUDESRC) PROJECT_DEFINES = $(VARARGS_DEFINES) $(STRING_H_DEFINES) PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = -Xc ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) \ $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = /usr/ucb/install INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -ms MDOCMACROS = -mdoc TROFFCVT = troffcvt TBLCVT = tblcvt TROFF2HTML = troff2html TROFF2RTF = troff2rtf UNROFF = unroff TCMANMACROS = -man TCMEMACROS = -me TCMMMACROS = -mm TCMSMACROS = -ms TCMDOCMACROS = -mdoc # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = -letm DEPETMLIB = FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # troffcvt miscellaneous stuff Makefile # make sure "all" is default target all:: # any special -D's or other flags for compiling DEFINES = # any special -I's for compiling INCLUDES = # Build an HTML file listing &#nnn; codes all:: list-html-codes list-html-codes:: list-html-codes.pl $(RM) $@ echo "#!"$(PERLPATH) > $@ $(MSUB) list-html-codes.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) list-html-codes help_aux:: @echo "'make "list-html-codes"' to "build the list-html-codes script install:: i.list-html-codes i.list-html-codes:: @echo list-html-codes is not installed anywhere. # Read actions file and generate troff-able list of special characters all:: list-specials list-specials:: list-specials.pl $(RM) $@ echo "#!"$(PERL5PATH) > $@ $(MSUB) list-specials.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) list-specials help_aux:: @echo "'make "list-specials"' to "build the list-specials script install:: i.list-specials i.list-specials:: @echo list-specials is not installed anywhere. # Check postprocessor special-char list for missing entries all:: chk-specials chk-specials:: chk-specials.pl $(RM) $@ echo "#!"$(PERL5PATH) > $@ $(MSUB) chk-specials.pl >> $@ $(CHMOD) a+x $@ clean:: $(RM) chk-specials help_aux:: @echo "'make "chk-specials"' to "build the chk-specials script install:: i.chk-specials i.chk-specials:: @echo chk-specials is not installed anywhere. # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend troffcvt-1.04/misc/list-html-codes.pl010066400017710000151000000003040631314550200213130ustar00junkyarddatamgmt00000400000027 # Script type: perl ($prog = $0) =~ s|.*/||; # get script name for messages for ($i = 0; $i < 256; $i++) { printf "&#%03d; <&#%03d;> <&#%03d;>
\n", $i, $i, $i; } troffcvt-1.04/misc/gen8bit010066400017710000151000000002050634003541500172320ustar00junkyarddatamgmt00000400000027#!/usr/local/bin/perl5 # generate "strike" of all characters in range 0 .. 255 foreach $i (0..255) { printf "%s: %c\n", $i, $i; } troffcvt-1.04/misc/iso-list010066400017710000151000000073150634122754300174540ustar00junkyarddatamgmt00000400000027 Latin-1 Latin-1 HTML HTML troffcvt decimal hex &#nnn; &name; name value value form form ---------------------------------------------- xxx 128 80 € xxx 129 81  xxx 130 82 ‚ xxx 131 83 ƒ xxx 132 84 „ xxx 133 85 … xxx 134 86 † xxx 135 87 ‡ xxx 136 88 ˆ xxx 137 89 ‰ xxx 138 8a Š xxx 139 8b ‹ xxx 140 8c Œ xxx 141 8d  xxx 142 8e Ž xxx 143 8f  xxx 144 90  xxx 145 91 ‘ xxx 146 92 ’ xxx 147 93 “ xxx 148 94 ” xxx 149 95 • xxx 150 96 – xxx 151 97 — xxx 152 98 ˜ xxx 153 99 ™ xxx 154 9a š xxx 155 9b › xxx 156 9c œ xxx 157 9d  xxx 158 9e ž xxx 159 9f Ÿ hardspace 160 a0     exclamdown 161 a1 ¡ ¡ cent 162 a2 ¢ ¢ sterling 163 a3 £ £ currency 164 a4 ¤ ¤ yen 165 a5 ¥ ¥ brokenbar 166 a6 ¦ ¦ section 167 a7 § § dieresis 168 a8 ¨ ¨ copyright 169 a9 © © ordfeminine 170 aa ª ª guillemotleft 171 ab « « logicalnot 172 ac ¬ ¬ opthyphen 173 ad ­ ­ registered 174 ae ® ® macron 175 af ¯ ¯o; degree 176 b0 ° ° plusminus 177 b1 ± ± twosuperior 178 b2 ² ² threesuperior 179 b3 ³ ³ acute 180 b4 ´ ´ mu 181 b5 µ µ paragraph 182 b6 ¶ ¶ dotmath 183 b7 · · cedilla 184 b8 ¸ ¸ onesuperior 185 b9 ¹ ¹ ordmasculine 186 ba º º guillemotright 187 bb » » onequarter 188 bc ¼ ¼ onehalf 189 bd ½ ½ threequarters 190 be ¾ ¾ questiondown 191 bf ¿ ¿ Agrave 192 c0 À À Aacute 193 c1 Á Á Acircumflex 194 c2   Atilde 195 c3 à à Adieresis 196 c4 Ä Ä Aring 197 c5 Å Å AE 198 c6 Æ Æ Ccedilla 199 c7 Ç Ç Egrave 200 c8 È È Eacute 201 c9 É É Ecircumflex 202 ca Ê Ê Edieresis 203 cb Ë Ë Igrave 204 cc Ì Ì Iacute 205 cd Í Í Icircumflex 206 ce Î Î Idieresis 207 cf Ï Ï Eth 208 d0 Ð Ð Ntilde 209 d1 Ñ Ñ Ograve 210 d2 Ò Ò Oacute 211 d3 Ó Ó Ocircumflex 212 d4 Ô Ô Otilde 213 d5 Õ Õ Odieresis 214 d6 Ö Ö multiply 215 d7 × Oslash 216 d8 Ø Ø Ugrave 217 d9 Ù Ù Uacute 218 da Ú Ú Ucircumflex 219 db Û Û Udieresis 220 dc Ü Ü Yacute 221 dd Ý Ý Thorn 222 de Þ Þ germandbls 223 df ß ß agrave 224 e0 à à aacute 225 e1 á á acircumflex 226 e2 â â atilde 227 e3 ã ã adieresis 228 e4 ä ä aring 229 e5 å å ae 230 e6 æ æ ccedilla 231 e7 ç ç egrave 232 e8 è è eacute 233 e9 é é ecircumflex 234 ea ê ê edieresis 235 eb ë ë igrave 236 ec ì ì iacute 237 ed í í icircumflex 238 ee î î idieresis 239 ef ï ï eth 240 f0 ð ð ntilde 241 f1 ñ ñ ograve 242 f2 ò ò oacute 243 f3 ó ó ocircumflex 244 f4 ô ô otilde 245 f5 õ õ odieresis 246 f6 ö ö divide 247 f7 ÷ ÷ oslash 248 f8 ø ø ugrave 249 f9 ù ù uacute 250 fa ú ú ucircumflex 251 fb û û udieresis 252 fc ü ü yacute 253 fd ý ý thorn 254 fe þ þ ydieresis 255 ff ÿ ÿ troffcvt-1.04/misc/chk-specials.pl010066400017710000151000000060600634137177500206740ustar00junkyarddatamgmt00000400000027 # Script type: perl5 # To do: # - option to replace list of unsupported specials in the special-char file # with an updated list. To do this, must be able to hold current contents # in order, and to recognize the current list of unsupported characters. # - Use actions file reader to write out a "strike": name: \(xx. This too # should list the built-in specials. # chk-specials - check a postprocessor special-char list to see which # special characters aren't listed. ($prog = $0) =~ s|.*/||; # get script name for messages $usage = "Usage: $prog special-char-list"; die "$usage\n" unless @ARGV; $actions = "$(TOP)/troffcvt/actions"; # troffcvt actions file # List of special character names. It's initialized with the built-in # specials. Then the special characters listed in the actions file are # added to the list. %special = ( "backslash" => "backslash", "at" => "at", "quoteleft" => "quoteleft", "quoteright" => "quoteright", "quotedblleft" => "quotedblleft", "quotedblright" => "quotedblright", "zerospace" => "zerospace", "twelfthspace" => "twelfthspace", "sixthspace" => "sixthspace", "digitspace" => "digitspace", "hardspace" => "hardspace", "minus" => "minus", "grave" => "grave", "acute" => "acute", "backspace" => "backspace", "emdash" => "emdash", "opthyphen" => "opthyphen", "tab" => "tab", "leader" => "leader", "fieldbegin" => "fieldbegin", "fieldend" => "fieldend", "fieldpad" => "fieldpad", ); open (IN, $actions) || die "$prog: cannot open $actions\n"; while () { chomp; @word = split (' ', $_); next unless $word[0] eq "imm"; next unless $word[1] eq "special-char"; $name = $word[3]; warn "$name\n" if $name !~ /^@/; $name =~ s/^@//; $special{$name} = $name; } close (IN); ProcessFile (shift (@ARGV)) while @ARGV; exit (0); # -------------------------------------------------------------------------- sub ProcessFile { my ($filename) = shift; my (%name, @name, $name, $rest, $count); my (@known, @unknown); open (IN, $filename) || die "$prog: cannot open $filename\n"; while () { chomp; next if /^#/; # ignore comments next if /^\s*$/; ($name, $rest) = split (' ', $_, 2); $name =~ s|/.*||; # name/modifier -> name push (@name, $name); ++$name{$name}; } close (IN); foreach $name (@name) { if (defined ($special{$name})) { push (@known, $name); } else { push (@unknown, $name); } } print "Known special character names listed in $filename:\n"; foreach $name (sort (@known)) { print "\t$name\n"; } print "Unknown special character names listed in $filename:\n"; foreach $name (sort (@unknown)) { print "\t$name\n"; } delete $special{shift (@name)} while @name; print "Special character names not listed in $filename:\n"; foreach $name (sort (keys (%special))) { print "\t$name\n"; } foreach $name (keys (%name)) { delete $name{$name} if $name{$name} == 1; } print "Special character names listed multiple times in $filename:\n"; foreach $name (sort (keys (%name))) { $count = $name{$name}; print "\t$name ($count time", $count > 1 ? "s" : "", ")\n"; } } troffcvt-1.04/misc/list-specials.pl010066400017710000151000000042450634122766300211010ustar00junkyarddatamgmt00000400000027 # Script type: perl5 # make-spec-list - read actions file for "imm special-char" lines and # generate a troff-able file listing each one. This can be run through # troffcvt translators to see what they do with each one. # This should also know about the characters in escMap and the quote # characters... (although those must be written out differently). ($prog = $0) =~ s|.*/||; # get script name for messages $usage = "Usage: $prog"; die "$usage\n" if @ARGV; $actions = "$(TOP)/troffcvt/actions"; # troffcvt actions file # troff strings listing builtin special character names and invocation sequences @bispecial = ( "backslash \\ee \\\\", "at @ @", "quoteleft ` `", "quoteright ' '", "quotedblleft `` ``", "quotedblright '' ''", "zerospace \\e& not visible", "twelfthspace \\e^ not visible", "sixthspace \\e| not visible", "digitspace \\e0 not visible", "hardspace \\e(space) not visible", "minus \\e- \\-", "grave \\e` \\`", "acute \\e' \\'", "backspace \\e(backspace) not visible", "opthyphen \\e% \\%", "tab \\et not visible", "leader varies", "fieldbegin varies", "fieldend varies", "fieldpad varies" ); # troff strings listing special character names and invocation sequences @special = (); open (IN, $actions) || die "$prog: cannot open $actions\n"; while () { chomp; @word = split (' ', $_); next unless $word[0] eq "imm"; next unless $word[1] eq "special-char"; $seq = $word[2]; $seq =~ s/^(['"])(.+)\1$/$2/; $name = $word[3]; warn "$name\n" if $name !~ /^@/; $name =~ s/^@//; push (@special, "$name \\e[$seq] \\[$seq]"); } close (IN); @bispecial = sort (@bispecial); @special = sort (@special); print ".nf\n"; printf "Built-in Special Characters:\n"; while (@bispecial) { # put the colon in after the name (it's not put in above when the # string is initially created because it messes up sorting). ($bispecial = shift (@bispecial)) =~ s/ /: /; print "\t$bispecial\n"; } printf "\nactions File Special Characters:\n"; while (@special) { # put the colon in after the name (it's not put in above when the # string is initially created because it messes up sorting). ($special = shift (@special)) =~ s/ /: /; print "\t$special\n"; } exit (0); troffcvt-1.04.orig/tarballs/ETM-1.09.tar100644 1750 1750 324000 6431756100 15456 0ustar blpblpetm/004077500017710000151000000000000632324667300134055ustar00junkyarddatamgmt00000400000027etm/Makefile010066400017710000151000000350210632324515000150300ustar00junkyarddatamgmt00000400000027# Makefile generated by imake - do not edit! # $XConsortium: imake.c /main/90 1996/11/13 14:43:23 lehors $ # ------------------------------------------------------------------------- # Makefile generated from "Imake.tmpl" and . # # Platform-specific parameters may be set in the appropriate .cf and # .p-cf configuration files. Site-wide parameters may be set in the # files site.def and site.p-def. Full rebuilds are recommended if # any parameters are changed. # ------------------------------------------------------------------------- # site-specific configuration parameters that need to come before the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # platform-specific configuration parameters specific to this project # edit hp.p-cf to change # ------------------------------------------------------------------------- # platform-specific configuration parameters # edit hp.cf to change # platform: hp.cf 95/07/15 # operating system: HP-UX 9.05 # ------------------------------------------------------------------------- # site-specific configuration parameters that go after the # platform-specific parameters - edit site.def or site.p-def to change # site: Primate Center 89/12/22 # ------------------------------------------------------------------------- # project-specific system and project description parameters # Edit Imake.p-params to change HASVOIDTYPE = 1 ETMVOIDTYPE = void ABORTSIGNAL = SIGABRT # ------------------------------------------------------------------------- # Standard system and project description parameters # Edit Imake.params to change # ------------------------------------------------------------------------- # definitions common to all Makefiles PATHSEP = / MFLAGS = -$(MAKEFLAGS) SHELL = /bin/sh VARARGS_DEFINES = -DVARARGS TOP = . CURRENT_DIR = . # Configuration file identification - name and release level CONFIGNAME = WRPRC2 CONFIGMAJORRELEASE = 2 CONFIGMINORRELEASE = 10 CONFIGRELEASE = $(CONFIGMAJORRELEASE).$(CONFIGMINORRELEASE) CONFIGROOTDIR = /usr/local/lib/config # Project identfication - name and release level PROJECTNAME = Exception and Termination Manager PROJECTMAJORRELEASE = 1 PROJECTMINORRELEASE = 09 PROJECTRELEASE = $(PROJECTMAJORRELEASE).$(PROJECTMINORRELEASE) BINDIR = /usr/bin USRLIBDIR = /usr/lib LINTLIBDIR = $(USRLIBDIR)/lint ETCDIR = /usr/etc INCLUDEROOT = /usr/include TMPDIR = /tmp SPOOLROOTDIR = /usr/spool LOCALROOTDIR = /usr/local LOCALBINDIR = $(LOCALROOTDIR)/bin LOCALUSRLIBDIR = $(LOCALROOTDIR)/lib LOCALLINTLIBDIR = $(LOCALUSRLIBDIR)/lint LOCALADMDIR = $(LOCALROOTDIR)/adm LOCALETCDIR = $(LOCALROOTDIR)/etc LOCALINCLUDEROOT = $(LOCALROOTDIR)/include MANROOT = /usr/local/man MANSOURCEPATH = $(MANROOT)/man MAN1SUFFIX = 1 MAN2SUFFIX = 2 MAN3SUFFIX = 3 MAN4SUFFIX = 4 MAN5SUFFIX = 5 MAN6SUFFIX = 6 MAN7SUFFIX = 7 MAN8SUFFIX = 8 MANLSUFFIX = l MANNSUFFIX = n MANSUFFIX = $(MAN1SUFFIX) MAN1DIR = $(MANSOURCEPATH)$(MAN1SUFFIX) MAN2DIR = $(MANSOURCEPATH)$(MAN2SUFFIX) MAN3DIR = $(MANSOURCEPATH)$(MAN3SUFFIX) MAN4DIR = $(MANSOURCEPATH)$(MAN4SUFFIX) MAN5DIR = $(MANSOURCEPATH)$(MAN5SUFFIX) MAN6DIR = $(MANSOURCEPATH)$(MAN6SUFFIX) MAN7DIR = $(MANSOURCEPATH)$(MAN7SUFFIX) MAN8DIR = $(MANSOURCEPATH)$(MAN8SUFFIX) MANLDIR = $(MANSOURCEPATH)$(MANLSUFFIX) MANNDIR = $(MANSOURCEPATH)$(MANNSUFFIX) MANDIR = $(MANSOURCEPATH)$(MANSUFFIX) IMBOOT = imboot DEPEND = makedepend MSUB = msub MKDIRHIER = mkdirhier AR = ar clq CC = cc CPP = /lib/cpp $(STD_CPP_DEFINES) LD = ld LINT = lint LINTLIBFLAG = -o LINTOPTS = -ax -DSYSV LINTLIBS = LN = ln -s MAKE = make MV = mv -f CP = cp CMP = cmp RM = rm -f TAGS = ctags PERL = perl PERLPATH = $(LOCALBINDIR)/perl PERL5 = perl5 PERL5PATH = $(LOCALBINDIR)/perl5 AWK = awk SED = sed COMM = comm CAT = cat SORT = sort UNIQ = uniq CHMOD = chmod CHDIR = cd SENDMAILPATH = /usr/lib/sendmail # Important local programs FIGEN = figen DISTAR = distar # Standard system include file directories, defines, etc. STD_CPP_DEFINES = STD_INCLUDES = -I$(LOCALINCLUDEROOT) STD_DEFINES = -DSYSV STD_LDLIBS = STD_LDFLAGS = -L$(LOCALUSRLIBDIR) # Project-specific include file directories, defines, etc. PROJECT_INCLUDES = PROJECT_DEFINES = PROJECT_LDLIBS = PROJECT_LDFLAGS = LOADERLIBPREFIX = CDEBUGFLAGS = -O CCOPTIONS = ALLINCLUDES = $(INCLUDES) $(PROJECT_INCLUDES) $(STD_INCLUDES) ALLDEFINES = $(STD_DEFINES) $(PROJECT_DEFINES) $(DEFINES) CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLINCLUDES) $(ALLDEFINES) LINTFLAGS = $(LINTOPTS) -DLINT $(ALLINCLUDES) $(ALLDEFINES) EXTRA_LDLIBS = $(LDLIBS) $(PROJECT_LDLIBS) $(STD_LDLIBS) LDOPTS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = install.sh INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 0444 INSTINCMODE = -m 0444 INSTPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTPROGMODE) $(INSTSTRIP) INSTUIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUIDPROGMODE) $(INSTSTRIP) INSTGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTGIDPROGMODE) $(INSTSTRIP) INSTUGIDPROGFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTUGIDPROGMODE) $(INSTSTRIP) INSTSCRIPTFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTSCRIPTMODE) INSTLIBFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTLIBMODE) INSTDATFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTDATMODE) INSTMANFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTMANMODE) INSTINCFLAGS = $(INSTCOPY) $(INSTOWNER) $(INSTGROUP) $(INSTINCMODE) SOELIM = soelim TROFF = groff NROFF = nroff TBL = gtbl EQN = geqn NEQN = neqn PIC = pic MANMACROS = -man MEMACROS = -me MMMACROS = -mm MSMACROS = -mgs # Library link and dependency specifiers BIBSTUFFLIB = -lbibstuff DEPBIBSTUFFLIB = ETMLIB = $(LOADERLIBPREFIX)$(TOP)/libetm.a DEPETMLIB = $(TOP)/libetm.a FPLLIB = -lfpl DEPFPLLIB = FQLLIB = -lfql DEPFQLLIB = GECOSLIB = -lgecos DEPGECOSLIB = LOGMGRLIB = -llogmgr DEPLOGMGRLIB = MEMMGRLIB = -lmemmgr DEPMEMMGRLIB = NDSLIB = -lnds DEPNDSLIB = NIOLIB = -lnio DEPNIOLIB = ORDERLIB = -lorder DEPORDERLIB = SEQNUMLIB = -lseqnum DEPSEQNUMLIB = SIMSCRLIB = -lsimscr DEPSIMSCRLIB = TFMLIB = -ltfm DEPTFMLIB = TSLIB = -ltokenscan DEPTSLIB = PORTLIB = -lport DEPPORTLIB = # Makefile-generating commands and parameters IMBOOT_DEFINES = IMBOOT_CMD = $(IMBOOT) -C $(CONFIGNAME) $(IMBOOT_DEFINES) # ------------------------------------------------------------------------- # Project-specific imake rules # Edit Imake.p-rules to change # ------------------------------------------------------------------------- # Standard imake rules # Edit Imake.rules to change # ------------------------------------------------------------------------- # start of Imakefile # Exception and Termination Manager Makefile # Use "make World" to build the distribution. But before you do that, # look at the files in the config subdirectory to see if you want # to change anything. # Requires imake, makedepend, mkdirhier, and the WRPRC2 imake # configuration files. LIBNAME = etm DEFINES= $(VARARGS_DEFINES) $(SIGNAL_DEFINES) -DHASVOIDTYPE=$(HASVOIDTYPE) LIBSRCS = etm.c LIBOBJS = etm.o TESTSRCS = etmtest.c TESTOBJS = etmtest.o SRCS = $(LIBSRCS) $(TESTSRCS) all:: .c.o: $(RM) $@ $(CC) -c $(CFLAGS) $*.c all:: lib$(LIBNAME).a lib$(LIBNAME).a: $(LIBOBJS) $(RM) $@ $(AR) $@ $(LIBOBJS) clean:: $(RM) lib$(LIBNAME).a lint:: lint.lib$(LIBNAME).a lint.lib$(LIBNAME).a: $(LINT) $(LINTFLAGS) $(LIBSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.lib$(LIBNAME).a"' to "lint sources for lib$(LIBNAME).a help_aux:: @echo "'make "lib$(LIBNAME).a"' to "build the lib$(LIBNAME).a library install:: i.lib$(LIBNAME).a help_aux:: @echo "'make "i.lib$(LIBNAME).a"' to "install lib$(LIBNAME).a i.lib$(LIBNAME).a:: lib$(LIBNAME).a @if [ -d $(LOCALUSRLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALUSRLIBDIR)); fi $(INSTALL) $(INSTLIBFLAGS) lib$(LIBNAME).a $(LOCALUSRLIBDIR)/lib$(LIBNAME).a lintlib:: llib-l$(LIBNAME).ln llib-l$(LIBNAME).ln:: $(LIBSRCS) $(RM) $@ $(LINT) $(LINTLIBFLAG)$(LIBNAME) $(LINTFLAGS) $(LIBSRCS) clean:: $(RM) llib-l$(LIBNAME).ln help_aux:: @echo "'make "llib-l$(LIBNAME).ln"' to "build the llib-l$(LIBNAME).ln lint library install.lint:: i.llib-l$(LIBNAME).ln help_aux:: @echo "'make "i.llib-l$(LIBNAME).ln"' to "install llib-l$(LIBNAME).ln i.llib-l$(LIBNAME).ln:: llib-l$(LIBNAME).ln @if [ -d $(LOCALLINTLIBDIR) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALLINTLIBDIR)); fi $(INSTALL) $(INSTLIBFLAGS) llib-l$(LIBNAME).ln $(LOCALLINTLIBDIR)/llib-l$(LIBNAME).ln # Header file stuff # The trouble with regenerating etm.h directly from etm.h.dist is that it # triggers excessive recompiles. Therefore, an intermediary file is # generated and compared with etm.h. If they don't differ, etm.h isn't # updated. Similarly for etm.internal.h. all:: etm.h etm.h:: etm.h.dist $(MAKE) $(MFLAGS) etm.h.new -@$(CMP) -s etm.h etm.h.new; \ if [ $$? -ne 0 ]; then \ echo "$(MV) "etm.h.new etm.h; \ $(MV) etm.h.new etm.h; \ echo etm.h" updated"; \ else \ echo etm.h" not updated." ; \ fi clean:: $(RM) etm.h help_aux:: @echo "'make "etm.h"' to "build etm.h install:: i.etm.h help_aux:: @echo "'make "i.etm.h"' to "install etm.h i.etm.h:: etm.h @if [ -d $(LOCALINCLUDEROOT) ]; then set +x; \ else (set -x; $(MKDIRHIER) $(LOCALINCLUDEROOT)); fi $(INSTALL) $(INSTINCFLAGS) etm.h $(LOCALINCLUDEROOT)/etm.h depend:: etm.h all:: etm.h.new etm.h.new:: etm.h.dist $(RM) $@ $(MSUB) etm.h.dist > $@ clean:: $(RM) etm.h.new help_aux:: @echo "'make "etm.h.new"' to "build etm.h.new all:: etm.internal.h etm.internal.h:: etm.internal.h.dist $(MAKE) $(MFLAGS) etm.internal.h.new -@$(CMP) -s etm.internal.h etm.internal.h.new; \ if [ $$? -ne 0 ]; then \ echo "$(MV) "etm.internal.h.new etm.internal.h; \ $(MV) etm.internal.h.new etm.internal.h; \ echo etm.internal.h" updated"; \ else \ echo etm.internal.h" not updated." ; \ fi clean:: $(RM) etm.internal.h help_aux:: @echo "'make "etm.internal.h"' to "build etm.internal.h install:: i.etm.internal.h i.etm.internal.h:: @echo etm.internal.h is not installed anywhere. depend:: etm.internal.h all:: etm.internal.h.new etm.internal.h.new:: etm.internal.h.dist $(RM) $@ $(MSUB) etm.internal.h.dist > $@ clean:: $(RM) etm.internal.h.new help_aux:: @echo "'make "etm.internal.h.new"' to "build etm.internal.h.new # test program all:: etmtest help_aux:: @echo "'make "etmtest"' to "build etmtest etmtest: $(TESTOBJS) $(DEPETMLIB) $(RM) $@ $(CC) -o $@ $(TESTOBJS) $(LDOPTS) $(ETMLIB) $(EXTRA_LDLIBS) clean:: $(RM) etmtest lint:: lint.etmtest lint.etmtest: $(LINT) $(LINTFLAGS) $(TESTSRCS) $(LINTLIBS) help_aux:: @echo "'make "lint.etmtest"' to "lint sources for etmtest install:: i.etmtest i.etmtest:: @echo etmtest is not installed anywhere. test:: etmtest -./etmtest 1 -./etmtest 2 -./etmtest 3 -./etmtest 4 -./etmtest 5 -./etmtest 6 all:: World:: @echo "Building "$(PROJECTNAME)", Release "$(PROJECTRELEASE) @echo "" @date @echo "" $(MAKE) $(MFLAGS) Makefile $(MAKE) $(MFLAGS) Makefiles $(MAKE) $(MFLAGS) clean $(MAKE) $(MFLAGS) depend $(MAKE) $(MFLAGS) all @echo "" @date @echo "" @echo "Done building "$(PROJECTNAME) help_aux:: @echo "'make "World"' to "build the entire $(PROJECTNAME) distribution depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(ALLINCLUDES) $(ALLDEFINES) -- $(SRCS) # documentation etm.ps:: etm.ms $(SOELIM) etm.ms | $(TROFF) $(MSMACROS) $(TROFFOPTS) > etm.ps clean:: $(RM) etm.ps help_aux:: @echo "'make "etm.ps"' to "format etm.ps in PostScript # ------------------------------------------------------------------------- # common rules for all Makefiles emptyrule:: clean:: $(RM_CMD) "#"* tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS Makefile:: $(IMBOOT_CMD) $(TOP) $(CURRENT_DIR) help:: @echo "'make Makefile' to rebuild Makefile" @echo "'make all' to make everything" @echo "'make target' to make a single target" @echo "'make depend' to generate header file dependencies" @echo "'make install' to install everything (except manual pages)" @echo "'make install.man' to install all manual pages" @echo "'make i.target' to install a single target" @echo "'make lint' to lint source files" @echo "'make lint.target' to lint source files for a single target" @echo "'make clean' to clean up" @make help_aux help_aux:: # ------------------------------------------------------------------------- # empty rules for directories that do not have SUBDIRS all:: depend:: lint:: install:: @echo "install in $(CURRENT_DIR) done" install.man:: @echo "install.man in $(CURRENT_DIR) done" Makefiles:: # ------------------------------------------------------------------------- # dependencies generated by makedepend # DO NOT DELETE etm.o: /usr/include/stdio.h /usr/include/sys/stdsyms.h /usr/include/signal.h etm.o: /usr/include/sys/signal.h /usr/include/sys/types.h etm.o: /usr/include/stdarg.h /usr/include/varargs.h etm.internal.h etm.h etm.o: /usr/include/stdlib.h etmtest.o: /usr/include/stdio.h /usr/include/sys/stdsyms.h etm.h $(LDFLAGS) $(PROJECT_LDFLAGS) $(STD_LDFLAGS) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *.a .emacs_* tags TAGS make.log MakeOut INSTALL = install.sh INSTCOPY = -c INSTSTRIP = -s INSTOWNER = INSTGROUP = INSTPROGMODE = -m 0755 INSTUIDPROGMODE = -m 04755 INSTGIDPROGMODE = -m 02755 INSTUGIDPROGMODE = -m 06755 INSTSCRIPTMODE = -m 0755 INSTLIBMODE = -m 0644 INSTDATMODE = -m 0444 INSTMANMODE = -m 044etm/etmtest.c010064400017710000151000000057560614747173700152530ustar00junkyarddatamgmt00000400000027/* * etmtest.c - check out Exception and Termination Manager. Also * serves as modest example of ETM use. * * etmtest 1 normal init/shutdown * etmtest 2 test panic recursion detection * etmtest 3 test print routine recursion detection * etmtest 4 use alternate print procedure * etmtest 5 deregistration * etmtest 6 dump core */ # ifdef THINK_C # include # endif # include # include "etm.h" static ETMProcRetType Shutdown1 (); static ETMProcRetType Shutdown2 (); static ETMProcRetType Shutdown5 (); static ETMProcRetType PrintProc3 (); static ETMProcRetType PrintProc4 (); char *usage = "\ Usage:\tetmtest 1\ttest normal initialization and shutdown\n\ \tetmtest 2\ttest panic loop detection\n\ \tetmtest 3\ttest print recursion detection\n\ \tetmtest 4\ttest alternate print procedure\n\ \tetmtest 5\ttest shutdown proc deregistration\n\ \tetmtest 6\ttest core dump generation\n\ "; int main (argc, argv) int argc; char *argv[]; { # ifdef THINK_C argc = ccommand (&argv); # else /* !THINK_C */ if (argc < 2) ETMPanic (usage); # endif /* THINK_C */ switch (atoi (argv[1])) { case 1: printf ("Initializing test 1 (normal initialization/shutdown)\n"); ETMInit (Shutdown1); break; case 2: printf ("Initializing test 2 (panic loop detection)\n"); printf ("(this should be followed by a panic loop message)\n"); ETMInit (Shutdown2); break; case 3: printf ("Initializing test 3 (print recursion detection)\n"); ETMInit ((ETMProcPtr) NULL); ETMSetPrintProc (PrintProc3); ETMMsg ("testing recursion loop detection..."); break; case 4: printf ("Initializing test 4 (alternate print procedure)\n"); ETMInit ((ETMProcPtr) NULL); ETMSetPrintProc (PrintProc4); ETMMsg ("message to alternate print procedure..."); ETMPanic ("panic to alternate print procedure..."); break; case 5: printf ("Initializing test 5 (shutdown proc deregistration)\n"); ETMInit ((ETMProcPtr) NULL); ETMAddShutdownProc (Shutdown5); ETMRemoveShutdownProc (Shutdown5); break; case 6: printf ("Initializing test 6 (core dump generation)\n"); ETMInit ((ETMProcPtr) NULL); ETMSetAbort (1); ETMPanic ("This should be followed by a core dump."); default: ETMPanic (usage); } ETMEnd (); printf ("Exiting...\n"); exit (0); } static ETMProcRetType Shutdown1 () { printf ("Shutting down...\n"); } static ETMProcRetType Shutdown2 () { /* shutdown routines shouldn't call ETMPanic(), so... */ ETMPanic ("This should cause a panic loop"); } static ETMProcRetType Shutdown5 () { printf ("Shutdown5: You should not see this message.\n"); printf ("(if you do, ETM has a bug)\n"); } /* This should result in ETM aborting, since this is the print procedure called by ETM, and itself (erroneously) calls ETM. */ static ETMProcRetType PrintProc3 (s) char *s; { ETMMsg ("%s", s); } /* Alternate print procedure which routes output to multiple destintations. */ static ETMProcRetType PrintProc4 (s) char *s; { printf ("stdout: %s", s); fprintf (stderr, "stderr: %s", s); } etm/README010064400017710000151000000024350632324374500142610ustar00junkyarddatamgmt00000400000027This directory contains source and documentation for Exception and Termination Manager. If you use the Imakefile, you must obtain the WRPRC imake configuration file distribution (Release 2). To build the distribution, try: % make World If that doesn't work, try the following: % imboot -C WRPRC2 % make World If you just use the Makefile you will have to edit some of the variable definitions. Use "make -n" and "make -n install" to see what will happen on your machine first! You'll need to create etm.h from etm.dist by changing ${ETMPROCRETTYPE} to "void" if you have void, or "int" otherwise. If the build fails, see PROBLEMS. The document etm.ms is formatted with the -ms macros. The WRPRC2 configuration distribution is available via the World Wide Web or by anonymous ftp: http://www.primate.wisc.edu/software/imake-stuff ftp://ftp.primate.wisc.edu/software/imake-stuff 02 Jul 91 Paul DuBois dubois@primate.wisc.edu 10 Jul 90 Release 1.00 26 Sep 90 Release 1.01 04 Oct 90 Release 1.02 26 Jun 91 Release 1.03 minor changes + creation of etm.h. 21 Jul 91 Release 1.04 See Changes-1.04 17 Sep 91 Release 1.05 See Changes-1.05 07 Jul 92 Release 1.06 See Changes-1.06 16 Jul 92 Release 1.07 See Changes-1.07 01 Sep 93 Release 1.08 See Changes-1.08 10 Apr 97 Release 1.09 See Changes-1.09 etm/Imakefile010064400017710000151000000033370622557511400152130ustar00junkyarddatamgmt00000400000027XCOMM Exception and Termination Manager Makefile XCOMM Use "make World" to build the distribution. But before you do that, XCOMM look at the files in the config subdirectory to see if you want XCOMM to change anything. XCOMM Requires imake, makedepend, mkdirhier, and the WRPRC2 imake XCOMM configuration files. LIBNAME = etm DEFINES= $(VARARGS_DEFINES) $(SIGNAL_DEFINES) -DHASVOIDTYPE=$(HASVOIDTYPE) LIBSRCS = etm.c LIBOBJS = etm.o TESTSRCS = etmtest.c TESTOBJS = etmtest.o SRCS = $(LIBSRCS) $(TESTSRCS) all:: NormalLibraryObjectRule() BuildNormalLibrary($(LIBNAME),$(LIBSRCS),$(LIBOBJS)) InstallLibrary($(LIBNAME),$(LOCALUSRLIBDIR)) BuildLintLibrary($(LIBNAME),$(LIBSRCS)) InstallLintLibrary($(LIBNAME),$(LOCALLINTLIBDIR)) XCOMM Header file stuff XCOMM The trouble with regenerating etm.h directly from etm.h.dist is that it XCOMM triggers excessive recompiles. Therefore, an intermediary file is XCOMM generated and compared with etm.h. If they don't differ, etm.h isn't XCOMM updated. Similarly for etm.internal.h. FileFromIntermediary(etm.h,etm.h.new,etm.h.dist) InstallIncludeFile(etm.h,$(LOCALINCLUDEROOT)) depend:: etm.h FileFromMsubTemplate(etm.h.new,etm.h.dist,NullArg) FileFromIntermediary(etm.internal.h,etm.internal.h.new,etm.internal.h.dist) FakeInstallFile(etm.internal.h) depend:: etm.internal.h FileFromMsubTemplate(etm.internal.h.new,etm.internal.h.dist,NullArg) XCOMM test program BuildProgram(etmtest,$(TESTSRCS),$(TESTOBJS),$(ETMLIB),$(DEPETMLIB)) FakeInstallFile(etmtest) test:: etmtest -./etmtest 1 -./etmtest 2 -./etmtest 3 -./etmtest 4 -./etmtest 5 -./etmtest 6 SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE)) DependTarget() XCOMM documentation TroffMsToPostScript(etm.ps,etm.ms,NullArg,NullArg) etm/etm.c010064400017710000151000000301360632324472100143240ustar00junkyarddatamgmt00000400000027/* * etm.c - Exception and Termination Manager * * 10 Jul 90 Paul DuBois dubois@primate.wisc.edu * * 10 Jul 90 V1.0. * - Created. * 26 Sep 90 V1.01. * - Allow alternate error message printer. This is * useful, e.g., for servers that want to use syslog instead of * stderr, or programs that want to send messages to multiple * destinations. * 04 Oct 90 V1.02. * - Allow exit status code to be modified. Mail servers * that panic otherwise exit with status 1, which causes sendmail * to return an extra error messsage to the person sending the * mail. Making the exit status 0 fixes this. * 27 Jun 91 V1.03. * - Created etm.h, other minor fixes. * 23 Jul 91 V1.04. * - ETMMsg() added. * 17 Sep 91 V1.05. * - ETMShutdownDeregister() added. More complete typecasting. * 02 Jun 92 V1.06. * - Yet more typing. Some function renaming, and a few new ones added. * 07 Jul 92 * - Added ETMSetAbort(), which can be used to cause ETMPanic() to dump * core dump after it prints its message. This can sometimes be useful * for debugging. * 10 Apr 97 V1.09 * - Move fflush(stdout)/fflush(stderr) into PrintMsg() so that it's * done uniformly. */ /* * This isn't quite right, since some ANSI systems are missing * stdarg.h. */ # if defined(__STDC__) || defined(THINK_C) # define STDARGS # endif /* __STDC__, THINK_C */ /* Include stdarg.h or varargs.h if present, with the former taking precedence. */ # include # include # include # ifdef STDARGS # include # else /* !STDARGS */ # ifdef VARARGS # include # endif /* VARARGS */ # endif /* STDARGS */ # include "etm.internal.h" # include "etm.h" # define bufSiz 1024 # if !HASVOIDTYPE # define void int # endif /* Determinal signal-handling routine return type */ # if SIGNALRETURNSINT # define SIGRET int # else # define SIGRET void # endif /* This horrible mess makes ETM (try to) use the proper underlying types for memory allocation that are appropriate for the system on which it's compiled. */ # if defined(__STDC__) || defined(SYSV) # if defined(__STDC__) # include # else /* SYSV */ # include # endif /* __STDC__ vs. SYSV */ # define allocPtrType void # define allocSizeType size_t # else /* !SYSV */ # define allocPtrType char # define allocSizeType unsigned # ifndef THINK_C extern allocPtrType *malloc (); # endif /* THINK_C */ # endif /* __STDC, SYSV */ # define mymalloc(x) malloc ((allocSizeType) (x)) # define myfree(x) free ((allocPtrType *) (x)) /* Private routines */ static ETMProcRetType Catch (); static SIGRET CatchManager (); static ETMProcRetType PrintMsg (); typedef struct ETMShutdownProc ETMShutdownProc; typedef struct ETMSigCatcher ETMSigCatcher; struct ETMShutdownProc { ETMProcPtr sdProc; ETMShutdownProc *nextShutdown; }; struct ETMSigCatcher { int signo; ETMProcPtr sigProc; ETMSigCatcher *nextCatcher; }; static ETMShutdownProc *sdProcList = (ETMShutdownProc *) NULL; static ETMSigCatcher *catcherList = (ETMSigCatcher *) NULL; static int exitStatus = 1; static int exitAbort = 0; /* Initialize signal catchers for signals that normally cause an exit, sets up the application's cleanup routine. */ ETMProcRetType ETMInit (p) ETMProcPtr p; { /* register application-specific cleanup routine */ ETMAddShutdownProc (p); /* register catchers for several common signals */ # ifdef SIGHUP ETMSetSignalProc (SIGHUP, Catch); # endif # ifdef SIGINT ETMSetSignalProc (SIGINT, Catch); # endif # ifdef SIGQUIT ETMSetSignalProc (SIGQUIT, Catch); # endif # ifdef SIGILL ETMSetSignalProc (SIGILL, Catch); # endif # ifdef SIGBUS ETMSetSignalProc (SIGBUS, Catch); # endif # ifdef SIGSEGV ETMSetSignalProc (SIGSEGV, Catch); # endif # ifdef SIGSYS ETMSetSignalProc (SIGSYS, Catch); # endif # ifdef SIGTERM ETMSetSignalProc (SIGTERM, Catch); # endif /* less likely, perhaps, but worth catching... */ # ifdef SIGFPE ETMSetSignalProc (SIGFPE, Catch); # endif # ifdef SIGPIPE ETMSetSignalProc (SIGPIPE, Catch); # endif } /* Invoke all the shutdown routines. Called either by application for normal shutdown, or by ETMPanic() when an exceptional condition occurs. */ ETMProcRetType ETMEnd () { ETMShutdownProc *sd; for (sd = sdProcList; sd != (ETMShutdownProc *) NULL; sd = sd->nextShutdown) { if (sd->sdProc != (ETMProcPtr) NULL) (*(sd->sdProc)) (); } } /* Register a shutdown routine. These are placed in a list in reverse order because shutdown is in reverse order of initialization. */ ETMProcRetType ETMAddShutdownProc (p) ETMProcPtr p; { ETMShutdownProc *sd; if (p == (ETMProcPtr) NULL) return; if ((sd = (ETMShutdownProc *) mymalloc (sizeof (ETMShutdownProc))) == (ETMShutdownProc *) NULL) ETMPanic ("ETMAddShutdownProc: out of memory"); sd->sdProc = p; sd->nextShutdown = sdProcList; sdProcList = sd; } /* Deregister a shutdown routine. This can be used when a routine only needs to be called if a panic occurs in a certain piece of code, but not after that code finishes. The algoritm is stupid because all it does it NULL out the proc pointer; it should really take the record out of the list. */ ETMProcRetType ETMRemoveShutdownProc (p) ETMProcPtr p; { ETMShutdownProc *sd = (ETMShutdownProc *) NULL, *sd2; if (sdProcList == (ETMShutdownProc *) NULL) /* shouldn't happen */ return; if (p == sdProcList->sdProc) /* first in list */ { sd = sdProcList; sdProcList = sdProcList->nextShutdown; } else { sd2 = sdProcList; while ((sd = sd2->nextShutdown) != (ETMShutdownProc *) NULL) { if (p == sd->sdProc) { sd2->nextShutdown = sd->nextShutdown; break; } sd2 = sd; } } if (sd != (ETMShutdownProc *) NULL) /* found it */ myfree (sd); } /* Register a signal-catching routine. This can be either for a new (currently not caught) signal, or to reset the catcher for a signal that's already being caught. An attempt is made to enhance portability by specifying that all handlers return ETMProcRetType. A single proxy routine, CatchManager(), which is declared properly according to the signal semantics of the compilation environment, actually catches all signals and determines which routine to invoke based on which signal occurred. This insulates programs from the vagaries of the signal-handling-proc return type mess. I hope. p == ETMSigDefault : restore default signal action p == ETMSigIgnore : ignore signal */ ETMProcRetType ETMSetSignalProc (signo, p) int signo; ETMProcPtr p; { ETMSigCatcher *cp; for (cp = catcherList; cp != (ETMSigCatcher *) NULL; cp = cp->nextCatcher) { if (cp->signo == signo) /* resetting existing catcher */ { if (p == ETMSigIgnore) { (void) signal (signo, SIG_IGN); p = (ETMProcPtr) NULL; /* to disable catcher struct */ } else if (p == ETMSigDefault) { (void) signal (signo, SIG_DFL); p = (ETMProcPtr) NULL; /* to disable catcher struct */ } cp->sigProc = p; return; } } /* catching a signal that's not currently being caught */ if (p == ETMSigIgnore) { (void) signal (signo, SIG_IGN); return; } else if (p == ETMSigDefault) { (void) signal (signo, SIG_DFL); return; } if ((cp = (ETMSigCatcher *) mymalloc (sizeof (ETMSigCatcher))) == (ETMSigCatcher *) NULL) ETMPanic ("ETMSetSignalProc: out of memory"); cp->signo = signo; cp->sigProc = p; cp->nextCatcher = catcherList; catcherList = cp; (void) signal (signo, CatchManager); } ETMProcPtr ETMGetSignalProc (signo) { ETMSigCatcher *cp; for (cp = catcherList; cp != (ETMSigCatcher *) NULL; cp = cp->nextCatcher) { if (cp->signo == signo) /* found it */ return (cp->sigProc); } /* not found, ignored, or default */ return ((ETMProcPtr) NULL); } /* All signals come through here. CatchManager() determines which catch routine should be invoked based on the signal number. */ static SIGRET CatchManager (signo) int signo; { ETMSigCatcher *cp; for (cp = catcherList; cp != (ETMSigCatcher *) NULL; cp = cp->nextCatcher) { /* if catcher wasn't disabled and it's right signal... */ if (cp->sigProc != (ETMProcPtr) NULL && cp->signo == signo) { (*(cp->sigProc)) (signo); break; } } if (cp == (ETMSigCatcher *) NULL) ETMPanic ("caught signal %d; program terminated", signo); } /* Default signal catching routine. Triggers a panic, which causes ETMEnd() to be executed. */ static ETMProcRetType Catch (signo) int signo; { ETMPanic ("caught signal %d; program terminated", signo); } /* ETMPanic - print message and die with status 1. Takes variable argument lists. Uses stdargs/varargs on those systems that have it. Try to avoid getting into a panic loop, whereby one of the shutdown routines calls panic. In that case just print a message and exit immediately: that is probably a bug in the application, not ETM. Flushes stdout before stderr so that error output appears after any pending application output. */ static int loop = 0; static char *loopMsg = "\r\nETMPanic loop; one of your shutdown routines panics!\r\n"; # ifdef STDARGS ETMProcRetType ETMPanic (char *fmt, ...) { va_list args; char buf[bufSiz]; if (loop++) { PrintMsg (loopMsg); exit (exitStatus); } ETMEnd (); va_start (args, fmt); vsprintf (buf, fmt, args); va_end (args); strcat (buf, "\n"); PrintMsg (buf); if (exitAbort) { /* deregister catcher for abort() signal to avoid panic loop */ ETMSetSignalProc (abortSignal, ETMSigDefault); abort (); } exit (exitStatus); } # else /* !STDARGS */ # ifdef VARARGS ETMProcRetType ETMPanic (va_alist) va_dcl { va_list args; char *fmt, buf[bufSiz]; if (loop++) { PrintMsg (loopMsg); exit (exitStatus); } ETMEnd (); va_start (args); fmt = va_arg (args, char *); vsprintf (buf, fmt, args); va_end (args); strcat (buf, "\n"); PrintMsg (buf); if (exitAbort) { /* deregister catcher for abort() signal to avoid panic loop */ ETMSetSignalProc (abortSignal, ETMSigDefault); abort (); } exit (exitStatus); } # else /* !VARARGS */ ETMProcRetType ETMPanic (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) char *fmt; char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9; { char buf[bufSiz]; if (loop++) { PrintMsg (loopMsg); exit (exitStatus); } ETMEnd (); sprintf (buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); strcat (buf, "\n"); PrintMsg (buf); if (exitAbort) { /* deregister catcher for abort() signal to avoid panic loop */ ETMSetSignalProc (abortSignal, ETMSigDefault); abort (); } exit (exitStatus); } # endif /* VARARGS */ # endif /* STDARGS */ /* * ETMMsg - print message and return. Takes variable argument * lists. Uses stdargs/varargs on those systems that have it. */ # ifdef STDARGS ETMProcRetType ETMMsg (char *fmt, ...) { va_list args; char buf[bufSiz]; va_start (args, fmt); vsprintf (buf, fmt, args); va_end (args); strcat (buf, "\n"); PrintMsg (buf); } # else /* !STDARGS */ # ifdef VARARGS ETMProcRetType ETMMsg (va_alist) va_dcl { va_list args; char *fmt, buf[bufSiz]; va_start (args); fmt = va_arg (args, char *); vsprintf (buf, fmt, args); va_end (args); strcat (buf, "\n"); PrintMsg (buf); } # else /* !VARARGS */ ETMProcRetType ETMMsg (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) char *fmt; char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9; { char buf[bufSiz]; sprintf (buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); strcat (buf, "\n"); PrintMsg (buf); } # endif /* VARARGS */ # endif /* STDARGS */ static ETMProcPtr printProc = (ETMProcPtr) NULL; ETMProcRetType ETMSetPrintProc (p) ETMProcPtr p; { printProc = p; } ETMProcPtr ETMGetPrintProc () { return ((ETMProcPtr) printProc); } static char *pLoopMsg = "\r\nETM print routine recursion detected!\r\n"; static ETMProcRetType PrintMsg (s) char *s; { static int loop = 0; fflush (stdout); fflush (stderr); if (loop++) { fprintf (stderr, "%s", pLoopMsg); fflush (stderr); exit (exitStatus); } if (printProc == (ETMProcPtr) NULL) /* default is stderr */ fprintf (stderr, "%s", s); else (*printProc) (s); fflush (stderr); --loop; } ETMProcRetType ETMSetExitStatus (status) int status; { exitStatus = status; } int ETMGetExitStatus () { return (exitStatus); } ETMProcRetType ETMSetAbort (abortVal) int abortVal; { exitAbort = abortVal; } int ETMGetAbort () { return (exitAbort); } etm/etm.ms010064400017710000151000000410520632324656200145250ustar00junkyarddatamgmt00000400000027.\" .\" ${TBL} file | ${TROFF} ${MSMACROS} | ${PRINTER} .\" .\" This should be a constant-width font available at your site. .\" If there isn't one, .fp 4 I is a suitable substitute. .fp 4 CW .\" revision date - change whenever this file is edited .ds RD 10 April 1997 .nr PO 1.2i \" page offset 1.2 inches .nr PD .7v \" inter-paragraph distance .\" .EH 'Exception and Termination Manager'- % -'' .OH ''- % -'Exception and Termination Manager' .OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr' .\" .\" I - italic font (taken from -ms and changed) .de I .nr PQ \\n(.f .if t \&\\$3\\f2\\$1\\fP\&\\$2 .if \\n(.$=0 .ft 2 .if n .if \\n(.$=1 \&\\$1 .if n .if \\n(.$>1 \&\\$1\c .if n .if \\n(.$>1 \&\\$2 .. .\" .\" B - boldface font (taken from -ms and changed) .de B .nr PQ \\n(.f .if t \&\\$3\\f3\\$1\\fP\&\\$2 .if \\n(.$=0 .ft 3 .if n .if \\n(.$=1 \&\\$1 .if n .if \\n(.$>1 \&\\$1\c .if n .if \\n(.$>1 \&\\$2 .. .\" .\" Cw - constant width font .de Cw .nr PQ \\n(.f .if t \&\\$3\\f4\\$1\\fP\&\\$2 .if \\n(.$=0 .ft 4 .if n .if \\n(.$=1 \&\\$1 .if n .if \\n(.$>1 \&\\$1\c .if n .if \\n(.$>1 \&\\$2 .. .\" the first IS should be preceded by .RS and the text associated .\" with the last IE should be followed by .RE. .\" .de IS \" interface routine description header start .RE .DS L .ta .5i +.5i +.5i .Cw .. .de IE \" interface routine description header end .DE .ft R .RS .. .TL .ps +2 ETM \*- A Program Exception and Termination Manager .sp .5v .ps .AU Paul DuBois .H*ahref mailto:dubois@primate.wisc.edu dubois@primate.wisc.edu .H*aend .AI .H*ahref http://www.primate.wisc.edu/ Wisconsin Regional Primate Research Center .H*aend Revision date:\0\0\*(RD .\" .H*toc*title "Table of Contents" .\" .NH Introduction .LP This document describes Exception and Termination Manager (ETM), a simple(-minded) library to manage exceptional conditions that arise during program execution, and to provide for orderly program shutdown. .LP There are at least a couple of approaches one may adopt for handling error conditions within an application: .IP \(bu Have functions always return a value and have all callers test the return value and respond accordingly. .IP \(bu Force the program to give up and exit early. .LP Each approach has strengths and weaknesses. A difficulty with the first is that actions composed of many subsidiary actions, each of which may themselves succeed or fail, can easily become very unwieldy when an attempt is made to handle all possible outcomes. However, such a program will also continue in the face of extreme adversity. .LP An advantage of the second approach is that it is, conceptually at least, simpler to let a program die when a serious error occurs. The difficulty lies in making sure the program cleans up and shuts down properly before it exits. This can be a problem especially when a program uses a number of independent modules which can each encounter exceptional conditions and need to be shut down, and which may know nothing of each other. ETM is designed to alleviate the difficulties of this second approach. .LP The general architecture assumed for this discussion is that of an application which uses zero or more subsystems which may be more or less independent of each other, and which may each require initialization and/or termination. Also, other application-specific initialization and/or termination actions may need to be performed which are unrelated to those of the subsystems, e.g., temporary files created at the beginning of the application need to be removed before final termination, network connections need to be shut down, terminal state needs to be restored. .LP Ideally, when an application executes normally, it will initialize, perform the main processing, then shut down in an orderly fashion. This does not always occur. Exceptional conditions may be detected which necessitate a ``panic'' (an immediate program exit) because processing cannot continue further, or because it is judged too burdensome to try to continue. .LP An individual subsystem may be easily written such that a panic within itself causes its own shutdown code to be invoked. It is more difficult to arrange for other subsystems to be notified of the panic so that they can shut down as well, since the subsystem in which the panic occurs may not even know about them. .LP An additional difficulty is that some exceptions may occur for reasons not related to algorithmically detectable conditions. For instance, the user of an application may cause a signal to be delivered to it at any time. This has nothing to do with normal execution and cannot be predicted. .LP The goals of ETM are thus twofold: .IP (1) Panics triggered anywhere within an application or any of its subsystems should cause orderly shutdown of all subsystems and the application itself. .IP (2) Signals that normally terminate a program should be caught and trigger a panic to allow shutdown as per (1). .NH Processing Model .LP The model used by ETM is that the application initializes subsystems in the order required by any dependencies among them, and then terminates them in the reverse order. The presumption here is that if subsystem .I ss2 is dependendent upon subsystem .I ss1 , then .I ss1 should be initialized first and terminated last; the dependency is unlikely to make it wise to shut down .I ss1 before .I ss2 . .LP ETM must itself be initialized before any other subsystem which uses it. The initialization call, .Cw ETMInit() , takes as an argument a pointer to a routine which performs any application-specific cleanup not related to its subsystems, or .Cw NULL if there is no such routine. .LP Each of the subsystems should then be initialized. A subsystem's initialization routine should call .Cw ETMAddShutdownProc() to register its own shutdown routine with ETM, if there is one. (Some subsystems may require no explicit initialization or termination. However, if there is a shutdown routine, you should at least call .Cw ETMAddShutdownProc() to register it.) .LP When the program detects an exceptional condition, it calls .Cw ETMPanic() to describe the problem and exit. .Cw ETMPanic() is also called automatically when a signal is caught. A message is printed, and all the shutdown routines that have been registered are automatically executed, including the application-specific one. .LP ETM is designed to handle shutting down under unusual circumstances, but it also works well for terminating normally. Instead of calling .Cw ETMPanic() , the application calls .Cw ETMEnd() . This is much like calling .Cw ETMPanic() , except that no error message is printed, and .Cw ETMEnd() returns to the caller. which takes care of calling all the shutdown routines that have been registered. .LP It is evident that the functionality provided by ETM is somewhat like that of the .Cw atexit() routine provided on some systems. Some differences between the two are: .IP \(bu .Cw atexit() is either built in or not available. ETM can be put on any system to which it can be ported (extent unknown, but includes at least SunOS, Ultrix, Mips RISC/os and THINK C). .IP \(bu ETM is more suited for handling exceptional conditions. .IP \(bu ETM shutdown routines can be installed and removed later. .Cw atexit() provides only for installation (although you could simulate removal by setting a flag which shutdown routines examine to see whether to execute or not). .LP Here is a short example of how to set up and shut down using ETM. .LP .DS L .ta .3i +.5i +1.5i .Cw main () { \&. . . ETMInit (Cleanup); /* register application-specific cleanup */ SS1Init (); /* registers SS1End() for shutdown */ SS2Init (); /* registers SS2End() for shutdown */ SS3Init (); /* registers SS3End() for shutdown */ .sp .5v \&...\0main processing here\0... .sp .5v ETMEnd (); /* calls SS3End (), SS2End () and SS1End () */ exit (0); } .ft R .DE .LP Subsystems that are themselves built on other subsystems may follow this model, except that they would not call .Cw ETMInit() or .Cw ETMEnd() . .LP If there is no special initialization or shutdown activity, and you don't care about catching signals, it is not necessary to call .Cw ETMInit() and .Cw ETMEnd() . The application may still call .Cw ETMPanic() to print error messages and terminate. (Even if the application does use .Cw ETMInit() and .Cw ETMEnd() , it is safe to call .Cw ETMPanic() before any initialization has been done, because nothing needs to be shut down at that point yet.) .LP If ETM itself encounters an exceptional condition (e.g., it cannot allocate memory when it needs to), it will\*-of course\*-trigger a panic. This should be rare, but if it occurs, ETM will generate a message indicating what the problem was. .NH Caveats .LP Shutdown routines shouldn't call .Cw ETMPanic() , since .Cw ETMPanic() causes shutdown routines to be executed. ETM detects loops of this sort, but their occurrence indicate a flaw in program logic. Similarly, if you install a print routine to redirect ETM's output somewhere other than .Cw stderr , the routine shouldn't call ETM to print any messages. .LP .I "kill \-9" is uncatchable and there's nothing you can do about it. .NH Programming Interface .LP The ETM library should be installed in .Cw /usr/lib/libetm.a or local equivalent, and applications should link in the ETM library with the .Cw \-letm flag. Source files that use ETM routines should include .Cw etm.h . If you use ETM functions in a source file without including .Cw etm.h , you will get undefined symbol errors at link time. .LP The abstract types .Cw ETMProcRetType and .Cw ETMProcPtr may be used for declaring and passing pointers to functions that are passed to ETM routines. By default these will be .Cw void and .Cw void(*)() , but on deficient systems with C compilers lacking void pointers they will be .Cw int and .Cw int(*)() , the usual C defaults for functions. .LP These types make it easier to declare properly typed functions and .Cw NULL pointers. For instance, if you don't pass any shutdown routine to .Cw ETMInit() , use .LP .DS .Cw ETMInit ((ETMProcPtr) NULL); .ft R .DE .LP If you do, use .LP .DS .Cw ETMProcRetType ShutdownProc () { . . . } \&. . . main () { \&. . . ETMInit (ShutdownProc); \&. . . } .ft R .DE .LP Descriptions of the ETM routines follow. .RS .IS ETMProcRetType ETMInit (p) ETMProcPtr p; .IE Registers the application's cleanup routine .Cw p (which should be .Cw NULL if there is none) and registers default handlers for the following signals (all of which normally cause program exit): .Cw SIGHUP , .Cw SIGINT , .Cw SIGQUIT , .Cw SIGILL , .Cw SIGSYS , .Cw SIGTERM , .Cw SIGBUS , .Cw SIGSEGV , .Cw SIGFPE , .Cw SIGPIPE . If .Cw p is not .Cw NULL , it should point to a routine that takes no arguments and returns no value. .IS ETMProcRetType ETMEnd () .IE Causes all registered shutdown routines to be executed. The application may then exit normally with .Cw exit(0) . .IS ETMProcRetType ETMPanic (fmt, ...) char *fmt; .IE .Cw ETMPanic() is called when a panic condition occurs, and the program cannot continue. The arguments are as those for .Cw printf() and are used to print a message after shutting down all subsystems and executing the application's cleanup routine, and before calling .Cw exit() . .Cw ETMPanic() adds a newline to the end of the message. .LP .Cw ETMPanic() may be called at any time, including prior to calling .Cw ETMInit() , but only those shutdown routines which have been registered are invoked. .LP A common problem with applications that encounter exceptional conditions such as segmentation faults is that you often don't see all the output your application has produced. This is because .Cw stdout is often buffered. To alleviate this problem, .Cw stdout is flushed before any message is printed, so that any pending application output is flushed and appears before the error message. .LP By default, .Cw ETMPanic() prints the message on .Cw stderr . This behavior may be modified with .Cw ETMSetPrintProc() . .LP The default .Cw exit() value is 1. This may be modified with .Cw ETMSetExitStatus() . .IS ETMProcRetType ETMMsg (fmt, ...) char *fmt; .IE .Cw ETMMsg() is like .Cw ETMPanic() except that it just prints the message and returns. It is useful in that if panic message output has been redirected somewhere other than .Cw stderr (e.g., to the system log), .Cw ETMMsg() will write its output there, too. The application does not need to know whether such redirection has taken place. .LP .Cw ETMMsg() may be called at any time, including prior to calling .Cw ETMInit() . .IS ETMProcRetType ETMAddShutdownProc (p) ETMProcPtr p; .IE Register a shutdown routine with ETM. This is normally called within a subsystem's initialization routine. .Cw p should point to a routine that takes no arguments and returns no value. .IS ETMProcRetType ETMRemoveShutdownProc (p) ETMProcPtr p; .IE Deregister a previously-registered shutdown routine with ETM. This is useful for routines that only need to be registered temporarily, e.g., during execution of some piece of code that temporarily creates some file that needs to be removed if the program crashes, but which removes it itself if execution proceeds normally. .IS ETMProcRetType ETMSetSignalProc (signo, p) int signo; ETMProcPtr p; .IE Register a signal-catching routine to override ETM's default. The routine will be called with one argument, the signal number. It should return no value, .ft I regardless of the usual return type of signal handler routines on your system. .ft R (When ETM is configured on your system, it knows the proper return value for .Cw signal() but hides differences among systems from your application so you don't have to think about it.) .LP To return a signal to its default action or to cause a signal to be ignored, pass the following values for .Cw p (these are defined in .Cw etm.h ): .LP .DS .ta 2i \f4ETMSigIgnore\fP signal is ignored \f4ETMSigDefault\fP signal default action is restored .DE .IS ETMProcPtr ETMGetSignalProc (signo) int signo; .IE Returns the function current used to catch signal .Cw signo , or .Cw NULL if the signal is handled with the default action or being ignored (it's not possible to distinguish between the last two cases). .IS ETMProcRetType ETMSetPrintProc (p) ETMProcPtr p; .IE This routine is used to register a procedure that ETM can use to print messages. The default is to send messages to .Cw stderr , which is appropriate for most programs. Applications may prefer to send messages elsewhere. For instance, non-interactive programs like network servers might send them to .Cw syslog() instead. Or a program may wish to send messages to multiple destinations. .LP To override the default, pass the address of an alternate print routine to .Cw ETMSetPrintProc() . The routine should take one argument, a pointer to a character string, and return no value. The argument will be the fully formatted panic message, complete with a newline on the end. To restore the default, pass .Cw NULL . .LP The printing routine shouldn't call .Cw ETMPanic() or .Cw ETMMsg() or a loop will be detected and ETM will conveniently panic as a service to let you know you have a logic error in your program. .IS ETMProcPtr ETMGetPrintProc () .IE Returns a pointer to the current printing function, .Cw NULL if the default is being used. .IS ETMProcRetType ETMSetExitStatus (status) int status; .IE This routine is used to register the status value that is passed to .Cw exit() when a panic occurs. The default is 1. For some applications it is desirable to return a different value. For instance, a mail server that processes messages may send back a message to the person who sent mail when a request is erroneous, then panic (perhaps by writing a message to the system log). On some systems, if a program invoked to handle mail returns non-zero, the mailer will send another message to that person stating that there was a problem handling the mail. This extra message is unnecessary, and can be suppressed by registering an exit status of 0. .LP If .Cw ETMSetAbort() has been called to force an .Cw abort() on a panic, the exit status is not returned. .IS int ETMGetExitStatus () .IE Returns the current exit status which will be returned if a panic occurs. .IS ETMProcRetType ETMSetAbort (val) int val; .IE Calling this function with a non-zero value of .Cw val causes ETM to try to generate a core image when .Cw ETMPanic() is called (after the panic message is printed). This can sometimes be useful for debugging. If .Cw val is zero, image generation is suppressed. The default is no image. .LP .Cw ETMSetAbort() is meaningless on systems with no concept of a core image. Also, if you install a signal catcher for .Cw SIGABRT , you may end up in a panic loop. .IS int ETMGetAbort () int val; .IE Return current image generation value. .\" this RE should follow the last function description .RE o the caller. which takes care of calling all the shutdown routines that have been registered. .LP It is evident that the functionality provided by ETM is somewhat like that of the .Cw atexit() routine provided on some systems. Some differences between the two are: .IP \(bu .Cw atexit() is either built in or not available. ETM can be put on any system to which it can be ported (extent unknown, but includes at least SunOS, Ultrix, Mips RISC/os and THINK C). .IP \(bu etm/Changes-1.04010064400017710000151000000004230614246400300152360ustar00junkyarddatamgmt00000400000027Changes to ETM distribution for release 1.04. Flush stdout before stderr (not other way around) so that pending application output will appear before the error message. Otherwise the error message can come out before pending output and not be easily seen. Added ETMMsg(). etm/Changes-1.05010064400017710000151000000001600614246400300152350ustar00junkyarddatamgmt00000400000027Changes to ETM distribution for release 1.05. Added ETMShutdownDeregister(). Added more complete typecasting. etm/config/004077500017710000151000000000000616727702200146505ustar00junkyarddatamgmt00000400000027etm/config/Mips.p-cf010066400017710000151000000003670632324465500163320ustar00junkyarddatamgmt00000400000027/* * Signal used in the abort() call appears to differ depending * on whether System V or BSD environment is being used... * (At least for RISC/OS 4.01.) */ # if SystemV # define AbortSignal SIGABRT # else # define AbortSignal SIGILL # endif etm/config/ultrix.p-cf010066400017710000151000000004150614246400400167320ustar00junkyarddatamgmt00000400000027/* * If you compile under System V or POSIX environment, this might need to * be SIGIOT. */ # define AbortSignal SIGILL /* * This appears to be necessary for Ultrix 3.1. * It can be YES for Ultrix 4.2, and perhaps any 4.X release... */ # define HasVoidType NO etm/config/Imake.p-params010064400017710000151000000016400632324370200173240ustar00junkyarddatamgmt00000400000027# ifndef ProjectName # define ProjectName Exception and Termination Manager # endif # ifndef ProjectMajorRelease # define ProjectMajorRelease 1 # endif # ifndef ProjectMinorRelease # define ProjectMinorRelease 09 # endif /* * Override default values of EtmLib/DepEtmLib, since they refer * to the already-installed library. */ #ifndef EtmLib #define EtmLib $(LOADERLIBPREFIX)$(TOP)/libetm.a #endif #ifndef DepEtmLib #define DepEtmLib $(TOP)/libetm.a #endif /* * put "#define HasVoidType NO" in platform.p-cf if your compiler * doesn't know about both void and void*. */ # ifndef HasVoidType # define HasVoidType YES /* be optimistic */ # endif /* * The signal used by the abort() system call */ # ifndef AbortSignal # define AbortSignal SIGABRT # endif # if HasVoidType HASVOIDTYPE = 1 ETMVOIDTYPE = void # else HASVOIDTYPE = 0 ETMVOIDTYPE = int # endif ABORTSIGNAL = AbortSignal EtmLib #define DepEtmLib $(TOP)/libetm.a #endif /* * put "#define HasVoidType NO" in platform.etm/Changes-1.06010064400017710000151000000051710614246400400152460ustar00junkyarddatamgmt00000400000027Changes to ETM distribution for release 1.06. Most important: Function names are actually defined as the name with a trailing underscore. This causes failure at link time as a reminder that etm.h wasn't included in source file in which it was needed. Because of this, libraries that use etm should be recompiled and reinstalled, or programs using those libraries will get "undefined symbol" errors for ETM function names. Added ETMProcRetType and ETMProcPtr abstract types to decrease readability of source code and scare potential users off. The built-in types underlying these are configured at build time to help portability to systems without void or void* type. Note that this does NOT change the interface in any way for current users, since anyone using previous releases must have already had void, and that is still the default underlying type. Bug fix: Added test for printing recursion in PrintMsg, so that if a function is registered as the print function and itself calls ETMMsg() or ETMPanic(), the (infinite) recursion is detected. Uses stdargs instead of varargs if present. (Actually, this is only true for ANSI and for THINK C at the moment; the configuration files need some work to select this automatically for other systems.) I finally changed the routine names I was sick of to ones that seem more descriptive (if unforunately even longer in some cases): ETMShutdownRegister() -> ETMAddShutdownProc() ETMShutdownDeregister() -> ETMRemoveShutdownProc() ETMSignalRegister() -> ETMSetSignalProc() ETMPrintRegister() -> ETMSetPrintProc() ETMStatusRegister() -> ETMSetExitStatus() This *does* change the user interface. Backward compatibility #defines for the old names are present in etm.h so that programs written for earlier ETM releases should still compile. These will disappear at some later date, however. Added routines ETMGetSignalProc(), ETMGetPrintProc() and ETMGetExitStatus() to make it easier for programs that want to temporarily replace any of these to do so, and then restore them to what they were. Added ETMSetAbort() function to allow core dump generation by ETMPanic(). Can be useful for debugging. ETMGetAbort() returns current setting. Before compiling, it would be useful to examine ProjectGroup.ptmpl and see if the setting of AbortSignal is correct for your system. If not, create a *.pcf file and override the default. Run "etmtest 6" to see if you get a core dump properly or not. Fixed some portability problems relating to compiling under Mips RISC/os in System V environment. etm.h now idempotent; may be included more than once safely. Documentation changes were made to reflect the modifications above. etm/Changes-1.07010064400017710000151000000007050614246400400152450ustar00junkyarddatamgmt00000400000027Changes to ETM distribution for release 1.07. In 1.06, function names were actually defined as the name with a trailing underscore to causes failure at link time as a reminder that etm.h wasn't included in source files in which it was needed. The definitions now use leading underscores. A user will consider library symbols to be part of the system name space and not user name space, so this change is more consistent with that conceptualization. etm/Changes-1.08010064400017710000151000000001320614246400400152400ustar00junkyarddatamgmt00000400000027Changes to ETM distribution for release 1.08. Now uses WRPRC2 imake configuration files. etm/etm.h.dist010064400017710000151000000041650625157556500153130ustar00junkyarddatamgmt00000400000027#ifndef _ETM_H #define _ETM_H /* * etm.h - Exception and Termination Manager header file */ /* * Values that can be passed to ETMSetSignalProc() to turn off signals * or restore to default action. Pretty ugly. Hope no one ever uses * them! (Because depending on the compiler, it's possible these may * actually be the same...) */ # define ETMSigDefault (${ETMVOIDTYPE} (*)())0 # define ETMSigIgnore (${ETMVOIDTYPE} (*)())1 typedef ${ETMVOIDTYPE} ETMProcRetType; typedef ETMProcRetType (*ETMProcPtr) (); /* * These defines cause failure at link time if this header * file wasn't included in each source file using ETM functions. */ # define ETMInit _ETMInit # define ETMEnd _ETMEnd # define ETMAddShutdownProc _ETMAddShutdownProc # define ETMRemoveShutdownProc _ETMRemoveShutdownProc # define ETMSetSignalProc _ETMSetSignalProc # define ETMGetSignalProc _ETMGetSignalProc # define ETMSetPrintProc _ETMSetPrintProc # define ETMGetPrintProc _ETMGetPrintProc # define ETMSetExitStatus _ETMSetExitStatus # define ETMGetExitStatus _ETMGetExitStatus # define ETMSetAbort _ETMSetAbort # define ETMGetAbort _ETMGetAbort # define ETMPanic _ETMPanic # define ETMMsg _ETMMsg /* Public routines */ extern ETMProcRetType ETMInit (); extern ETMProcRetType ETMEnd (); extern ETMProcRetType ETMAddShutdownProc (); extern ETMProcRetType ETMRemoveShutdownProc (); extern ETMProcRetType ETMSetSignalProc (); extern ETMProcPtr ETMGetSignalProc (); extern ETMProcRetType ETMSetPrintProc (); extern ETMProcPtr ETMGetPrintProc (); extern ETMProcRetType ETMSetExitStatus (); extern int ETMGetExitStatus (); extern ETMProcRetType ETMSetAbort (); extern int ETMGetAbort (); #if __STDC__ extern ETMProcRetType ETMPanic (char *fmt,...); extern ETMProcRetType ETMMsg (char *fmt,...); #else extern ETMProcRetType ETMPanic (); extern ETMProcRetType ETMMsg (); #endif /* backward-compatibility defines */ # define ETMShutdownRegister ETMAddShutdownProc # define ETMShutdownDeregister ETMRemoveShutdownProc # define ETMSignalRegister ETMSetSignalProc # define ETMPrintRegister ETMSetPrintProc # define ETMStatusRegister ETMSetExitStatus #endif /* _ETM_H */ etm/etm.internal.h.dist010066400017710000151000000000440614246400400171000ustar00junkyarddatamgmt00000400000027# define abortSignal ${ABORTSIGNAL} etm/Changes-1.09010064400017710000151000000005700632324463000152510ustar00junkyarddatamgmt00000400000027Changes to ETM distribution for release 1.09. Fixed etm.h.dist a little so it works with ANSI C compilers. Fixed usage message in etmtest so it printed tests in correct order. Move fflush(stdout)/fflush(stderr) into PrintMsg() so that it's done uniformly. (It was being done in ETMPanic() but not ETMMsg(), so that output from stdout and stderr could still get mixed up.) etm/PROBLEMS010066400017710000151000000013220616727672600145560ustar00junkyarddatamgmt00000400000027If you find that your C compiler complains about ETMPanic() and ETMMsg() having incorrect definitions, or being redeclared, etc., then probably the wrong declarations of these routines are being selected in etm.h. This file is creatded from etm.h.dist. The relevant lines are: #if __STDC__ extern ETMProcRetType ETMPanic (char *fmt,...); extern ETMProcRetType ETMMsg (char *fmt,...); #else extern ETMProcRetType ETMPanic (); extern ETMProcRetType ETMMsg (); #endif If your C compiler defines __STDC__, but defines it as 0 to indicate incomplete ANSI conformance, the test may fail and the non-prototyped lines here will be used. Try changing the test in etm.h.dist to: #ifdef __STDC__ Then rebuild the distribution. etm/etm.html010066400017710000151000000416420632324663600150630ustar00junkyarddatamgmt00000400000027 ETM -- A Program Exception and Termination Manager

ETM -- A Program Exception and Termination Manager

Paul DuBois
dubois@primate.wisc.edu

Wisconsin Regional Primate Research Center
Revision date: 10 April 1997

Table of Contents


Introduction


This document describes Exception and Termination Manager (ETM), a simple(-minded) library to manage exceptional conditions that arise during program execution, and to provide for orderly program shutdown.

There are at least a couple of approaches one may adopt for handling error conditions within an application:

*
Have functions always return a value and have all callers test the return value and respond accordingly.
*
Force the program to give up and exit early.

Each approach has strengths and weaknesses. A difficulty with the first is that actions composed of many subsidiary actions, each of which may themselves succeed or fail, can easily become very unwieldy when an attempt is made to handle all possible outcomes. However, such a program will also continue in the face of extreme adversity.

An advantage of the second approach is that it is, conceptually at least, simpler to let a program die when a serious error occurs. The difficulty lies in making sure the program cleans up and shuts down properly before it exits. This can be a problem especially when a program uses a number of independent modules which can each encounter exceptional conditions and need to be shut down, and which may know nothing of each other. ETM is designed to alleviate the difficulties of this second approach.

The general architecture assumed for this discussion is that of an application which uses zero or more subsystems which may be more or less independent of each other, and which may each require initialization and/or termination. Also, other application-specific initialization and/or termination actions may need to be performed which are unrelated to those of the subsystems, e.g., temporary files created at the beginning of the application need to be removed before final termination, network connections need to be shut down, terminal state needs to be restored.

Ideally, when an application executes normally, it will initialize, perform the main processing, then shut down in an orderly fashion. This does not always occur. Exceptional conditions may be detected which necessitate a "panic" (an immediate program exit) because processing cannot continue further, or because it is judged too burdensome to try to continue.

An individual subsystem may be easily written such that a panic within itself causes its own shutdown code to be invoked. It is more difficult to arrange for other subsystems to be notified of the panic so that they can shut down as well, since the subsystem in which the panic occurs may not even know about them.

An additional difficulty is that some exceptions may occur for reasons not related to algorithmically detectable conditions. For instance, the user of an application may cause a signal to be delivered to it at any time. This has nothing to do with normal execution and cannot be predicted.

The goals of ETM are thus twofold:

(1)
Panics triggered anywhere within an application or any of its subsystems should cause orderly shutdown of all subsystems and the application itself.
(2)
Signals that normally terminate a program should be caught and trigger a panic to allow shutdown as per (1).

Processing Model


The model used by ETM is that the application initializes subsystems in the order required by any dependencies among them, and then terminates them in the reverse order. The presumption here is that if subsystem ss2 is dependendent upon subsystem ss1, then ss1 should be initialized first and terminated last; the dependency is unlikely to make it wise to shut down ss1 before ss2.

ETM must itself be initialized before any other subsystem which uses it. The initialization call, ETMInit(), takes as an argument a pointer to a routine which performs any application-specific cleanup not related to its subsystems, or NULL if there is no such routine.

Each of the subsystems should then be initialized. A subsystem's initialization routine should call ETMAddShutdownProc() to register its own shutdown routine with ETM, if there is one. (Some subsystems may require no explicit initialization or termination. However, if there is a shutdown routine, you should at least call ETMAddShutdownProc() to register it.)

When the program detects an exceptional condition, it calls ETMPanic() to describe the problem and exit. ETMPanic() is also called automatically when a signal is caught. A message is printed, and all the shutdown routines that have been registered are automatically executed, including the application-specific one.

ETM is designed to handle shutting down under unusual circumstances, but it also works well for terminating normally. Instead of calling ETMPanic(), the application calls ETMEnd(). This is much like calling ETMPanic(), except that no error message is printed, and ETMEnd() returns to the caller. which takes care of calling all the shutdown routines that have been registered.

It is evident that the functionality provided by ETM is somewhat like that of the atexit() routine provided on some systems. Some differences between the two are:

*
atexit() is either built in or not available. ETM can be put on any system to which it can be ported (extent unknown, but includes at least SunOS, Ultrix, Mips RISC/os and THINK C).
*
ETM is more suited for handling exceptional conditions.
*
ETM shutdown routines can be installed and removed later. atexit() provides only for installation (although you could simulate removal by setting a flag which shutdown routines examine to see whether to execute or not).

Here is a short example of how to set up and shut down using ETM.

   
   main ()
   {
     . . .
     ETMInit (Cleanup);  /* register application-specific cleanup */
     SS1Init ();         /* registers SS1End() for shutdown */
     SS2Init ();         /* registers SS2End() for shutdown */
     SS3Init ();         /* registers SS3End() for shutdown */
     ... main processing here ...
     ETMEnd ();          /* calls SS3End (), SS2End () and SS1End () */
     exit (0);
   }

Subsystems that are themselves built on other subsystems may follow this model, except that they would not call ETMInit() or ETMEnd().

If there is no special initialization or shutdown activity, and you don't care about catching signals, it is not necessary to call ETMInit() and ETMEnd(). The application may still call ETMPanic() to print error messages and terminate. (Even if the application does use ETMInit() and ETMEnd(), it is safe to call ETMPanic() before any initialization has been done, because nothing needs to be shut down at that point yet.)

If ETM itself encounters an exceptional condition (e.g., it cannot allocate memory when it needs to), it will--of course--trigger a panic. This should be rare, but if it occurs, ETM will generate a message indicating what the problem was.

Caveats


Shutdown routines shouldn't call ETMPanic(), since ETMPanic() causes shutdown routines to be executed. ETM detects loops of this sort, but their occurrence indicate a flaw in program logic. Similarly, if you install a print routine to redirect ETM's output somewhere other than stderr, the routine shouldn't call ETM to print any messages.

kill -9 is uncatchable and there's nothing you can do about it.

Programming Interface


The ETM library should be installed in /usr/lib/libetm.a or local equivalent, and applications should link in the ETM library with the -letm flag. Source files that use ETM routines should include etm.h. If you use ETM functions in a source file without including etm.h, you will get undefined symbol errors at link time.

The abstract types ETMProcRetType and ETMProcPtr may be used for declaring and passing pointers to functions that are passed to ETM routines. By default these will be void and void(*)(), but on deficient systems with C compilers lacking void pointers they will be int and int(*)(), the usual C defaults for functions.

These types make it easier to declare properly typed functions and NULL pointers. For instance, if you don't pass any shutdown routine to ETMInit(), use

   
   ETMInit ((ETMProcPtr) NULL);

If you do, use

   
   ETMProcRetType ShutdownProc () { . . . }
   . . .
   main ()
   {
     . . .
     ETMInit (ShutdownProc);
     . . .
   }

Descriptions of the ETM routines follow.

   
   ETMProcRetType ETMInit (p)
   ETMProcPtr     p;
    Registers the application's cleanup routine p (which should be NULL if there is none) and registers default handlers for the following signals (all of which normally cause program exit): SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGSYS, SIGTERM, SIGBUS, SIGSEGV, SIGFPE, SIGPIPE. If p is not NULL, it should point to a routine that takes no arguments and returns no value.
   
   ETMProcRetType ETMEnd ()
    Causes all registered shutdown routines to be executed. The application may then exit normally with exit(0).
   
   ETMProcRetType ETMPanic (fmt, ...)
   char *fmt;
    ETMPanic() is called when a panic condition occurs, and the program cannot continue. The arguments are as those for printf() and are used to print a message after shutting down all subsystems and executing the application's cleanup routine, and before calling exit(). ETMPanic() adds a newline to the end of the message.

    ETMPanic() may be called at any time, including prior to calling ETMInit(), but only those shutdown routines which have been registered are invoked.

    A common problem with applications that encounter exceptional conditions such as segmentation faults is that you often don't see all the output your application has produced. This is because stdout is often buffered. To alleviate this problem, stdout is flushed before any message is printed, so that any pending application output is flushed and appears before the error message.

    By default, ETMPanic() prints the message on stderr. This behavior may be modified with ETMSetPrintProc().

    The default exit() value is 1. This may be modified with ETMSetExitStatus().

   
   ETMProcRetType ETMMsg (fmt, ...)
   char *fmt;
    ETMMsg() is like ETMPanic() except that it just prints the message and returns. It is useful in that if panic message output has been redirected somewhere other than stderr (e.g., to the system log), ETMMsg() will write its output there, too. The application does not need to know whether such redirection has taken place.

    ETMMsg() may be called at any time, including prior to calling ETMInit().

   
   ETMProcRetType ETMAddShutdownProc (p)
   ETMProcPtr     p;
    Register a shutdown routine with ETM. This is normally called within a subsystem's initialization routine. p should point to a routine that takes no arguments and returns no value.
   
   ETMProcRetType ETMRemoveShutdownProc (p)
   ETMProcPtr     p;
    Deregister a previously-registered shutdown routine with ETM. This is useful for routines that only need to be registered temporarily, e.g., during execution of some piece of code that temporarily creates some file that needs to be removed if the program crashes, but which removes it itself if execution proceeds normally.
   
   ETMProcRetType ETMSetSignalProc (signo, p)
   int  signo;
   ETMProcPtr     p;
    Register a signal-catching routine to override ETM's default. The routine will be called with one argument, the signal number. It should return no value, regardless of the usual return type of signal handler routines on your system. (When ETM is configured on your system, it knows the proper return value for signal() but hides differences among systems from your application so you don't have to think about it.)

    To return a signal to its default action or to cause a signal to be ignored, pass the following values for p (these are defined in etm.h):

       ETMSigIgnore        signal is ignored
       ETMSigDefault       signal default action is restored
    
   
   ETMProcPtr ETMGetSignalProc (signo)
   int  signo;
    Returns the function current used to catch signal signo, or NULL if the signal is handled with the default action or being ignored (it's not possible to distinguish between the last two cases).
   
   ETMProcRetType ETMSetPrintProc (p)
   ETMProcPtr     p;
    This routine is used to register a procedure that ETM can use to print messages. The default is to send messages to stderr, which is appropriate for most programs. Applications may prefer to send messages elsewhere. For instance, non-interactive programs like network servers might send them to syslog() instead. Or a program may wish to send messages to multiple destinations.

    To override the default, pass the address of an alternate print routine to ETMSetPrintProc(). The routine should take one argument, a pointer to a character string, and return no value. The argument will be the fully formatted panic message, complete with a newline on the end. To restore the default, pass NULL.

    The printing routine shouldn't call ETMPanic() or ETMMsg() or a loop will be detected and ETM will conveniently panic as a service to let you know you have a logic error in your program.

   
   ETMProcPtr ETMGetPrintProc ()
    Returns a pointer to the current printing function, NULL if the default is being used.
   
   ETMProcRetType ETMSetExitStatus (status)
   int  status;
    This routine is used to register the status value that is passed to exit() when a panic occurs. The default is 1. For some applications it is desirable to return a different value. For instance, a mail server that processes messages may send back a message to the person who sent mail when a request is erroneous, then panic (perhaps by writing a message to the system log). On some systems, if a program invoked to handle mail returns non-zero, the mailer will send another message to that person stating that there was a problem handling the mail. This extra message is unnecessary, and can be suppressed by registering an exit status of 0.

    If ETMSetAbort() has been called to force an abort() on a panic, the exit status is not returned.

   
   int ETMGetExitStatus ()
    Returns the current exit status which will be returned if a panic occurs.
   
   ETMProcRetType ETMSetAbort (val)
   int  val;
    Calling this function with a non-zero value of val causes ETM to try to generate a core image when ETMPanic() is called (after the panic message is printed). This can sometimes be useful for debugging. If val is zero, image generation is suppressed. The default is no image.

    ETMSetAbort() is meaningless on systems with no concept of a core image. Also, if you install a signal catcher for SIGABRT, you may end up in a panic loop.

   
   int ETMGetAbort ()
   int  val;
    Return current image generation value.
etm/etm.txt010066400017710000151000000342020632324663000147220ustar00junkyarddatamgmt00000400000027ETM -- A Program Exception and Termination Manager Paul DuBois dubois@primate.wisc.edu Wisconsin Regional Primate Research Center Revision date: 10 April 1997 1. Introduction This document describes Exception and Termination Manager (ETM), a simple(-minded) library to manage exceptional conditions that arise during program execution, and to provide for orderly program shutdown. There are at least a couple of approaches one may adopt for handling error conditions within an application: - Have functions always return a value and have all callers test the return value and respond accordingly. - Force the program to give up and exit early. Each approach has strengths and weaknesses. A difficulty with the first is that actions composed of many subsidiary actions, each of which may themselves succeed or fail, can easily become very unwieldy when an attempt is made to handle all possible outcomes. However, such a program will also continue in the face of extreme adversity. An advantage of the second approach is that it is, conceptually at least, simpler to let a program die when a serious error occurs. The difficulty lies in making sure the program cleans up and shuts down properly before it exits. This can be a problem especially when a program uses a number of independent modules which can each encounter exceptional conditions and need to be shut down, and which may know nothing of each other. ETM is designed to alleviate the difficulties of this second approach. The general architecture assumed for this discussion is that of an application which uses zero or more subsystems which may be more or less independent of each other, and which may each require initialization and/or termination. Also, other application-specific initialization and/or termination actions may need to be performed which are unrelated to those of the subsystems, e.g., temporary files created at the beginning of the application need to be removed before final termination, network connections need to be shut down, terminal state needs to be restored. Ideally, when an application executes normally, it will initialize, perform the main processing, then shut down in an orderly fashion. This does not always occur. Exceptional conditions may be detected which necessitate a "panic" (an immediate program exit) because processing cannot continue further, or because it is judged too burdensome to try to continue. An individual subsystem may be easily written such that a panic within itself causes its own shutdown code to be invoked. It is more difficult to arrange for other subsystems to be notified of the panic so that they can shut down as well, since the subsystem in which the panic occurs may not even know about them. An additional difficulty is that some exceptions may occur for reasons not related to algorithmically detectable conditions. For instance, the user of an application may cause a signal to be delivered to it at any time. This has nothing to do with normal execution and cannot be predicted. The goals of ETM are thus twofold: (1) Panics triggered anywhere within an application or any of its subsystems should cause orderly shutdown of all subsystems and the application itself. (2) Signals that normally terminate a program should be caught and trigger a panic to allow shutdown as per (1). 2. Processing Model The model used by ETM is that the application initializes subsystems in the order required by any dependencies among them, and then terminates them in the reverse order. The presumption here is that if subsystem ss2 is dependendent upon subsystem ss1, then ss1 should be initialized first and terminated last; the dependency is unlikely to make it wise to shut down ss1 before ss2. ETM must itself be initialized before any other subsystem which uses it. The initialization call, ETMInit(), takes as an argument a pointer to a routine which performs any application-specific cleanup not related to its subsystems, or NULL if there is no such routine. Each of the subsystems should then be initialized. A subsystem's initialization routine should call ETMAddShutdownProc() to register its own shutdown routine with ETM, if there is one. (Some subsystems may require no explicit initialization or termination. However, if there is a shutdown routine, you should at least call ETMAddShutdownProc() to register it.) When the program detects an exceptional condition, it calls ETMPanic() to describe the problem and exit. ETMPanic() is also called automatically when a signal is caught. A message is printed, and all the shutdown routines that have been registered are automatically executed, including the application-specific one. ETM is designed to handle shutting down under unusual circumstances, but it also works well for terminating normally. Instead of calling ETMPanic(), the application calls ETMEnd(). This is much like calling ETMPanic(), except that no error message is printed, and ETMEnd() returns to the caller. which takes care of calling all the shutdown routines that have been registered. It is evident that the functionality provided by ETM is somewhat like that of the atexit() routine provided on some systems. Some differences between the two are: - atexit() is either built in or not available. ETM can be put on any system to which it can be ported (extent unknown, but includes at least SunOS, Ultrix, Mips RISC/os and THINK C). - ETM is more suited for handling exceptional conditions. - ETM shutdown routines can be installed and removed later. atexit() provides only for installation (although you could simulate removal by setting a flag which shutdown routines examine to see whether to execute or not). Here is a short example of how to set up and shut down using ETM. main () { . . . ETMInit (Cleanup); /* register application-specific cleanup */ SS1Init (); /* registers SS1End() for shutdown */ SS2Init (); /* registers SS2End() for shutdown */ SS3Init (); /* registers SS3End() for shutdown */ ... main processing here ... ETMEnd (); /* calls SS3End (), SS2End () and SS1End () */ exit (0); } Subsystems that are themselves built on other subsystems may follow this model, except that they would not call ETMInit() or ETMEnd(). If there is no special initialization or shutdown activity, and you don't care about catching signals, it is not necessary to call ETMInit() and ETMEnd(). The application may still call ETMPanic() to print error messages and terminate. (Even if the application does use ETMInit() and ETMEnd(), it is safe to call ETMPanic() before any initialization has been done, because nothing needs to be shut down at that point yet.) If ETM itself encounters an exceptional condition (e.g., it cannot allocate memory when it needs to), it will--of course--trigger a panic. This should be rare, but if it occurs, ETM will generate a message indicating what the problem was. 3. Caveats Shutdown routines shouldn't call ETMPanic(), since ETMPanic() causes shutdown routines to be executed. ETM detects loops of this sort, but their occurrence indicate a flaw in program logic. Similarly, if you install a print routine to redirect ETM's output somewhere other than stderr, the routine shouldn't call ETM to print any messages. kill -9 is uncatchable and there's nothing you can do about it. 4. Programming Interface The ETM library should be installed in /usr/lib/libetm.a or local equivalent, and applications should link in the ETM library with the -letm flag. Source files that use ETM routines should include etm.h. If you use ETM functions in a source file without including etm.h, you will get undefined symbol errors at link time. The abstract types ETMProcRetType and ETMProcPtr may be used for declaring and passing pointers to functions that are passed to ETM routines. By default these will be void and void(*)(), but on deficient systems with C compilers lacking void pointers they will be int and int(*)(), the usual C defaults for functions. These types make it easier to declare properly typed functions and NULL pointers. For instance, if you don't pass any shutdown routine to ETMInit(), use ETMInit ((ETMProcPtr) NULL); If you do, use ETMProcRetType ShutdownProc () { . . . } . . . main () { . . . ETMInit (ShutdownProc); . . . } Descriptions of the ETM routines follow. ETMProcRetType ETMInit (p) ETMProcPtr p; Registers the application's cleanup routine p (which should be NULL if there is none) and registers default handlers for the following signals (all of which normally cause program exit): SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGSYS, SIGTERM, SIGBUS, SIGSEGV, SIGFPE, SIGPIPE. If p is not NULL, it should point to a routine that takes no arguments and returns no value. ETMProcRetType ETMEnd () Causes all registered shutdown routines to be executed. The application may then exit normally with exit(0). ETMProcRetType ETMPanic (fmt, ...) char *fmt; ETMPanic() is called when a panic condition occurs, and the program cannot continue. The arguments are as those for printf() and are used to print a message after shutting down all subsystems and executing the application's cleanup routine, and before calling exit(). ETMPanic() adds a newline to the end of the message. ETMPanic() may be called at any time, including prior to calling ETMInit(), but only those shutdown routines which have been registered are invoked. A common problem with applications that encounter exceptional conditions such as segmentation faults is that you often don't see all the output your application has produced. This is because stdout is often buffered. To alleviate this problem, stdout is flushed before any message is printed, so that any pending application output is flushed and appears before the error message. By default, ETMPanic() prints the message on stderr. This behavior may be modified with ETMSetPrintProc(). The default exit() value is 1. This may be modified with ETMSetExitStatus(). ETMProcRetType ETMMsg (fmt, ...) char *fmt; ETMMsg() is like ETMPanic() except that it just prints the message and returns. It is useful in that if panic message output has been redirected somewhere other than stderr (e.g., to the system log), ETMMsg() will write its output there, too. The application does not need to know whether such redirection has taken place. ETMMsg() may be called at any time, including prior to calling ETMInit(). ETMProcRetType ETMAddShutdownProc (p) ETMProcPtr p; Register a shutdown routine with ETM. This is normally called within a subsystem's initialization routine. p should point to a routine that takes no arguments and returns no value. ETMProcRetType ETMRemoveShutdownProc (p) ETMProcPtr p; Deregister a previously-registered shutdown routine with ETM. This is useful for routines that only need to be registered temporarily, e.g., during execution of some piece of code that temporarily creates some file that needs to be removed if the program crashes, but which removes it itself if execution proceeds normally. ETMProcRetType ETMSetSignalProc (signo, p) int signo; ETMProcPtr p; Register a signal-catching routine to override ETM's default. The routine will be called with one argument, the signal number. It should return no value, regardless of the usual return type of signal handler routines on your system. (When ETM is configured on your system, it knows the proper return value for signal() but hides differences among systems from your application so you don't have to think about it.) To return a signal to its default action or to cause a signal to be ignored, pass the following values for p (these are defined in etm.h): ETMSigIgnore signal is ignored ETMSigDefault signal default action is restored ETMProcPtr ETMGetSignalProc (signo) int signo; Returns the function current used to catch signal signo, or NULL if the signal is handled with the default action or being ignored (it's not possible to distinguish between the last two cases). ETMProcRetType ETMSetPrintProc (p) ETMProcPtr p; This routine is used to register a procedure that ETM can use to print messages. The default is to send messages to stderr, which is appropriate for most programs. Applications may prefer to send messages elsewhere. For instance, non-interactive programs like network servers might send them to syslog() instead. Or a program may wish to send messages to multiple destinations. To override the default, pass the address of an alternate print routine to ETMSetPrintProc(). The routine should take one argument, a pointer to a character string, and return no value. The argument will be the fully formatted panic message, complete with a newline on the end. To restore the default, pass NULL. The printing routine shouldn't call ETMPanic() or ETMMsg() or a loop will be detected and ETM will conveniently panic as a service to let you know you have a logic error in your program. ETMProcPtr ETMGetPrintProc () Returns a pointer to the current printing function, NULL if the default is being used. ETMProcRetType ETMSetExitStatus (status) int status; This routine is used to register the status value that is passed to exit() when a panic occurs. The default is 1. For some applications it is desirable to return a different value. For instance, a mail server that processes messages may send back a message to the person who sent mail when a request is erroneous, then panic (perhaps by writing a message to the system log). On some systems, if a program invoked to handle mail returns non-zero, the mailer will send another message to that person stating that there was a problem handling the mail. This extra message is unnecessary, and can be suppressed by registering an exit status of 0. If ETMSetAbort() has been called to force an abort() on a panic, the exit status is not returned. int ETMGetExitStatus () Returns the current exit status which will be returned if a panic occurs. ETMProcRetType ETMSetAbort (val) int val; Calling this function with a non-zero value of val causes ETM to try to generate a core image when ETMPanic() is called (after the panic message is printed). This can sometimes be useful for debugging. If val is zero, image generation is suppressed. The default is no image. ETMSetAbort() is meaningless on systems with no concept of a core image. Also, if you install a signal catcher for SIGABRT, you may end up in a panic loop. int ETMGetAbort () int val; Return current image generation value. al circumstances, but it also works well for terminating normally. Instead of calling ETMPanic(), the application calls ETMEnd(). This is much like calling ETMPanic(), except that no error message is printed, and ETMEnd() returns to the caller. which takes care of calling all the shutdown routines that have been registered. It is evident that the functionality provided by ETM is