chris@hwcs.UUCP (Chris Miller) (07/11/85)
export PATH || exec /bin/sh $0 $* : Apologies to sites who have had this before. The last attempt : at distribution fell down a black hole just upstream from here. : "This is a shar archive; use /bin/sh to extract" : "Extracted files will be owned by you, and will have" : "default permissions" PATH=/bin:/usr/bin echo If this archive is complete, \"End of archive\" will appear at the end echo Extracting Introduction sed 's/^X//' <<'End-of-file' >Introduction XThis is a distribution of a preprocessor, lbl, for nroff and its Xkindred. Lbl allows you to give symbolic labels to objects in a text Xfile which belong in numbered sequences (e.g. chapters, figures, Xtables, equations) and to refer to them by name; sequence numbers are Xassigned automatically. Hence, it is unnecessary to adjust all Xcross-references every time that a new item is inserted into the middle Xof a sequence. X XMulti-level sequences are supported (similar to the multi-level section Xnumbers in many macro packages); the user has control over the format Xof each level of sequence numbers (roman, arabic, letters). Many Xindependent sequences may be used simultaneously, limited only by the Xmemory available to the program; the same name may be used for items in Xseveral sequences. X XThe program was written by Chris Miller at Heriot-Watt University, XEdinburgh. Please report bugs, portability problems or ideas for Ximprovements to chris@hwcs.uucp ( ....!mcvax!ukc!kcl-cs!hwcs!chris if Xyou need to be more explicit in your mail path). X XAs indicated in the attached NOTICE, you are free to pass this to Xanyone else; it contains NO code restricted under proprietary Xagreements. If you make alterations, please (a) inform the author and X(b) mark the emendations to the original distribution clearly X(preferably through conditional compilation) -- I desire neither praise Xfor your brilliance nor scorn for your incompetence! X End-of-file echo Extracting NOTICE sed 's/^X//' <<'End-of-file' >NOTICE XNOTICE: X XThe software and documentation contained within this directory and Xall its subdirectories is copyright (C) C.D.F. Miller, 1984, 1985. X XPermission is hereby given for its free reproduction and modification Xfor non-commercial purposes, provided that this notice and all embedded Xcopyright notices be retained. Commercial organisations may give away Xcopies as part of their systems provided that they do so without charge, Xand that they acknowledge the source of the software. X X C.D.F. Miller X Department of Computer Science X Heriot-Watt University X 79 Grassmarket X Edinburgh X Scotland End-of-file echo Extracting READ.ME sed 's/^X//' <<'End-of-file' >READ.ME Xdoc contains manual page and more extensive guide Xhdr contains header files Xsrc contains the C source code End-of-file echo Extracting Makefile sed 's/^X//' <<'End-of-file' >Makefile X# (C) C.D.F.Miller, Heriot-Watt University, March 1984 X XDESTDIR=/ XBIN=/usr/local XMAN=/usr/man/man1 XDOC=/usr/doc X Xsrc/lbl: X cd src; make X Xinstall: src/lbl X cp src/lbl $(DESTDIR)$(BIN) X strip $(DESTDIR)$(BIN)/lbl X cp doc/lbl.1 $(DESTDIR)$(MAN) X cp doc/lbl $(DESTDIR)$(DOC) X Xlbl.shar: X shar Introduction NOTICE READ.ME Makefile doc hdr src >lbl.shar X Xclean: X cd src; make clean End-of-file echo Making directory doc. mkdir doc echo Extracting doc/Makefile sed 's/^X//' <<'End-of-file' >doc/Makefile XLBL=lbl XNROFF=nroff XFILTER=cat X Xdoc: lbl X $(LBL) lbl | $(NROFF) -ms | $(FILTER) X Xman: lbl.1 X $(NROFF) -man lbl.1 | $(FILTER) X Xexample: example.n X lbl example.n | $(NROFF) -ms | $(FILTER) End-of-file echo Extracting doc/READ.ME sed 's/^X//' <<'End-of-file' >doc/READ.ME XThe files in this directory are: X Xlbl.1 Manual page, to be installed in /usr/man/man1 or wherever X else you keep the pages for contributed user programs. X Xlbl Longer manual; possibly to be installed in /usr/doc. This X uses the "ms" macro package, which is still probably the X most widely available. The command to generate the formatted X manual is X lbl lbl | nroff -ms X Xexample.n X A short example of the use of lbl. This example is also X embedded within the manual in a different guise. X XMakefile X A very trivial Makefile for the documentation End-of-file echo Extracting doc/example.n sed 's/^X//' <<'End-of-file' >doc/example.n X.\" (C) C.D.F. Miller, Heriot-Watt University, March 1984 X.\" X.\" We use '.L= sec' to generate the numbered headings X.de L= X.if '\\$1'sec' .NH \\$2 X.. X.ND X.TL XExample of LBL X.L= sec 1 intro XIntroduction X.L= table 1 * X.PP XWe begin with a small table (Table @table opening@). X.DS C XTable @table opening@ about here X.DE Xand consider things in more detail in Section @sec cont@. X.L= table 2 opening X.L= sec 1 cont XContinuation X.L= table 1 * X.PP XIn this continuation we refer back to Section @sec intro@, which contained XTable @table opening@, and presnt more detailed information in Table X@table detail@. X.DS XTable @table detail@ about here. X.DE X.L= table 2 detail X.L= sec 2 subcont XSub-continuation X.PP XIn which we further refine things, as shown in Table @table mega-detail@ below. X.DS XTable @table mega-detail@ about here. X.DE X.L= table 2 mega-detail End-of-file echo Extracting doc/lbl sed 's/^X//' <<'End-of-file' >doc/lbl X.\" (C) C.D.F. Miller, Heriot-Watt University, March 1984 X.\" X.\" This file should be formatted by X.\" lbl lbl | nroff -ms X.L= delimiter # X.ND X.TL XLBL - Symbolic Labels in Text Documents X.NH 1 XIntroduction X.L= sec 1 intro X.PP X.I lbl Xis a pre-processor for X.I troff Xand X.I nroff Xwhich allows Sections, Figures, Tables, etc., to be referred to by Xsymbolic names rather than by absolute number. XIt will handle forward references as well as backward ones. X.PP XUses of a label in the text are indicated by a delimiter character (default '@', Xbut resettable), followed by a X.I type Xname (e.g. "TABLE", "EQN", etc.), followed by the label itself X(e.g. "Profits-1983"). XEach such occurrence is replaced by a reference number; the default Xstyle of numbering is a sequence of period-separated arabic numbers X(e.g. 2.4.1) but this is resettable. XFinally, another delimiter is required to close the reference X(cf. the use of delimiters in X.I eqn Xfor in-line equations). X.LP XExamples: X.DS XFor full details refer to Table @TABLE Profits-1983@. XAs we saw in Chapter @chap intro@, ... XFigure @fig wing-profile@ shows the airflow patterns ... X.DE X.PP XLabels may be defined at any point in the text. XThe definition looks like a X.I troff Xmacro, and the definition line is retained in the original text. XBy default, the macro used is ".L=", but this can be reset. XThe macro takes 3 arguments: a type-name, a level-number, and Xa label-name. X.PP XThe type-name corresponds to that used to signal a label occurrence in Xthe text. XThere is no restriction on the choice of name; any sequence of Xnon-blank characters may be used. XUpper- and lower-case letters X.I are Xdistinguished. X.PP XThe level-number corresponds to the header-level numbers used Xby the .NH macro in X.I ms , Xthe .sh macro in X.I me , Xetc. XThe index at the given level is incremented by 1, and all higher indexes Xset to 0. XInitially, all indexes are set to 0 by default, but other starting values Xmay be chosen. XThere is an implementation-defined restriction on the number Xof levels of index (currently 20); Xit is not anticipated that this will lead to problems. X.PP XThe label may be any sequence of non-blank characters; Xthe same label may be used in more than one type. XFurthermore, the special label-name ``*'' can be used to increment the Xappropriate level-counter without defining a label at all; Xthis is useful, for example, when all tables, figures, etc., in a section Xtake their initial index from the section number: two ways of doing this Xwould be: X.DS L Xa. X .L= section 1 this-section X .L= last table 0 X .L= last figure 0 X ... X ... refer to table @section this-section@.@table profits@ ... X ... see figure @section this-section@.@figure structure@ ... X ... X .L= table 1 profits X ... X .L= figure 1 structure X ... X X(see section #sec directives# for the use of X``.L=\ last\ ...'') X Xb. X .L= section 1 this-section X .L= table 1 * X .L= figure 1 * X ... X ... refer to table @table profits@ ... X ... see figure @figure structure@ ... X ... X .L= table 2 profits X ... X .L= figure 2 structure X ... X.DE XIt is largely a matter of taste which technique is used; Xthe former is more long-winded, but avoids the need to remember to Xkeep the tables and figures in step every time the section is Xupdated. XYet a third possibility (similar to the first) would be: X.DS L Xc. X .L= section 1 this-section X .ds Sc "@section this-section@ X .L= last table 0 X ... X ... refer to table \*(Sc.@table profits@ X etc. X.DE Xmaking use of the string-definition facility within X.I nroff . X.PP XIt is important to be aware that all processing on labels is done Xbefore X.I troff Xprocesses the text; attempts to build label-references by Xusing macros or X.I troff Xstrings registers will almost certainly not work as expected. X.NH 1 XCommand Line Options X.L= sec 1 options X.PP XOptions to X.I lbl Xare set in the command line, which has the form X.DS Xlbl [ -d\fIdelim\fR ] [ -m\fImacro\fR ] [ -l ] [ -s ] X.DE X.IP -d X.I \fIdelim\fR Xis the character used to delimit in-line occurrences of label Xreferences (default ``@''); X.IP -m X.I macro Xis the 2-character name of Xa X.I troff Xmacro which introduces label definitions, etc. (default ``L=''); X.IP -l Xcauses a listing of label-definitions to be written to the standard Xerror stream. XEach label-type is listed, together with its print format, followed by Xa line for each label of that type, showing label-name, file and line Xwhere it is defined, and value; X.IP -s Xcauses the generation of the X.I troff Xinput file to be suppressed; Xsetting X.I -s Xautomatically also sets X.I -l . X.NH 1 XControl directives X.L= sec 1 directives X.PP XIn addition to defining labels, the \fB.L=\fR macro (or its substitute) Xcan be used for several other purposes. XThese are all indicated by commands of the form X.DS X\&.L= \fIcommand\fR \fIargument\fR ... X.DE Xwhere the \fIcommand\fRs are reserved words which may not be used as Xtype-names. XThese commands allow control over the initialisation of label values, Xthe print format of labels, and thelabel reference delimiter. X.IP "\&.L= delimiter off" X.br Xturns off interpretation of the delimiter character altogether; Xsubsequent text is copied literally until another \fIdelimiter\fR Xcommand is encountered; X.IP "\&.L= delimiter \fIcharacter\fR" X.br Xresets the delimiter in subsequent text to the given character; X.IP "\&.L= format \fItypename\fR \fIstring\fR" X.br Xsets the print format for labels of the given type - see section X#sec formats#; X.IP "\&.L= last \fItypename\fR \fIcount1\fR \fIcount2\fR ..." X.br Xresets the counters for \fItypename\fR as though the last label Xgenerated had been \fIcount1.count2...\fR (with all omitted counts Xtaken as 0). X.NH 2 XPrint formats X.L= sec 2 formats X.PP XThe default print format for a label is as a sequence of period-separated Xarabic numerals. XHowever, it is also possible to specify alphabetic or roman labels, Xor a mixture, and to have separators other than a period. XThis is governed by the format given in a ``.LE\ format'' command. X.PP XSuch a format contains escape sequences (flagged by a ``%'' character) Xand literal text. XThe text is copied until an escape sequence is encountered; such a Xsequence is replaced by the index for the next level of the label Xvalue, printed in one of the following formats: X.IP %1 XArabic numerals (without non-significant leading zeros); X.IP %0 XAs %1, but offset by 1 so that the first value printed will be 0 rather Xthan 1; X.IP %a XLower-case alphabetics, starting at ``a''; ``z'' is followed by ``aa'', Xetc.; X.IP %A XUpper-case alphabetics; X.IP %i XLower-case roman numerals (with some odd choices for large numbers, Xconsistent with the roman numerals printed by X.I troff ). X.IP %I XUpper-case roman numerals. X.LP XA ``%'' followed by any other character (in particular another ``%'') prints Xas that character. X.NH 1 XLimits X.L= sec 1 limits X.PP X.I Lbl Ximposes no limit on the size of text to be processed, but (like X.I refer ) Xneeds to act on a text as a whole, rather than processing individual Xfiles. XThe limit on the number of levels of header is unlikely to prove a problem. XThe number of labels which may be used is limited only by the amount Xof memory available to a process; even on a small machine it is Xpossible to handle a few hundred label definitions. X.NH 1 XFurther Examples X.L= sec 1 examples X.PP XThe copying of the definition macros makes it possible to use them Xas X.I troff Xmacros, as in the following example: X.DS X\&.de L= X\&.ie '\e\e$1'sec' .NH \e\e$2 X\&.el .ie '\e\e$1'table' .if !'\e\e$3'*' \e{ X\&.DS C X\&Table '\e\e$3' about here X\&.DE X\&\e} X\&.el .if '\e\e$1'fig' .if !'\e\e$3'*' \e{ X\&.DS C X\&Figure '\e\e$3' about here X\&.DE X\&\e} X\&.. X\&.nr LL 5i X\&.ND X\&.TL X\&Example of LBL X\&.L= sec 1 intro X\&Introduction X\&.L= table 1 * X\&.PP X\&We begin with a small table (Table @table opening@). X\&.L= table 2 opening X\&and consider things in more detail in Section X\&@sec cont@. X\&.L= sec 1 cont X\&Continuation X\&.L= table 1 * X\&.PP X\&In this continuation we refer back to Section X\&@sec intro@, which contained X\&Table @table opening@, and present more detailed X\&information in Table X\&@table detail@. X\&.L= table 2 detail X\&.L= sec 2 subcont X\&Sub-continuation X\&.PP X\&In which we further refine things, as shown in X\&Table @table mega-detail@ below. X\&.L= table 2 mega-detail X.DE XIn the above, the ``.L=\ sec'' macros automatically generate the Xnumbered headings by expanding to the \fIms\fR ``.NH'' macros, Xwhile the ``table'' definitions cause the insertion of figures Xsuch as X.DS C XTable 'detail' about here X.DE XThe above example thus produces the following: X.DS X Example of LBL X X X X X X\fI1. Introduction\fR X X We begin with a small table (Table 1.1). X X X Table 'opening' about here X X and consider things in more detail in Section 2. X X\fI2. Continuation\fR X X In this continuation we refer back to Section X1, which contained Table 1.1, and present more Xdetailed information in Table 2.1. X X X Table 'detail' about here X X X X\fI2.1. Sub-continuation\fR X X In which we further refine things, as shown Xin Table 2.2 below. X X X Table 'mega-detail' about here X.DE X.PP XThe alphabetic formats may be useful for such things as appendices, Xe.g. X.DS X\&.L= format appendix %A X\&.L= appendix 1 trade-marks X\&.SH X\&Appendix @appendix trade-marks@: X\&List of Registered Trade Marks X\&.LP X\&(For the addresses of the proprietors see X\&@appendix props@). X\& ... X\&.L= appendix 1 props X.DE Xwhich will generate X.DS X\fIAppendix A: List of Registered Trade Marks\fR X X(For the addresses of the proprietors see appendix B). X.DE End-of-file echo Extracting doc/lbl.1 sed 's/^X//' <<'End-of-file' >doc/lbl.1 X.\" (C) C.D.F. Miller, Heriot-Watt University, March 1984 X.\" X.TH LBL 1 Local X.ad X.fi X.SH NAME Xlbl \- preprocess symbolic labels for troff(1) text X.SH SYNOPSIS X.B lbl X[ X.B -d\c Xdelim X] [ X.B -m\c Xmacro X] [ X.B -l X] [ X.B -s X] [ file ... ] X.SH DESCRIPTION X.I Lbl Xis a preprocessor for X.I troff (1) Xwhich constructs serial numbers automatically for tables, equations, Xsections, etc., and allows them to be referred to by symbolic names. XIt avoids the need for a user to keep track of such numberings, and Xto alter all cross-references whenever a labelled Xobject is introduced or deleted. X.PP XAs many independent sequences of labels as required can be maintained; Xeach sequence is given a symbolic name, known as the X.I label-type . XWithin each label-type, objects are referred to by symbolic names known Xas X.I labels ; Xthe same label may be used in several different label-types without problems. XNames for labels and label-types may be arbitrary sequences of alphanumeric Xcharacters. XIn addition, the special label-name ``*'' may be used as an anonymous label, Xused to increment a level counter without generating a label (e.g. to keep Xtable numbers in step with the corresponding section numbers). X.PP X.I Lbl Xreads as input the concatenation of all specified X.I file Xarguments (interpreting ``-'' to mean the standard input); Xif no X.I file Xargument is given, X.I lbl Xreads the standard input. XThe input consists of arbitrary text (normally input for X.I troff (1), X.I eqn (1), Xand the rest of that family) interspersed with X.I label-definitions Xand X.I label-references , Xtogether with a few other sorts of definition described below. X.PP X\fILabel Definitions:\fR Xa label-definition Xdefines the value of a symbolic label. XAll such definitions are introduced by a line beginning with Xa special X.I troff Xmacro; the default macro is X.B \&.L= Xbut this can be overridden in the command line. XThe label-definition macro is followed by a label-type, a numeric level, Xand a label-name; Xa value is given to the label by incrementing the current count for Xthe label-type at the given level (similar to the generation of Xnumbered headings by such macros as X.B \&.NH Xin the X.I ms (6) Xpackage, X.B \&.H Xin X.I mm Xand X.B \&.sh Xin X.I me ). XUnless otherwise specified, the first count generated at a given level will Xbe 1; when a count is incremented, all deeper counts are reset to 0. X.PP XThere are several other uses of the definition-macro: X.IP "\&.L= delimiter off" X.br Xinhibits all subsequent translation of label-references; X.IP "\&.L= delimiter \fIchar\fR" X.br Xresets the delimiter introducing label-references to X.I char X(see below); X.IP "\&.L= format \fIlabel-type pattern\fR" Xresets the printing format for a label reference (see below); X.IP "\&.L= last \fIlabel-type count ...\fR" Xresets the counts for \fIlabel-type\fR as though the last label generated Xhad had the specified counts for its successive levels (missing counts Xall being taken as 0). XAll counts must be arabic numerals, regardless of the print format being Xused for the label-type. X.LP XAll label-definition, etc., lines are copied unchanged to the output. X.PP X\fILabel References\fR: Xa label-reference is introduced and terminated by a X.I delimiter Xcharacter (default ``@''); Xthe opening delimiter is followed by a label-type and a label-name; Xthe entire reference is replaced by the value of the specified label, Xprinted according to the format specified for the label-type (see below). X.PP X\fIPrint Formats\fR: Xa print format consists of a literal string containing escape-sequences Xfor which successive values of the level counts of a label are substituted. XThe format is copied only as far as the escape sequence for the last level Xof the label being printed, and it is an error for there to be too few Xescape sequences. XThe sequences are X.IP %1 Xprint in arabic numerals, no non-significant leading zeros; X.IP %0 Xprint as for ``%1'', but subtracting 1 so that counts start from 0 rather than X1. X.IP %i Xprint in lower-case roman numerals; X.IP %I Xprint in upper-case roman; X.IP %a Xprint as a lower-case letter (starting at ``a''); X.IP %A Xprint as an upper-case letter. X``%'' followed by any other character prints as that character. X.LP XThe default format is to print all levels in arabic, separated by periods X(i.e. "%1.%1.%1.%1\ ..."). X.PP X\fICommand Line Options\fR: X.IP -d\fIdelim\fR X.br X.I delim Xis a single character to be used in place of ``@'' Xas the label-reference delimiter. X.IP -m\fImacro\fR X.br X.I macro Xis a 2-character macro-name to be used in place of ``.L='' as the Xlabel-definition macro. X.IP -l Xcauses a listing of all label-definitions to be written to the standard Xerror stream. X.IP -s Xsuppresses all output except error messages and the listing generated by Xthe \fI-l\fR option, which is automatically turned on. X.SH EXAMPLE X Input X .L= sec 1 intro X .L= format sec %A.%1.%1.%1.%1 X .L= last table 3 1 X This is Section @sec intro@; it is followed by Section X @sec next@ which contains Section @sec subsection@. X .L= table 2 only. X The only table used is Table @table only@. X .L= sec 1 next X .L= sec 2 subsection X Output X .L= sec 1 intro X .L= format sec %A.%1.%1.%1.%1 X .L= last table 3 1 X This is Section A; it is followed by Section X B which contains Section B.1. X .L= table 2 only. X The only table used is Table 3.2. X .L= sec 1 next X .L= sec 2 subsection X.SH BUGS XWith the X.I -s Xoption, errors such as reference to an undefined label, which can only Xbe detected on a second scan of the input, are not reported. X.SH FILES X/tmp/lbl* - temporary storage X.SH "SEE ALSO" Xtroff(1), nroff(1), eqn(1), refer(1), tbl(1) End-of-file echo Making directory hdr. mkdir hdr echo Extracting hdr/ftypes.h sed 's/^X//' <<'End-of-file' >hdr/ftypes.h X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X Xchar *copy(); Xlabel *findlabel(); Xtype *addtype(); Xtype *findtype(); X Xchar *fgets(); Xchar *malloc(); Xchar *mktemp(); End-of-file echo Extracting hdr/lbl.h sed 's/^X//' <<'End-of-file' >hdr/lbl.h X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X#include <stdio.h> X#include <types.h> X#include <ftypes.h> X X#define STDFORM "%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1.%1" X X#define MAGIC1 '\01' X#define MAGIC2 '\02' X#define M_FILE 'F' X#define M_DELIM 'D' End-of-file echo Extracting hdr/types.h sed 's/^X//' <<'End-of-file' >hdr/types.h X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X#define rg register X#define us unsigned X X/*** Header levels ***/ X#define NLEVELS 20 Xtypedef us int levels[NLEVELS]; X X/*** Header format ***/ Xtypedef char *format; X X/*** Label type: name and current header levels ***/ Xtypedef struct type X{ X char *t_name; X levels t_levels; X format t_format; X struct label *t_labels; X struct type *t_next; X} type; X X/*** Label definition ***/ Xtypedef struct label X{ X char *l_name; X type *l_type; X levels l_levels; X us int l_bottom; /* Last significant level */ X char *l_file; /* File where defined */ X long l_line; /* line " " */ X struct label *l_next; X} label; X X/*** Action routine ***/ Xtypedef int (*func)(); X X/*** Command keyword ***/ Xtypedef struct keyword X{ X char *k_name; X func k_action; X us int k_minargs; X us int k_maxargs; X} keyword; End-of-file echo Making directory src. mkdir src echo Extracting src/Makefile sed 's/^X//' <<'End-of-file' >src/Makefile XOBJS=lbl.o actions.o build.o error.o externs.o find.o keyword.o list.o printl.o rescan.o scan.o signals.o XSRCS=lbl.c actions.c build.c error.c externs.c find.c keyword.c list.c printl.c rescan.c scan.c signals.c XHDR=../hdr X XCFLAGS=-O -I$(HDR) XLDFLAGS= X Xlbl: $(OBJS) X cc -o lbl $(LDFLAGS) $(OBJS) X Xlint: $(SRCS) X lint -abchx $(SRCS) X Xtags: $(SRCS) X ctags $(SRCS) X Xclean: X rm -f *.o tags lbl X X$(OBJS): $(HDR)/lbl.h $(HDR)/types.h $(HDR)/ftypes.h End-of-file echo Extracting src/actions.c sed 's/^X//' <<'End-of-file' >src/actions.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* actions.c: X * keyword action routines X */ X X#include <lbl.h> X#include <ctype.h> X Xextern char *def_format; Xextern int sflag; Xextern FILE *tempfile; X X/*ARGSUSED*/ Xa_delimiter(nargs, argvec) X int nargs; X char *argvec[]; X{ X if (strcmp(argvec[1], "off") == 0) X { X if (!sflag) X fprintf(tempfile, "%c%c%c\n", MAGIC1, MAGIC2, M_DELIM); X return; X } X if (argvec[1][1] != '\0') X { X error("delimiter more than 1 character"); X return; X } X if (argvec[1][0] == '\0') X { X error("null delimiter character"); X return; X } X if (!sflag) X fprintf(tempfile, "%c%c%c%c\n", MAGIC1, MAGIC2, X M_DELIM, argvec[1][0]); X} X X/*ARGSUSED*/ Xa_format(nargs, argvec) X int nargs; X char *argvec[]; X{ X type *tp = findtype(argvec[1], 1); X X if (tp->t_format != def_format) X error("[warning] format for %s redefined", tp->t_name); X tp->t_format = copy(argvec[2]); X} X X/*ARGSUSED*/ Xa_last(nargs, argvec) X int nargs; X char *argvec[]; X{ X type *tp = findtype(argvec[1], 1); X int indx; X X nargs -= 2; X argvec += 2; X for (indx = 0; indx < nargs; indx++) X { X if (!isdigit(argvec[indx][0])) X { X error("non-numeric label index"); X break; X } X tp->t_levels[indx] = atoi(argvec[indx]); X } X while (indx < NLEVELS) X tp->t_levels[indx++] = 0; X} End-of-file echo Extracting src/build.c sed 's/^X//' <<'End-of-file' >src/build.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* build.c: X * routines to build new labels and label-types X */ X X#include <lbl.h> X#include <ctype.h> X Xextern char *def_format; Xextern char *filename; Xextern long fileline; Xextern type *typetable; X Xchar *alloc(nbytes) X us int nbytes; X{ X char *malloc(); X char *ptr = malloc(nbytes); X X if (ptr==NULL) X fatal("ran out of memory space"); X return ptr; X} X Xchar * Xcopy(str) X char *str; X{ X char *strcpy(); X us int strlen(); X X char *s = alloc(strlen(str)+1); X X return strcpy(s, str); X} X Xaddlbl(lbltype, lbllevel, lblname) X char *lbltype; X char *lbllevel; X char *lblname; X{ X type *tp = findtype(lbltype, 1); X label *lp; X label *last; X us int bottom; X us int indx; X X if (!isdigit(lbllevel[0])) X { X error("non-numeric index level"); X return; X } X if ((bottom = atoi(lbllevel)) == 0 || bottom > NLEVELS) X { X error("index level must be in range 1-%u", NLEVELS); X return; X } X bottom--; X X ++(tp->t_levels[bottom]); X for (indx = bottom+1; indx < NLEVELS; indx++) X tp->t_levels[indx] = 0; X X if (strcmp(lblname, "*") != 0) X { X lp = findlabel(tp, lblname); X X if (lp != NULL) X { X error("redefinition of %s ignored", lblname); X return; X } X lp = (label *) alloc(sizeof(label)); X X lp->l_name = copy(lblname); X lp->l_type = tp; X for (indx = 0; indx < bottom; indx++) X lp->l_levels[indx] = tp->t_levels[indx]; X lp->l_levels[bottom] = tp->t_levels[bottom]; X lp->l_bottom = bottom; X lp->l_file = filename; X lp->l_line = fileline; X lp->l_next = NULL; X /* Add to end of list, so that verbose listing comes out X * in order X */ X if (tp->t_labels == NULL) X tp->t_labels = lp; X else X { X for (last = tp->t_labels; last->l_next != NULL; X last = last->l_next) X ; X last->l_next = lp; X } X } X} X Xtype * Xaddtype(name) X char *name; X{ X type *tp = (type *) alloc(sizeof(type)); X us int indx; X X tp->t_name = copy(name); X for (indx = 0; indx < NLEVELS; indx++) X tp->t_levels[indx] = 0; X tp->t_format = def_format; X tp->t_labels = NULL; X tp->t_next = typetable; X typetable = tp; X return tp; X} End-of-file echo Extracting src/error.c sed 's/^X//' <<'End-of-file' >src/error.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* error.c: X * report and handle errors X */ X X#include <lbl.h> X Xextern char *progname; Xextern char *filename; Xextern char tempname[]; Xextern long fileline; X X/*VARARGS1*/ Xerror(msg, arg1) X char *msg; X char *arg1; X{ X fprintf(stderr, "%s: ", progname); X if (filename != NULL) X fprintf(stderr, "%s, line %D - ", filename, fileline); X fprintf(stderr, msg, arg1); X fprintf(stderr, "\n"); X} X X/*VARARGS1*/ Xfatal(msg, arg1) X char *msg; X char *arg1; X{ X error(msg, arg1); X unlink(tempname); X exit(1); X} End-of-file echo Extracting src/externs.c sed 's/^X//' <<'End-of-file' >src/externs.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X#include <lbl.h> X Xchar delimiter = '@'; Xchar macroname[] = "L="; Xchar tempname[] = "/tmp/lblXXXXXX"; Xchar *def_format = STDFORM; Xchar *progname = "lbl"; Xchar *filename = NULL; Xint lflag = 0; Xint sflag = 0; XFILE *tempfile = NULL; Xlong fileline; Xtype *typetable = NULL; End-of-file echo Extracting src/find.c sed 's/^X//' <<'End-of-file' >src/find.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* find.c: X * routines to find a type entry and a label entry X */ X X#include <lbl.h> X Xextern type *typetable; X Xtype * Xfindtype(name, create) X rg char *name; X rg int create; X{ X rg type *tp; X X for (tp = typetable; tp != NULL; tp = tp->t_next) X if (strcmp(name, tp->t_name) == 0) X return tp; X if (create) X return addtype(name); X return NULL; X} X Xlabel * Xfindlabel(tp, name) X rg type *tp; X rg char *name; X{ X rg label *lp; X X if (tp == NULL) X return NULL; X for (lp = tp->t_labels; lp != NULL; lp = lp->l_next) X if (strcmp(name, lp->l_name) == 0) X return lp; X return NULL; X} End-of-file echo Extracting src/keyword.c sed 's/^X//' <<'End-of-file' >src/keyword.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* keyword.c: X * look up a command keyword (by sequential search). X */ X X#include <lbl.h> X Xextern int a_delimiter(); Xextern int a_format(); Xextern int a_last(); X Xkeyword keytable[] = X{ X { "delimiter", a_delimiter, 2, 2 }, X { "format", a_format, 3, 3 }, X { "last", a_last, 3, 22 } X}; X#define NKEYS (sizeof(keytable) / sizeof(keyword)) X Xkeyword * Xfindkeyword(word) X char *word; X{ X int indx; X X for (indx=0; indx < NKEYS; indx++) X if (strcmp(word, keytable[indx].k_name) == 0) X return keytable+indx; X return NULL; X} End-of-file echo Extracting src/lbl.c sed 's/^X//' <<'End-of-file' >src/lbl.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* lbl.c: X * main program - decode switches and arguments X * and process each input file. X * usage: X * lbl [ -d<char> ] [ -m<macro> ] [ -l ] [ -s ] X * -d <char> delimits in-line occurrences of a tag X * -m <macro> defines a tag value X * -l list label definitions X * -s suppress nroff output (implies -l) X * defaults: X * -d@ -mL= X */ X X#include <lbl.h> X Xextern int lflag; Xextern int sflag; Xextern char delimiter; Xextern char macroname[]; Xextern char tempname[]; Xextern char *progname; Xextern FILE *tempfile; X Xmain(argc, argv) X us int argc; X char *argv[]; X{ X us int decode(); X us int nflags; X FILE *input; X int anydone = 0; X static char standard[] = "standard input"; X X if (argc != 0) X { X argc--; X progname = *(argv++); X } X nflags = decode(argc, argv); X argc -= nflags; X argv += nflags; X X /* Remaining arguments must be filenames; treat "-" X * specially as standard input. X * If no arguments, use atandard input. X */ X X /* Pass 1: copy to temp file, building table of tags */ X if (!sflag) X { X mktemp(tempname); X if ((tempfile=fopen(tempname, "w"))==NULL) X fatal("cannot make temporary file"); X setsignals(); X } X if (argc == 0) X { X scan(standard, stdin); X anydone = 1; X } X else X { X while (argc != 0) X { X if (strcmp(argv[0], "-") == 0) X { X anydone = 1; X scan(standard, stdin); X } X else X { X if ((input=fopen(argv[0], "r")) == NULL) X error("cannot open %s", argv[0]); X else X { X anydone = 1; X scan(argv[0], input); X fclose(input); X } X } X argc--; X argv++; X } X } X if (!sflag) X fclose(tempfile); X if (lflag) X listdefs(); X X /* Pass 2: translate tags */ X X if (!anydone) X { X unlink(tempname); X exit(3); X } X if (!sflag) X { X if ((tempfile=fopen(tempname, "r")) == NULL) X fatal("temporary file vanished before rescan!"); X rescan(); X unlink(tempname); X } X exit(0); X} X X/* Decode argument list */ Xus int Xdecode(argc, argv) X us int argc; X char *argv[]; X{ X int nflags = 0; X X while (argc != 0) X { X if (argv[0][0] != '-') X return nflags; X switch (argv[0][1]) X { X case 'd': X if ((delimiter=argv[0][2]) == '\0') X fatal("missing delimiter after -d"); X if (argv[0][3] != '\0') X fatal("delimiter must be 1 character"); X break; X case 'm': X if ((macroname[0]=argv[0][2]) == '\0' || X (macroname[1]=argv[0][3]) == '\0' || X argv[0][4] != '\0') X fatal( X "macro name must be 2 characters"); X break; X case 'l': X lflag = 1; X break; X case 's': X lflag = sflag = 1; X break; X default: X fatal("unknown flag '%s'", argv[0]); X /*NOTREACHED*/ X } X argc--; X argv++; X nflags++; X } X return nflags; X} End-of-file echo Extracting src/list.c sed 's/^X//' <<'End-of-file' >src/list.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* list.c: X * list definitions in verbose mode X */ X X#include <lbl.h> X Xextern char *def_format; Xextern type *typetable; X Xlistdefs() X{ X type *tp; X X if (typetable == NULL) X { X fprintf(stderr, "No labels defined\n"); X return; X } X for (tp = typetable; tp != NULL; tp = tp->t_next) X listtype(tp); X} X Xlisttype(tp) X type *tp; X{ X label *lp; X X fprintf(stderr, "*** Type %s: format %s\n", tp->t_name, X tp->t_format==def_format ? "default" : tp->t_format); X if (tp->t_labels == NULL) X { X fprintf(stderr, "(No labels defined\n)"); X return; X } X for (lp = tp->t_labels; lp != NULL; lp = lp->l_next) X { X fprintf(stderr, "%-16.16s %-14.14s %-6D ", X lp->l_name, X lp->l_file, X lp->l_line); X printl(lp, stderr); X putc('\n', stderr); X } X putc('\n', stderr); X} End-of-file echo Extracting src/printl.c sed 's/^X//' <<'End-of-file' >src/printl.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* printl.c: X * print a label according to a format X */ X X#include <lbl.h> X Xprintl(lab, out) X rg label *lab; X rg FILE *out; X{ X rg format f = lab->l_type->t_format; X rg us int i; X X for (i = 0; i <= lab->l_bottom; i++) X { X while (*f) X { X if (*f != '%') X putc(*f, out); X else X switch (*++f) X { X default: X putc(*f, out); X break; X case '\0': X putc('%', out); X break; X case '0': X printd(lab->l_levels[i]-1, out); X f++; X goto loopend; X case '1': X printd(lab->l_levels[i], out); X f++; X goto loopend; X case 'i': X case 'I': X printr(*f, lab->l_levels[i], X out); X f++; X goto loopend; X case 'a': X case 'A': X printa(*f, lab->l_levels[i], X out); X f++; X goto loopend; X } X f++; X } X error("format too short to print label %s", lab->l_name); X break; X loopend: X continue; X } X} X X/* Print Decimal */ Xprintd(n, out) X us int n; X FILE *out; X{ X fprintf(out, "%u", n); X} X X/* Print Alphabetic X * actually base 26 (digits a-z), displaced by 1! X * a is either "a" or "A" for upper or lower case. X */ Xprinta(a, n, out) X char a; X us int n; X FILE *out; X{ X if (n==0) X putc('0', out); X else X auxprinta(a, n-1, out); X} X Xauxprinta(a, n, out) X char a; X us int n; X FILE *out; X{ X if (n > 25) X auxprinta(a, n/26 - 1, out); X putc(a + n%26, out); X} X X/* Print Roman X * a is either "a" or "A" for upper or lower case. X */ Xprintr(a, n, out) X char a; X us int n; X FILE *out; X{ X if (n==0) X { X putc('0', out); X return; X } X if (n >= 50000) X { X putc('!', out); X return; X } X while (n >= 10000) X putc(a+('Z'-'I'), out), n -= 10000; X if (n >= 9000) X putc(a+('M'-'I'), out), putc(a+('Z'-'I'), out), n -= 9000; X if (n >= 5000) X putc(a+('W'-'I'), out), n -= 5000; X if (n >= 4000) X putc(a+('M'-'I'), out), putc(a+('W'-'I'), out), n -= 4000; X while (n >= 1000) X putc(a+('M'-'I'), out), n -= 1000; X if (n >= 900) X putc(a+('C'-'I'), out), putc(a+('M'-'I'), out), n -= 900; X if (n >= 500) X putc(a+('D'-'I'), out), n -= 500; X if (n >= 400) X putc(a+('C'-'I'), out), putc(a+('D'-'I'), out), n -= 400; X while (n >= 100) X putc(a+('C'-'I'), out), n -= 100; X if (n >= 90) X putc(a+('X'-'I'), out), putc(a+('C'-'I'), out), n -= 90; X if (n >= 50) X putc(a+('L'-'I'), out), n -= 50; X if (n >= 40) X putc(a+('X'-'I'), out), putc(a+('L'-'I'), out), n -= 40; X while (n >= 10) X putc(a+('X'-'I'), out), n -= 10; X if (n >= 9) X putc(a+('I'-'I'), out), putc(a+('X'-'I'), out), n -= 9; X if (n >= 5) X putc(a+('V'-'I'), out), n -= 5; X if (n >= 4) X putc(a+('I'-'I'), out), putc(a+('V'-'I'), out), n -= 4; X while (n >= 1) X putc(a+('I'-'I'), out), n -= 1; X} End-of-file echo Extracting src/rescan.c sed 's/^X//' <<'End-of-file' >src/rescan.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* rescan.c: X * read temporary file, substituting for defined labels X */ X X#include <lbl.h> X#include <ctype.h> X Xextern char delimiter; Xextern char *filename; Xextern FILE *tempfile; Xextern long fileline; X Xint translate = 1; X Xrescan() X{ X rg int c; X /* Keep tempfile, delimiter and translate flag in registers to X * speed up this routine; the last two need to be reloaded after X * and only after calls to domagic() X */ X rg FILE *tf = tempfile; X rg int dlm = delimiter; X rg int tr = translate; X X while ((c = getc(tf)) != EOF) X { X if (c == MAGIC1) X { X if ((c = getc(tf)) == MAGIC2) X { X domagic(); X dlm = delimiter; X tr = translate; X continue; X } X else X ungetc(c, tf); X } X if (c == dlm && tr) X { X doreplace(); X continue; X } X if (c == '\n') X fileline++; X putchar(c); X } X} X Xdomagic() X{ X int c; X static char buffer[BUFSIZ]; X X switch (getc(tempfile)) X { X case M_DELIM: X c = getc(tempfile); X if (c == '\n') X translate = 0; X else X { X translate = 1; X delimiter = c; X getc(tempfile); X } X break; X case M_FILE: X fgets(buffer, BUFSIZ, tempfile); X buffer[strlen(buffer)-1] = '\0'; X filename = buffer; X fileline = 1; X break; X } X} X Xdoreplace() X{ X rg int c; X char typename[BUFSIZ]; X char labelname[BUFSIZ]; X rg type *tp; X rg label *lp; X X /* <delimiter><delimiter> gives <delimiter> as output */ X if ((c = getc(tempfile)) == delimiter) X { X putchar(delimiter); X return; X } X ungetc(c, tempfile); X getword(typename); X getword(labelname); X if ((c = getc(tempfile)) != delimiter) X { X error("malformed label reference"); X while (c != delimiter) X { X if (c == EOF || c == '\n') X break; X c = getc(tempfile); X } X return; X } X if ((tp = findtype(typename, 0)) == NULL) X { X error("undefined type '%s'", typename); X printf("<<%s %s>>", typename, labelname); X return; X } X if ((lp = findlabel(tp, labelname)) == NULL) X { X error("undefined label '%s'", labelname); X printf("<<%s %s>>", typename, labelname); X return; X } X printl(lp, stdout); X} X Xgetword(buffer) X rg char *buffer; X{ X rg int c; X rg int dlm = delimiter; X rg FILE *tf = tempfile; X X c = getc(tf); X while (isspace(c)) X c = getc(tf); X while (c != dlm && !isspace(c) && c != '\n' && c != EOF) X { X *buffer++ = c; X c = getc(tf); X } X *buffer = '\0'; X if (!isspace(c) && c != EOF) X ungetc(c, tf); X} End-of-file echo Extracting src/scan.c sed 's/^X//' <<'End-of-file' >src/scan.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* scan.c: X * scan an input file, recording label-definitions, etc. X * All special actions are introduced by a line starting X * .<macro> X * where <macro> is "L=" unless redefined in the command-line. X * Actions are X * .L= <type> <level> <label> X * define <label> by incrementing the <level>th X * index of label-type <type>, e.g. X * .L= table 1 profits_1983 X * .L= delimiter <char> X * redefines the delimiter for the subsequent text. X * .L= format <type> <string> X * defines a format for displaying the given label <type>; X * the latest definition in the input will be used for X * ALL occurrences, including preceding ones. X * e.g. X * .L= format appendix %A-%1 X * .L= next <type> <value> <value> ... X * set the value of the next label generated for <type>; X * the <value>s give successive levels, with omitted X * trailing values defaulting to 0. X */ X X#include <lbl.h> X#include <ctype.h> X Xextern char macroname[]; Xextern char *filename; Xextern int sflag; Xextern FILE *tempfile; Xextern long fileline; X Xscan(fname, f) X rg char *fname; X rg FILE *f; X{ X char line[BUFSIZ]; X rg int line_complete = 1; X X /* Mark start of file in temp file */ X if (!sflag) X fprintf(tempfile, "%c%c%c%s\n", MAGIC1, MAGIC2, M_FILE, fname); X filename = fname; X fileline = 0L; X X while (fgets(line, BUFSIZ, f) != NULL) X { X if (!sflag) X fputs(line, tempfile); X if (line_complete) X { X fileline++; X line_complete = line[strlen(line)-1] == '\n'; X if (line[0]=='.' && line[1]==macroname[0] && X line[2]==macroname[1]) X { X if (line_complete) X process(line+3); X else X error(".%s line too long", macroname); X } X } X else X line_complete = line[strlen(line)-1] == '\n'; X } X} X Xprocess(line) X char *line; X{ X us int split(); X keyword *findkeyword(); X us int nargs; X char *argvec[NLEVELS+2]; X keyword *key; X X if ((nargs = split(line, argvec)) == 0) X { X error("empty .%s line", macroname); X return; X } X X /* Check for and act upon reserved words */ X if ((key = findkeyword(argvec[0])) != NULL) X { X if (nargs < key->k_minargs) X { X error("%s - too few arguments", key->k_name); X return; X } X if (nargs > key->k_maxargs) X { X error("%s - too many arguments", key->k_name); X return; X } X (*(key->k_action))(nargs, argvec); X return; X } X X /* Process a label definition */ X if (nargs != 3) X { X error("too %s arguments in label definition", X nargs < 3 ? "few" : "many"); X return; X } X addlbl(argvec[0], argvec[1], argvec[2]); X} X X/* split - split a line into arguments X * N.B. successive calls of this invalidate earlier calls; X * argvec is set to point to strings within the X * static local buffer "copybuf" which is overwritten on X * each call. X */ Xus int Xsplit(line, argvec) X char *line; X char *argvec[]; X{ X us int nargs = 0; X static char copybuf[BUFSIZ]; X char *ln = copybuf; X X strcpy(ln, line); X while (*ln) X { X while (isspace(*ln)) X ln++; X if (*ln) X { X if (nargs > 2+NLEVELS) X { X error("surplus arguments to .%s ignored", X macroname); X break; X } X argvec[nargs++] = ln; X while (*ln && !isspace(*ln)) X ln++; X if (*ln) X *ln++ = '\0'; X } X } X if (nargs > 2+NLEVELS) X nargs = 2+NLEVELS; X return nargs; X} End-of-file echo Extracting src/signals.c sed 's/^X//' <<'End-of-file' >src/signals.c X/* (C) C.D.F. Miller, Heriot-Watt University, March 1984 X * X * Permission is hereby given to reproduce or modify this X * software freely, provided that this notice be retained, X * and that no use be made of the software for commercial X * purposes without the express written permission of the X * author. X */ X X/* signals.c: X * provide clean-up after trapping external signals X */ X X#include <lbl.h> X#include <signal.h> X Xextern char tempname[]; X Xint Xonsignal() X{ X unlink(tempname); X _exit(2); X} X Xsetsignals() X{ X int (*oldsig)(); X X if ((oldsig=signal(SIGINT, onsignal)) == SIG_IGN) X signal(SIGINT, SIG_IGN); X if ((oldsig=signal(SIGQUIT, onsignal)) == SIG_IGN) X signal(SIGQUIT, SIG_IGN); X if ((oldsig=signal(SIGHUP, onsignal)) == SIG_IGN) X signal(SIGHUP, SIG_IGN); X if ((oldsig=signal(SIGTERM, onsignal)) == SIG_IGN) X signal(SIGTERM, SIG_IGN); X} End-of-file echo End of archive exit 0 -- Chris Miller, Heriot-Watt University, Edinburgh ...!ukc!{cstvax,kcl-cs}!hwcs!chris chris@hwcs.uucp