hutch@lzaz.ATT.COM (R.HUTCHISON) (02/18/88)
When writing a document, I want to be able to symbolically reference some point in my (or someone else's) document. FOr example, in my document, I want to say... ... for more information, refer to page XX (section 1.2.3) of this manual. I don't want to hard-code either the page number or the section number because if I change the document substantially these numbers will change and I might forget to adjust all the references. I would like to be able to mark a point in my document, assign a symbol (hopefully not only 2 characters) and then reference that symbol elsewhere. I would like forward and backward references (I know I might have to troff it twice - it would be worth it). Has anyone solved this one? If so, would you like to share it with me (us)? Thanks much Robert Hutchison ihnp4!lzaz!hutch
carvalho@garnet.berkeley.edu (Marcio de Carvalho) (02/19/88)
In article <63@lzaz.ATT.COM> hutch@lzaz.ATT.COM (R.HUTCHISON) writes: >When writing a document, I want to be able to symbolically reference >some point in my (or someone else's) document. FOr example, in my >document, I want to say... > > ... for more information, refer to page XX (section 1.2.3) > of this manual. > Have a look at the following reference: A. Aho and R. Sethi, "Maintaining Cross References in Manuscripts," Software- Practice and Experience, 18, pp 1-13, 1988. They show how to use UNIX tools (grep awk and sed) to maintain cross references. One of their examples is exactly what you want.
morrell@hpsal2.HP.COM (Michael Morrell) (02/20/88)
/ hpsal2:comp.text / hutch@lzaz.ATT.COM (R.HUTCHISON) / 4:34 am Feb 18, 1988 / When writing a document, I want to be able to symbolically reference some point in my (or someone else's) document. FOr example, in my document, I want to say... ... for more information, refer to page XX (section 1.2.3) of this manual. I don't want to hard-code either the page number or the section number because if I change the document substantially these numbers will change and I might forget to adjust all the references. I would like to be able to mark a point in my document, assign a symbol (hopefully not only 2 characters) and then reference that symbol elsewhere. I would like forward and backward references (I know I might have to troff it twice - it would be worth it). Has anyone solved this one? If so, would you like to share it with me (us)? Thanks much Robert Hutchison ihnp4!lzaz!hutch ---------- Have you tried the lbl program that was posted some time back. I think it was in comp.sources.unix. I'll post a copy if there's enough interest. Michael Morrell hpda!morrell
morrell@hpsal2.HP.COM (Michael Morrell) (02/25/88)
> Have you tried the lbl program that was posted some time back. I think > it was in comp.sources.unix. I'll post a copy if there's enough interest. > Michael Morrell > hpda!morrell ---------- I received several mail messages asking for the program. It is available through volume 6 of comp.sources.unix, but since it is not that large, I'll just post it here. Michael #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Introduction # Makefile # NOTICE # READ.ME # doc # hdr # src # This archive created: Thu Jul 3 23:27:04 1986 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Introduction'" '(1433 characters)' if test -f 'Introduction' then echo shar: "will not over-write existing file 'Introduction'" else sed 's/^ X//' << \SHAR_EOF > '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 SHAR_EOF if test 1433 -ne "`wc -c < 'Introduction'`" then echo shar: "error transmitting 'Introduction'" '(should have been 1433 characters)' fi fi echo shar: "extracting 'Makefile'" '(375 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^ X//' << \SHAR_EOF > '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 SHAR_EOF if test 375 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 375 characters)' fi fi echo shar: "extracting 'NOTICE'" '(611 characters)' if test -f 'NOTICE' then echo shar: "will not over-write existing file 'NOTICE'" else sed 's/^ X//' << \SHAR_EOF > '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 SHAR_EOF if test 611 -ne "`wc -c < 'NOTICE'`" then echo shar: "error transmitting 'NOTICE'" '(should have been 611 characters)' fi fi echo shar: "extracting 'READ.ME'" '(107 characters)' if test -f 'READ.ME' then echo shar: "will not over-write existing file 'READ.ME'" else sed 's/^ X//' << \SHAR_EOF > 'READ.ME' Xdoc contains manual page and more extensive guide Xhdr contains header files Xsrc contains the C source code SHAR_EOF if test 107 -ne "`wc -c < 'READ.ME'`" then echo shar: "error transmitting 'READ.ME'" '(should have been 107 characters)' fi fi if test ! -d 'doc' then echo shar: "creating directory 'doc'" mkdir 'doc' fi echo shar: "entering directory 'doc'" cd 'doc' echo shar: "extracting 'Makefile'" '(187 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^ X//' << \SHAR_EOF > '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) SHAR_EOF if test 187 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 187 characters)' fi fi echo shar: "extracting 'READ.ME'" '(548 characters)' if test -f 'READ.ME' then echo shar: "will not over-write existing file 'READ.ME'" else sed 's/^ X//' << \SHAR_EOF > '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 SHAR_EOF if test 548 -ne "`wc -c < 'READ.ME'`" then echo shar: "error transmitting 'READ.ME'" '(should have been 548 characters)' fi fi echo shar: "extracting 'example.n'" '(850 characters)' if test -f 'example.n' then echo shar: "will not over-write existing file 'example.n'" else sed 's/^ X//' << \SHAR_EOF > '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 SHAR_EOF if test 850 -ne "`wc -c < 'example.n'`" then echo shar: "error transmitting 'example.n'" '(should have been 850 characters)' fi fi echo shar: "extracting 'lbl'" '(9613 characters)' if test -f 'lbl' then echo shar: "will not over-write existing file 'lbl'" else sed 's/^ X//' << \SHAR_EOF > '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 SHAR_EOF if test 9613 -ne "`wc -c < 'lbl'`" then echo shar: "error transmitting 'lbl'" '(should have been 9613 characters)' fi fi echo shar: "extracting 'lbl.1'" '(5623 characters)' if test -f 'lbl.1' then echo shar: "will not over-write existing file 'lbl.1'" else sed 's/^ X//' << \SHAR_EOF > '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) SHAR_EOF if test 5623 -ne "`wc -c < 'lbl.1'`" then echo shar: "error transmitting 'lbl.1'" '(should have been 5623 characters)' fi fi echo shar: "extracting 'lbl.doc'" '(10768 characters)' if test -f 'lbl.doc' then echo shar: "will not over-write existing file 'lbl.doc'" else sed 's/^ X//' << \SHAR_EOF > 'lbl.doc' X X X X X X X X X X LBL - Symbolic Labels in Text Documents X X X X X X1. Introduction X X _l_b_l is a pre-processor for _t_r_o_f_f and _n_r_o_f_f which allows XSections, Figures, Tables, etc., to be referred to by Xsymbolic names rather than by absolute number. It will Xhandle forward references as well as backward ones. X X Uses of a label in the text are indicated by a Xdelimiter character (default '@', but resettable), followed Xby a _t_y_p_e name (e.g. "TABLE", "EQN", etc.), followed by the Xlabel itself (e.g. "Profits-1983"). Each such occurrence is Xreplaced by a reference number; the default style of Xnumbering is a sequence of period-separated arabic numbers X(e.g. 2.4.1) but this is resettable. Finally, another Xdelimiter is required to close the reference (cf. the use of Xdelimiters in _e_q_n for in-line equations). X XExamples: X X For full details refer to Table @TABLE Profits-1983@. X As we saw in Chapter @chap intro@, ... X Figure @fig wing-profile@ shows the airflow patterns ... X X X Labels may be defined at any point in the text. The Xdefinition looks like a _t_r_o_f_f macro, and the definition line Xis retained in the original text. By default, the macro Xused is ".L=", but this can be reset. The macro takes 3 Xarguments: a type-name, a level-number, and a label-name. X X The type-name corresponds to that used to signal a Xlabel occurrence in the text. There is no restriction on Xthe choice of name; any sequence of non-blank characters may Xbe used. Upper- and lower-case letters _a_r_e distinguished. X X The level-number corresponds to the header-level Xnumbers used by the .NH macro in _m_s, the .sh macro in _m_e, Xetc. The index at the given level is incremented by 1, and Xall higher indexes set to 0. Initially, all indexes are set Xto 0 by default, but other starting values may be chosen. XThere is an implementation-defined restriction on the number Xof levels of index (currently 20); it is not anticipated Xthat this will lead to problems. X X The label may be any sequence of non-blank characters; X X X X X X X X X X - 2 - X X Xthe same label may be used in more than one type. XFurthermore, the special label-name ``*'' can be used to Xincrement the appropriate level-counter without defining a Xlabel at all; this is useful, for example, when all tables, Xfigures, etc., in a section take their initial index from Xthe section number: two ways of doing this would be: X 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 3 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 XIt is largely a matter of taste which technique is used; the Xformer is more long-winded, but avoids the need to remember Xto keep the tables and figures in step every time the Xsection is updated. Yet a third possibility (similar to the Xfirst) would be: X Xc. X .L= section 1 this-section X .ds Sc "@section this-section@ X .L= last table 0 X ... X ... refer to table .@table profits@ X etc. X Xmaking use of the string-definition facility within _n_r_o_f_f. X X It is important to be aware that all processing on Xlabels is done before _t_r_o_f_f processes the text; attempts to X X X X X X X X X X - 3 - X X Xbuild label-references by using macros or _t_r_o_f_f strings Xregisters will almost certainly not work as expected. X X2. Command Line Options X X Options to _l_b_l are set in the command line, which has Xthe form X X lbl [ -d_d_e_l_i_m ] [ -m_m_a_c_r_o ] [ -l ] [ -s ] X X X-d _d_e_l_i_m is the character used to delimit in-line X occurrences of label references (default ``@''); X X-m _m_a_c_r_o is the 2-character name of a _t_r_o_f_f macro which X introduces label definitions, etc. (default ``L=''); X X-l causes a listing of label-definitions to be written to X the standard error stream. Each label-type is listed, X together with its print format, followed by a line for X each label of that type, showing label-name, file and X line where it is defined, and value; X X-s causes the generation of the _t_r_o_f_f input file to be X suppressed; setting -_s automatically also sets -_l. X X3. Control directives X X In addition to defining labels, the .L= macro (or its Xsubstitute) can be used for several other purposes. These Xare all indicated by commands of the form X X .L= _c_o_m_m_a_n_d _a_r_g_u_m_e_n_t ... X Xwhere the _c_o_m_m_a_n_ds are reserved words which may not be used Xas type-names. These commands allow control over the Xinitialisation of label values, the print format of labels, Xand thelabel reference delimiter. X X.L= delimiter off X turns off interpretation of the delimiter character X altogether; subsequent text is copied literally until X another _d_e_l_i_m_i_t_e_r command is encountered; X X.L= delimiter _c_h_a_r_a_c_t_e_r X resets the delimiter in subsequent text to the given X character; X X.L= format _t_y_p_e_n_a_m_e _s_t_r_i_n_g X sets the print format for labels of the given type - X see section 3.1; X X.L= last _t_y_p_e_n_a_m_e _c_o_u_n_t_1 _c_o_u_n_t_2 ... X resets the counters for _t_y_p_e_n_a_m_e as though the last X X X X X X X X X X - 4 - X X X label generated had been _c_o_u_n_t_1._c_o_u_n_t_2... (with all X omitted counts taken as 0). X X3.1. Print formats X X The default print format for a label is as a sequence Xof period-separated arabic numerals. However, it is also Xpossible to specify alphabetic or roman labels, or a Xmixture, and to have separators other than a period. This Xis governed by the format given in a ``.LE format'' command. X X Such a format contains escape sequences (flagged by a X``%'' character) and literal text. The text is copied until Xan escape sequence is encountered; such a sequence is Xreplaced by the index for the next level of the label value, Xprinted in one of the following formats: X X%1 Arabic numerals (without non-significant leading X zeros); X X%0 As %1, but offset by 1 so that the first value printed X will be 0 rather than 1; X X%a Lower-case alphabetics, starting at ``a''; ``z'' is X followed by ``aa'', etc.; X X%A Upper-case alphabetics; X X%i Lower-case roman numerals (with some odd choices for X large numbers, consistent with the roman numerals X printed by _t_r_o_f_f). X X%I Upper-case roman numerals. X XA ``%'' followed by any other character (in particular Xanother ``%'') prints as that character. X X4. Limits X X _L_b_l imposes no limit on the size of text to be Xprocessed, but (like _r_e_f_e_r) needs to act on a text as a Xwhole, rather than processing individual files. The limit Xon the number of levels of header is unlikely to prove a Xproblem. The number of labels which may be used is limited Xonly by the amount of memory available to a process; even on Xa small machine it is possible to handle a few hundred label Xdefinitions. X X5. Further Examples X X The copying of the definition macros makes it possible Xto use them as _t_r_o_f_f macros, as in the following example: X X X X X X X X X X X X - 5 - X X X X .de L= X .ie '\\$1'sec' .NH \\$2 X .el .ie '\\$1'table' .if !'\\$3'*' \{ X .DS C X Table '\\$3' about here X .DE X \} X .el .if '\\$1'fig' .if !'\\$3'*' \{ X .DS C X Figure '\\$3' about here X .DE X \} 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 XIn the above, the ``.L= sec'' macros automatically generate Xthe numbered headings by expanding to the _m_s ``.NH'' macros, Xwhile the ``table'' definitions cause the insertion of Xfigures such as X X Table 'detail' about here X XThe above example thus produces the following: X X X X X X X X X X X X X - 6 - X X X X Example of LBL X X X X X X _1. _I_n_t_r_o_d_u_c_t_i_o_n 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 _2. _C_o_n_t_i_n_u_a_t_i_o_n X X In this continuation we refer back to Section X 1, which contained Table 1.1, and present more X detailed information in Table 2.1. X X X Table 'detail' about here X X X X _2._1. _S_u_b-_c_o_n_t_i_n_u_a_t_i_o_n X X In which we further refine things, as shown X in Table 2.2 below. X X X Table 'mega-detail' about here X X X The alphabetic formats may be useful for such things as Xappendices, e.g. X 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 Xwhich will generate X X X X X X X X X X X X X - 7 - X X X X _A_p_p_e_n_d_i_x _A: _L_i_s_t _o_f _R_e_g_i_s_t_e_r_e_d _T_r_a_d_e _M_a_r_k_s X X (For the addresses of the proprietors see appendix B). X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X echo shar: "274 control characters may be missing from 'lbl.doc'" SHAR_EOF if test 10768 -ne "`wc -c < 'lbl.doc'`" then echo shar: "error transmitting 'lbl.doc'" '(should have been 10768 characters)' fi fi echo shar: "done with directory 'doc'" cd .. if test ! -d 'hdr' then echo shar: "creating directory 'hdr'" mkdir 'hdr' fi echo shar: "entering directory 'hdr'" cd 'hdr' echo shar: "extracting 'ftypes.h'" '(426 characters)' if test -f 'ftypes.h' then echo shar: "will not over-write existing file 'ftypes.h'" else sed 's/^ X//' << \SHAR_EOF > '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(); SHAR_EOF if test 426 -ne "`wc -c < 'ftypes.h'`" then echo shar: "error transmitting 'ftypes.h'" '(should have been 426 characters)' fi fi echo shar: "extracting 'lbl.h'" '(528 characters)' if test -f 'lbl.h' then echo shar: "will not over-write existing file 'lbl.h'" else sed 's/^ X//' << \SHAR_EOF > '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' SHAR_EOF if test 528 -ne "`wc -c < 'lbl.h'`" then echo shar: "error transmitting 'lbl.h'" '(should have been 528 characters)' fi fi echo shar: "extracting 'types.h'" '(1122 characters)' if test -f 'types.h' then echo shar: "will not over-write existing file 'types.h'" else sed 's/^ X//' << \SHAR_EOF > '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; SHAR_EOF if test 1122 -ne "`wc -c < 'types.h'`" then echo shar: "error transmitting 'types.h'" '(should have been 1122 characters)' fi fi echo shar: "done with directory 'hdr'" cd .. if test ! -d 'src' then echo shar: "creating directory 'src'" mkdir 'src' fi echo shar: "entering directory 'src'" cd 'src' echo shar: "extracting 'Makefile'" '(446 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^ X//' << \SHAR_EOF > '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=-i 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 SHAR_EOF if test 446 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 446 characters)' fi fi echo shar: "extracting 'actions.c'" '(1518 characters)' if test -f 'actions.c' then echo shar: "will not over-write existing file 'actions.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 1518 -ne "`wc -c < 'actions.c'`" then echo shar: "error transmitting 'actions.c'" '(should have been 1518 characters)' fi fi echo shar: "extracting 'build.c'" '(2304 characters)' if test -f 'build.c' then echo shar: "will not over-write existing file 'build.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 2304 -ne "`wc -c < 'build.c'`" then echo shar: "error transmitting 'build.c'" '(should have been 2304 characters)' fi fi echo shar: "extracting 'error.c'" '(801 characters)' if test -f 'error.c' then echo shar: "will not over-write existing file 'error.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 801 -ne "`wc -c < 'error.c'`" then echo shar: "error transmitting 'error.c'" '(should have been 801 characters)' fi fi echo shar: "extracting 'externs.c'" '(579 characters)' if test -f 'externs.c' then echo shar: "will not over-write existing file 'externs.c'" else sed 's/^ X//' << \SHAR_EOF > '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; SHAR_EOF if test 579 -ne "`wc -c < 'externs.c'`" then echo shar: "error transmitting 'externs.c'" '(should have been 579 characters)' fi fi echo shar: "extracting 'find.c'" '(885 characters)' if test -f 'find.c' then echo shar: "will not over-write existing file 'find.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 885 -ne "`wc -c < 'find.c'`" then echo shar: "error transmitting 'find.c'" '(should have been 885 characters)' fi fi echo shar: "extracting 'keyword.c'" '(826 characters)' if test -f 'keyword.c' then echo shar: "will not over-write existing file 'keyword.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 826 -ne "`wc -c < 'keyword.c'`" then echo shar: "error transmitting 'keyword.c'" '(should have been 826 characters)' fi fi echo shar: "extracting 'lbl.c'" '(2926 characters)' if test -f 'lbl.c' then echo shar: "will not over-write existing file 'lbl.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 2926 -ne "`wc -c < 'lbl.c'`" then echo shar: "error transmitting 'lbl.c'" '(should have been 2926 characters)' fi fi echo shar: "extracting 'list.c'" '(1066 characters)' if test -f 'list.c' then echo shar: "will not over-write existing file 'list.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 1066 -ne "`wc -c < 'list.c'`" then echo shar: "error transmitting 'list.c'" '(should have been 1066 characters)' fi fi echo shar: "extracting 'printl.c'" '(2951 characters)' if test -f 'printl.c' then echo shar: "will not over-write existing file 'printl.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 2951 -ne "`wc -c < 'printl.c'`" then echo shar: "error transmitting 'printl.c'" '(should have been 2951 characters)' fi fi echo shar: "extracting 'rescan.c'" '(2630 characters)' if test -f 'rescan.c' then echo shar: "will not over-write existing file 'rescan.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 2630 -ne "`wc -c < 'rescan.c'`" then echo shar: "error transmitting 'rescan.c'" '(should have been 2630 characters)' fi fi echo shar: "extracting 'scan.c'" '(3478 characters)' if test -f 'scan.c' then echo shar: "will not over-write existing file 'scan.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 3478 -ne "`wc -c < 'scan.c'`" then echo shar: "error transmitting 'scan.c'" '(should have been 3478 characters)' fi fi echo shar: "extracting 'signals.c'" '(845 characters)' if test -f 'signals.c' then echo shar: "will not over-write existing file 'signals.c'" else sed 's/^ X//' << \SHAR_EOF > '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} SHAR_EOF if test 845 -ne "`wc -c < 'signals.c'`" then echo shar: "error transmitting 'signals.c'" '(should have been 845 characters)' fi fi echo shar: "extracting 'Make.log'" '(431 characters)' if test -f 'Make.log' then echo shar: "will not over-write existing file 'Make.log'" else sed 's/^ X//' << \SHAR_EOF > 'Make.log' Xcc -O -I../hdr -c lbl.c Xcc -O -I../hdr -c actions.c Xcc -O -I../hdr -c build.c Xcc -O -I../hdr -c error.c Xcc -O -I../hdr -c externs.c Xcc -O -I../hdr -c find.c Xcc -O -I../hdr -c keyword.c Xcc -O -I../hdr -c list.c Xcc -O -I../hdr -c printl.c Xcc -O -I../hdr -c rescan.c Xcc -O -I../hdr -c scan.c Xcc -O -I../hdr -c signals.c Xcc -o lbl -i lbl.o actions.o build.o error.o externs.o find.o keyword.o list.o printl.o rescan.o scan.o signals.o SHAR_EOF if test 431 -ne "`wc -c < 'Make.log'`" then echo shar: "error transmitting 'Make.log'" '(should have been 431 characters)' fi fi echo shar: "done with directory 'src'" cd .. exit 0 # End of shell archive
bd@hpsemc.HP.COM (bob desinger) (02/27/88)
In article <63@lzaz.ATT.COM> hutch@lzaz.ATT.COM (R.HUTCHISON) writes: > When writing a document, I want to be able to symbolically reference > some point in my (or someone else's) document. The new book on awk shows how to do this; my impression is that they implement the Aho and Sethi procedures in awk. You'll need the awk that has functions: either the System V.2 (I think) version or else the AT&T Toolchest version. The Toolchest version comes with all the awk scripts in the book, which saves a *lot* of typing. -- bd