Article View: comp.text
Article #683Re: page numbering between chapters in nroff
From: Henry McGilton -- Software Produ...
Date: Wed, 30 Aug 1989 22:08
Date: Wed, 30 Aug 1989 22:08
208 lines
7915 bytes
7915 bytes
In article 5223, Kevin Carothers writes:
* I have a very large document, consisting of multiple
* chapters, and I would like to pass the ending page from
* the previous chapter to the first page of the next
* chapter (plus 1, of course).
* Does anyone have any nifty algorithms for doing this?
* So far I haven't been able to figure out a simple way
* of doing this.
* The only thing that seems doable so far is to append a
* ".so" to the end of each chapter, but this is rather
* unacceptable, as each chapter can stand on its own, or
* in conjunction with all others.
What you want is doable without mucking around with .so
lines and such.
* The Nroff/Troff Users guide mentions that number
* registers (.nr %) can be read or written, but I have
* seen no example.
Be aware that even if you set the % number register from the command
line, you might not necessarily get the results you want, because
the -ms macro package uses an internal number register called
PN to record its notion of the current page.
* Ideally, I would like to set an environment variable
* with the page #, so that from a makefile I can do
* something like
* nroff -ms -n$page chapterx.ms
By an `environment variable' I assume you mean a Shell
environment variable? If so, be aware that it's only
fairly recently that make took notice of Shell
environment variables. Older versions of make couldn't
do this, and if you're stuck with such a version, you'll
have to modify the approach. I show how below.
There are several approaches.
First off, if you've already gone to the trouble of
creating a Makefile, why format one chapter at a time? Just
format the whole shebang every time. Create a Makefile
that has approximately this form:
CHAPTERS = c1.ms c2.ms c3.ms c4.ms . . . and so on . . .
DEVICE = -Tlw
MACROPACKAGE = -ms
FORMATTER = /usr/bin/troff $(DEVICE) $(MACROPACKAGE) -t
book.dit:
$(FORMATTER) $(CHAPTERS) > book.dit
This way, the document gets formatted every time, and the start
page of one chapter is one more than the end page of the previous
chapter.
OK -- it's quite possible you're concerned about the amount
of time taken to reformat the whole document every time a
line gets changed. Especially if your document is large.
But just for comparison, my 600 page UNIX System V book
formats in under two hours on a Sun-2/120 (that includes
cross references, pic, tbl, eqn, troff, tables of contents,
and index).
However, here's one way to do what you want. Create a Makefile
that looks like this:
1 DEVICE = -Tlw
2 MACROPACKAGE = -ms
3 FORMATTER = /usr/bin/troff $(DEVICE) $(MACROPACKAGE) -t
5 .SUFFIXES: .ms .dit
6 .ms.dit:
7 $(FORMATTER) -rP$$page $< > $@
Let's pull this apart. Line 5 describes the suffixes you will
be using. You will be transforming ms files into dit files.
I am assuming you're using device independent troff here. The same
process applies equally well to nroff or old four font C/A/T troff.
Lines 6 and seven describe the actual rule. To get from a
.ms file to a .dit file, you run the formatter, with the
input file as the $< macro, and the output file as the
$@ macro. Notice the -rP$$page portion of the rule.
This is setting number register P to the contents of the
page environment variable. This assumes you have a
version of make that looks at environment variables.
Why the double $ sign? make uses the $ sign to
mark the onset of a macro reference. If you simply coded
it as $page as in your query, make would expand this
reference as whatever `p' is defined to be, followed by
the letters `age'. Chances are, this would expand to
troff -Tlw -ms -t age c1.ms > c1.dit
and troff would then complain about not being able to
open file `age'. The double $ sign expands to a single
$ sign, and then the Shell fills in the result of $page
when the Shell eventually gets to running the troff command.
How would you use this? You would do something like:
setenv page 5 (if you're using the C Shell)
make chapter1.dit
But, rather than messing with environment variables, you could
simply pass the page number into the make process as a make
macro. Modify the Makefile to read:
6 .ms.dit:
7 $(FORMATTER) -rP$(PAGE) $< > $@
and then you type
make chapter1.dit PAGE=5
Now, so far, I haven't said how you get the starting page
number into the actual troff process. At the start of each
of your chapters, you could write something like this:
1 .LP
2 .rs
3 .if \nP
4 .bp \nP
5 .NH 1
6 Chapter One Heading
7 .LP
8 text
Line 1 is the .LP (or .PP, .IP, .QP, or whatever) you need
to get the -ms macro package initialised.
Line 2 clears no space mode so the .bp will have effect.
Line 3 asks if the P number register has been set to something
other than zero from the troff command line. If it has, line
4 does a page eject withe that page number as the start page number.
There are other approaches, but they involve making changes to
the macro package.
Here is another approach. This one assumes you're using
device independent troff. Device independent troff places the
page number at the start of each `page' in its output file.
The page number just appears at the start of the line, like
p123
for page 123. Note that the page number is the actual
number printed at the bottom of the page, as a decimal
number.
This means that you can discover the number of the last
printed page by simply doing
grep ^p outputfile.dit
The last page number printed will be the last line of output
from grep.
For example, I have this file called c1.dit and I can run
grep to get the result like this:
grep ^p c1.dit
p1
p5
p6
Why is there a p1 in the file? That's because of the
extra blank page generated by the .bp in the example
earlier. The real start of the chapter is at page 5, and
the chapter is two pages long.
Now I can embellish this process a little by doing:
grep ^p c1.dit | sed -n -e '$s/p//p'
6
The sed command goes to the last line of its input,
subsitutes the letter `p' for nothing, and prints the
result. So, now you get the number 6.
How would you use this magic? Suppose you already had
built chapter1.dit, and you now want to start on chapter2.dit.
The starting page number for chapter2.dit can be obtained by:
make chapter2.dit PAGE=`grep ^p chapter1.dit | sed -n -e '$s/p//p'`
Finally, suppose all your chapter pages should start on odd
numbered pages. Pipe the output of sed into this silly
little awk program:
awk '{ if ($0 % 2 == 0) print $0 + 1; else print $0 + 2 }'
I package the grep, sed, and awk stuff into a little Shell
script called getlast or something like that, and use it instead
of the complex command line.
+------------------+------------------------+---------------------------+
| Henry McGilton | I saw the future, | arpa: hmcgilton@sun.com |
| Sun Microsystems | and it didn't work. | uucp: ...!sun!angel!henry |
| Mt. View, CA | | |
+------------------+------------------------+---------------------------+
Technical Details
Message-ID:
<124007@sun.Eng.Sun.COM>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!watmath!att!dptg!rutgers!apple!sun-barr!newstop!sun!angel!henryReferences:
<5689@ttidca.TTI.COM>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!watmath!att!dptg!rutgers!apple!sun-barr!newstop!sun!angel!henry From: henry%angel@Sun.COM (Henry McGilton -- Software Products) Newsgroups: comp.text Subject: Re: page numbering between chapters in nroff Message-ID: <124007@sun.Eng.Sun.COM> Date: 30 Aug 89 22:08:41 GMT References: <5689@ttidca.TTI.COM> Sender: news@sun.Eng.Sun.COM Lines: 208