[net.sources] LBL - a symbolic label pre-processor for NROFF

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