[comp.text] Part 1 repost

lee@anduk.co.uk (Liam R. Quin) (05/16/89)

This is the first in the promised series.  There is also an introduction,
including both a PostScript and a text file (which I re-posted yesterday).
[Anduk's gateway fell over at the weekend sorry if this gets out twice]

============================================
Lightening Introduction to Troff Programming
Copyright (c) 1989 Liam R. Quin

I am including this article for those people who find the troff documentation
particularly difficult.  In order to understand the rest of the material,
you'll have to be prepared to dive into your documentation, so this is
simply to help you get started.  It is very terse.....

The examples all work, if you have the same version of troff that I do.

For what it's worth, I'm using ``SoftQuad Publishing Software'' Release 2.9.

I have marked with a side-bar where there are most likely to be
differences					|
						| old troff:
						| Like this.

These are mostly to do with long variable names and error handling.

If you have an older release of sqtroff, see NOTE 1 near the end of this
article.

If you are likely to give courses in the future, see NOTE 2 at the en.

Lee

==============================
0. Lightening Overview

Troff has number registers, strings macros and diversions.

0.0 Number registers hold arbitrary *integer* expressions.
You can set them with
	.nr register-name expression
where
	register-name is a string of letters, numbers or punctuation
	expression is a numeric expression.
Old versions of troff limit all names to 1 or 2 names.

You use them with
	\nX	1-character name
	\n(XX 	2-character name
	\n[xxx]	1, 2, or longer- character name

0.1 Strings hold a single word or phrase.
In other words, you can't put a newline into a string,
because it's the string terminator.

You set them with
	.ds string-name "anything you like here
You use them with
	\*[xxx]
(as for number registers. but with a * instead of an n).

0.2 macros hold multiple lines of unformatted (input) text.

You make a macro with
	.de macro-name
	text (which can include pretty much
	anything)
	..
where the dots have to be at the start of the line (but if I put them there,
old news and mail software will fall over!).

You use the macro with
	.macro-name
in exactly the same way that you would use a normal request (.ps for example).

0.3 diversions hold formatted (output) text.

You make them with
	.di diversion-name
	text
	.di
and use them with
	.diversion-name

Typically when you use a diversion, you need to do
	.in 0
	.nf
	.diversion-name

You will see why later.

Do not worry about the difference between macros and diversions at this
stage
[but I am not going to explain it in much detail on the net.  See
 TF:TR 5-14ff. if you have it, or look at your troff documentation.]

1.0 Interpolation

Troff reads its input (conceptually) a character at a time.

Strings and registers are ``interpolated'' as soon as they are seen
in the input.

						| Old versions of troff:
In other words, if you do			|
	.ds Name "Simon				| .ds Na "Simon
	Hello, \*[Name], how are you?		| Hello, \*(Na, how are you?
what troff actually sees is
	Hello, Simon, how are you?

Similarly, if you do				|
	.nr Age 12+(300/12)			| .nr A 12+(300/12)
	Simon is \n[Age] years old.		| Simon is \nA years old.
troff sees
	Simon is 37 years old.

This means that you can use strings and number registers anywhere you like.

It also means that you sometimes have to take special pains to avoid troff
from `interpolating' things.

For example, if you want to print a backslash (\), you can't simply
include it in your text, because troff will look for a following * or n!

There are other things that you can put after a \, however, and one of
them is `e'.  \e tells troff to print the current ``escape'' character;
this is normally the backslash.

The troff manual has a compete list of these things;  this introduction is
to give you the general flavour of how things work.

[omitted: activity break involving creating a file containing strings,
 registers and macros.  You can go have a play if you want!! try making
 a letter with the recipient's name in strings, perhaps, using a macro
 for the address.]

1.3 Common problems:
* if you forget the
	..
  or the
	.di
  at the end of a macro or diversion, all of the rest of the input will
  go into it, and of course won't be printed.  Troff will give you an
  error message:
    sqtroff:filename:223:Diversion (diversion-name) not closed
  or
    sqtroff:filename:255:de:Macro definition not closed
  including the filename and line number, sometimes or simply "(wrapup)" if
  the error isn't detected until the end of all the input.
						| old troff:
						| there is no error message.
						| The rest of your document
						| will simply vanish.

* If you get the name of a string or register wrong, nothing will happen.
  (sqtroff will give a warning if you have the warning level set
  appropriately).

2.0 [awfully terse summary]

Remove a register with .rr
	.rr regname [name2 ...]
remove a macro or string with
	.rm name [name....]

Strings and macros share the same name-space.  In other words, if you
do
	.ds Name "Marion			| .ds Na Marion
	.de Name				| .de Na
	Here is My Name				| Here is My Name
	..					| ..
the .de first removes the string before defining a macro with the same
name.  You do not get a warning.

Worse, if you do
	.de de
you can no longer use the built-in `.de'!  (But sqtroff will give a warning).

In order to define your own version of `de', you have to do
	.rn de old-de \" rename the built-in request
	.old-de de
	whatever you want
	..

Also, macro-aliasing does not notice that you	| Old troff doesn't have
have redefined the request:			| aliasing, so this does
	.alias nr set-register			| not affect you, except
	.de nr					| maybe to make you
	. tm nr obsolete			| jealous! :-)
	..					|
then
	.set-register
will continue to behave as .nr used to.

==============================

Good.

Summary:
	number registers
	expressions [see your manual, sorry]
	strings
	macros
	diversions

Actions:
	creating
	removing
	renaming
	aliasing

Other Key Words:
	name-space
	interpolation

==================
NOTE 1 on sqtroff:


Some older versions used : instead of ., but only for lines involving
long names.

I suggest that you create a file called `tmac.acc', and put it in your
macro directory (probably /usr/lib/tmac).  It contains:
	:acc .
	;ac2 '
	.ev 1
	:acc .
	;ac2 '
	.ev
	.ev 2
	:acc .
	;ac2 '
	.ev
with the leading spaces/tabs removed, and NO BLANK LINES.

Then do
	sqtroff -macc other-arguments-to-troff
If you're still on 2.6 or older, you may have to put an explicit
	.so /usr/lib/tmac/tmac.acc
(or wherever you put it) into each of your files.  If you can't put
things in /usr/lib/tr\mac, you'll have to do that anyway).

The examples will then work for you.

====================
NOTE 2 on copyright:

Please ask me before charging people to learn troff from you with any of this
stuff.  I will say almost certainly say yes, but I'd like to know if it's
being used!  In any case, you should acknowledge that you got the material
from me.

Lee

End Of Part A

Part B
@ will start at ``Tricks With Names''
@ will show how to build stacks, arrays and so on.
@ will have an example set of macros to do bullet-lists (like
  this one), which
  1.  nest (like this)
  2.  can use numbers (like this)
  3.  can use the special characters from part C, that are featured
      in the PostScript example.
@ will be posted in a day or two.
-- 
Lee Russell Quin, Unixsys UK Ltd, The Genesis Centre, Birchwood,
Warrington, ENGLAND, WA3 7BH; Tel. +44 925 828181, Fax +44 925 827834
	lee%anduk.uucp@ai.toronto.edu;  {utzoo,uunet}!utai!anduk!lee
UK:	uu.warwick.ac.uk!anduk.co.uk!lee

rcd@ico.ISC.COM (Dick Dunn) (05/17/89)

In article <18@nx32s.anduk.co.uk>, lee@anduk.co.uk (Liam R. Quin) posted
the beginning of an introduction supposedly for troff.  However, much of
it is specific to a formatter based on troff but significantly changed.
I assume he's talking about one by ``SoftQuad Publishing Software''
mentioned in the article as sqtroff.

It's particularly confusing to read:
> I have marked with a side-bar where there are most likely to be
> differences					|
> 						| old troff:
> 						| Like this.

because "old troff" is conventionally used to refer to pre-DWB troff,
i.e., the one which generated C/A/T output.  But in the article by Quin,
"old troff" comments also apply to "new troff" (i.e., ditroff).

I think it's an exceptionally bad idea to start right off teaching people a
notation which is peculiar to a vendor-specific extended version of troff
and not supported by the "reference" version.  Call it a "sqtroff"
tutorial!

While I was at it, I came across an item which made me wonder about the
naming extensions:
> You make a macro with
> 	.de macro-name
> 	text (which can include pretty much
> 	anything)
> 	..
This was in a context where it was clear that the macro name could be more
than two characters.  Then:

> You use the macro with
> 	.macro-name
> in exactly the same way that you would use a normal request (.ps for example).

BUT note that troff syntax does NOT require a space between request name
and first argument!  Consider:
	.de ps12
	<text of macro>
	..
	.ps12
To be compatible with troff, the last line would have to mean the same as
	.ps 12
i.e., set point size to 12.  It's not clear how you'd invoke the ps12
macro.

Consider also the methods for interpolating strings and number registers
using notations \*[name] and \n[name].  These clash with troff, since [ is
a valid name for a number register or string.  Try:
	.nr [ 37
	The text is \n[abcd].
This must produce "The text is 37abcd." in troff.

It may seem that [ would be a very poor choice of name for a register,
string, etc...but macro packages commonly use bizarre names laden with
special characters internally.

Moreover, it's not possible to decide what to interpolate based on the
existence of a definition of register (or string) [, because the value of
an undefined number register is 0.
-- 
Dick Dunn      UUCP: {ncar,nbires}!ico!rcd           (303)449-2870
   ...Relax...don't worry...have a homebrew.

lee@anduk.co.uk (Liam R. Quin) (05/19/89)

In article <15768@vail.ICO.ISC.COM> rcd@ico.ISC.COM (Dick Dunn) writes:

> In article <18@nx32s.anduk.co.uk>, lee@anduk.co.uk (Liam R. Quin) posted
> the beginning of an introduction supposedly for troff.
> However, much of
> it is specific to a formatter based on troff but significantly changed.
> I assume he's talking about one by ``SoftQuad Publishing Software''
This is only superficially correct.
The notes apply to all the versions of troff I've seen.
Some of the examples use long names because it makes them easier to read,
but I have included ``standard'' versions too.  There are a few programming
techniques that you can't actually do unless you have long names; I
intended at least to mention these, although not to rely on them of course.

I'll wait to see if anyone found the stuff useful before posting any more,
of course.

> But in the article by Quin,
[[ <flame-on>: It's Mr. Quin, or `Lee' -- simply using a surname is generally
   considered rude in England.</flame-off> ]]

> "old troff" comments also apply to "new troff" (i.e., ditroff).
I don't think that 1978 is very new.  I'm sorry if you were confused by
this.  Let me know if your troff doesn't run the `stack' example, though,
which was intended to be fairly portable!


I chose to use longer names in some of the examples for several reasons.
* It is *much* easier to start off with a higher-level representation.

  In other words, the macros are easier to understand if you use long names.
  If your troff doesn't support them (and there are lots that do, including
  SoftQuad's, Proficient's, and the UCB (non-proprietary) version), it is
  actually not that hard to add, and worth-while if you do a lot of work
  with ditroff.

Note:
  In some of the DWB derivatives that support long names the syntax is
  \C'name' instead of [name], but the changes are fairly straight-forward.

* I have several versions of troff here, and the examples with ditroff and
  nroff as well as Osanna's `otroff' itself [ancient troff? :-) :-)].
  But I use versions with long names by preference.

In the 2nd part (that I posted a couple of days ago), there is the first
`useful' example -- numbered lists that you can nest fairly deeply --
presented first with long names (for clarity, hopefully!) and then in
troff format, with the short (``bird-dropping'') style names.

But the examples are for teaching, so I value clarity very highly.  You
will probably have to change them to get them to do exactly what you
need, so I might as well write them in the way that I have.

> I think it's an exceptionally bad idea to start right off teaching people a
> notation which is peculiar to a vendor-specific extended version of troff
> and not supported by the "reference" version.
It is not clear to me what you mean by `reference'.

If you use the word in the sense that the `reference' Unix is that which
runs on Mr. Ritchie's machine, then the `reference' troff is probably
the Research ditroff.  This isn't available to most people, however.
[0.5 :-)]

Seriously, though, the examples work with other troffs.  It's sort
of like writing F*RTRAN or BaSick [:-(] -- start off coding in a higher-
level psuedo-code and then translate.
And people who have a version of troff with long names get to benefit, too.

> To be compatible with troff, [.ps12] would have to mean the same as
> 	.ps 12
> i.e., set point size to 12.  It's not clear how you'd invoke the ps12
> macro.
As soon as you define a macro called ps12, you no longer have to be
compatible in this respect.
If the macro is not defined, at least one such version of troff that I use
takes it to mean .ps 12, optionally printing a warning.

> Moreover, it's not possible to decide what to interpolate based on the
> existence of a definition of register (or string) [, because the value of
> an undefined number register is 0.
Troff knows whether or not a macro/string/register has been defined.
It simply doesn't tell the user (although some versions produce a
warning, and it's fairly easy to change ditroff to do this).
So troff can, in fact, do this.  It could probably even work out whether
to do [ or xxx in \*[xxx] depending on whether xxx was a defined name,
although there seems to be no need for this.

I found a few bugs in macro packages like -mm to do
with forgetting to initialise registers, or using the wrong name by
mistake, simply by adding an optional warning to ditroff!
There are some subtler bugs I found that way to do with the mis-use of tabs,
too, and there is a strong case for adding better error messages to
troff.  I once posted some patches that do this.


Lee

-- 
Lee Russell Quin, Unixsys UK Ltd, The Genesis Centre, Birchwood,
Warrington, ENGLAND, WA3 7BH; Tel. +44 925 828181, Fax +44 925 827834
	lee%anduk.uucp@ai.toronto.edu;  {utzoo,uunet}!utai!anduk!lee
UK:	uu.warwick.ac.uk!anduk.co.uk!lee

rcd@ico.ISC.COM (Dick Dunn) (05/25/89)

In article <20@nx32s.anduk.co.uk>, lee@anduk.co.uk (Liam R. Quin) writes:
> In article <15768@vail.ICO.ISC.COM> I wrote:
> > In article <18@nx32s.anduk.co.uk>, lee@anduk.co.uk (Liam R. Quin) posted
> > the beginning of an introduction supposedly for troff.
> > However, much of
> > it is specific to a formatter based on troff but significantly changed.
> This is only superficially correct.
> The notes apply to all the versions of troff I've seen.

It is much more than "superficially correct"!  It doesn't matter if it ap-
plies to all versions of troff you've seen--that's a personal view.  I can
as easily say that much of it applies to *no* version of troff I've seen.

The point is that, as far as I can tell, the extensions do not exist in
*any* version of troff that AT&T has ever sold or licensed.  That's a lot
of instances of troff over the years even if it isn't all of them.

> > But in the article by Quin,
> [[ <flame-on>: It's Mr. Quin, or `Lee' -- simply using a surname is generally
>    considered rude in England.</flame-off> ]]
This flame is more rude than the supposed offence!  Clearly no offense was
intended.  In the US, whence I posted:
	- It is considered rude to address a person by given name without
	  some introduction (excepting certain salespeople and recruiters,
	  who don't understand "rude"...but that doesn't apply here.)
	- Neither "Liam" nor "Lee" is obviously a male's name.  I may not
	  have searched far enough by this point in the followup, but not
	  knowing sex, I could at best use "M- Liam", which is an affecta-
	  tion and would still leave open the possibility that, in choosing
	  a more formal address, I should have said "Dr Liam".
	- The surname alone is considered proper in this context.

> > "old troff" comments also apply to "new troff" (i.e., ditroff).
> I don't think that 1978 is very new...

The first ditroff appeared more on the order of early '80's.  After that,
pic was added, then grap was added.  These require changes in troff.  Grap
corresponds to DWB 2.0, which is probably no older than 1986 or 1987.  The
recent changes also give a much-improved nroff.

> I chose to use longer names in some of the examples for several reasons.
> * It is *much* easier to start off with a higher-level representation.

I agree, but it doesn't work!  I have often wished for longer names, and
for some safer way to partition the name space.  But one of the uses of
troff input format is as an exchange format.  If one takes great liberties
with the notation, that use is lost.  (My own teaching experience suggests
that one is better to stay on the straight and narrow; students have enough
to remember just what's correct and what isn't, let alone some sense of
conditional validity and substitution.)

>   In other words, the macros are easier to understand if you use long names.
>   If your troff doesn't support them (and there are lots that do, including
>   SoftQuad's, Proficient's, and the UCB (non-proprietary) version), it is
>   actually not that hard to add, and worth-while if you do a lot of work
>   with ditroff.

It is not possible to add long names to troff without either modifying
troff itself or adding a separate translating component.  That is, either:
	- Obtain a source license for DWB and do some programming.  (This
	  raises the possibility of getting it "wrong"--i.e., inconsistent
	  with other forms of the extension.  It's too expensive anyway.)
	- Adding a pre-processor to translate long names down to two-char-
	  acter names.  This looks simple at first, but it involves pre-
	  processing macro files and .so files as well...which in turn
	  requires understanding almost all of the input language.
I can't see either of these as practical.

Again, it may or may not be worthwhile--for me it would not be, because the
documents I prepare using troff may have to be formatted on at least five
different types of machines even before I send them to anyone else.

I am interested in the "UCB (non-proprietary) version"--the last I'd heard,
Berkeley had not managed to "free" nroff/troff from AT&T code and they
didn't have anyone working on it.  Details?

> But the examples are for teaching, so I value clarity very highly.  You
> will probably have to change them to get them to do exactly what you
> need, so I might as well write them in the way that I have.

Again it's a matter of teaching preference, but I've found that examples
which don't work letter-for-letter can be very disturbing.  I contend that
it is possible to write troff examples which *need not* be changed at least
to work for the original purpose.

> > I think it's an exceptionally bad idea to start right off teaching people a
> > notation which is peculiar to a vendor-specific extended version of troff
> > and not supported by the "reference" version.
> It is not clear to me what you mean by `reference'.

I mean the version which is sold/licensed/distributed by AT&T, which
presumably forms the base for at least some of the other extended
versions.  This "version" is actually a series of versions over the years,
but none of them have the long-name extensions.

> > To be compatible with troff, [.ps12] would have to mean the same as
> > 	.ps 12
> > i.e., set point size to 12.  It's not clear how you'd invoke the ps12
> > macro.
> As soon as you define a macro called ps12, you no longer have to be
> compatible in this respect.

Who are "you"?  Troff input almost always involves two parties--the
document author and the macro author.  They can (and frequently do) get
into conflicts.  Suppose that it's the document author who defines ps12 and
uses it with macros which have been scrunched.  (Note in passing:  The
business of pulling out the separator between command and arguments is a
Bad Idea...but it's still common.)

> Troff knows whether or not a macro/string/register has been defined.
> It simply doesn't tell the user (although some versions produce a
> warning, and it's fairly easy to change ditroff to do this).

One can make a good case either way for number registers.  However, macros
and strings share the same name space with one another--and with the
built-in commands.  It is an important, documented, time-honored property
of troff that "...control lines with unrecognized names are ignored."

> So troff can, in fact, do this.  It could probably even work out whether
> to do [ or xxx in \*[xxx] depending on whether xxx was a defined name,
> although there seems to be no need for this.

No, not if the string [ is defined.  If there has been a
	.ds [ stuff
then \*[xxx] *must* produce stuffxxx]

> I found a few bugs in macro packages like -mm to do
> with forgetting to initialise registers,...

I certainly won't question that you've found bugs in mm!  But I wonder
which were bugs and which just relied on uninitialized registers implicitly
having value 0?

> ...and there is a strong case for adding better error messages to
> troff...

Quite true.  But one ought to be careful to distinguish "errors" from
"warnings", in order not to bury useful error messages where they won't be
noticed.  For example, using an undefined command is probably a warning
that one ought to be able to switch on during debugging, but (per above)
it's not an error so you don't want to see it normally.
-- 
Dick Dunn      UUCP: {ncar,nbires}!ico!rcd           (303)449-2870
   ...CAUTION:  I get mean when my blood-capsaicin level gets low.

rcd@ico.ISC.COM (Dick Dunn) (05/25/89)

In article <15795@vail.ICO.ISC.COM>, I screwed up:
In discussing what Mr Quin took as rudeness, I pointed out that it was not
immediately clear that I should use Mr, but then said:

> 	  ...I could at best use "M- Liam", which is an affecta-
> 	  tion and would still leave open the possibility that, in choosing
> 	  a more formal address, I should have said "Dr Liam".

Please, s/Liam/Quin/, and this should make it obvious that I don't have any
cultural reference to associate sex with the name "Liam" since I don't even
have an association to identify it as curname or given name!  (This happens
with "English" names as well, of course--"James" or "Scott" commonly occur
in either use.)
-- 
Dick Dunn      UUCP: {ncar,nbires}!ico!rcd           (303)449-2870
   ...CAUTION:  I get mean when my blood-capsaicin level gets low.

murray@sq.com (Murray Maloney) (05/30/89)

In articles <15768@vail.ICO.ISC.COM> and <15795@vail.ICO.ISC.COM>,
rcd@ico.ISC.COM (Dick Dunn) comments on articles <18@nx32s.anduk.co.uk>
and <20@nx32s.anduk.co.uk>, posted by lee@anduk.co.uk (Liam R. Quin).

I would like to comment on several of the points that have been raised.

********************************************************************************
In article <15795@vail.ICO.ISC.COM>, Dick Dunn writes
> In article <20@nx32s.anduk.co.uk>, lee@anduk.co.uk (Liam R. Quin) writes:
> > In article <15768@vail.ICO.ISC.COM> I (Dick Dunn) wrote:
> > > In article <18@nx32s.anduk.co.uk>, lee@anduk.co.uk (Liam R. Quin) posted
> > > the beginning of an introduction supposedly for troff.
> > > However, much of
> > > it is specific to a formatter based on troff but significantly changed.
> > This is only superficially correct.
> > The notes apply to all the versions of troff I've seen.
> 
> It is much more than "superficially correct"!  It doesn't matter if it ap-
> plies to all versions of troff you've seen--that's a personal view.  I can
> as easily say that much of it applies to *no* version of troff I've seen.

In fact, Mr Quin's notes apply to many versions of troff, including 
common troff, ditroff, and nroff as well as UCB's Gremlin ditroff,
Eroff, Xroff, profficient troff, PWB, DWB, DWB 2.0, and sqtroff.

> The point is that, as far as I can tell, the extensions do not exist in
> *any* version of troff that AT&T has ever sold or licensed.  That's a lot
> of instances of troff over the years even if it isn't all of them.

Almost two years ago, SoftQuad and AT&T entered into a co-marketing 
arrangement which was announced in the press at the time.  Under the
terms of this agreement, negotiated over many months and following 
evaluations by AT&T of various products, 

	SoftQuad Publishing Software is available in source 
	and binary form through AT&T and SoftQuad as an enhanced 
	product derived from AT&T's UNIX(R) system Documenter's 
	Workbench(TM) Release 2.0 Software.

In its current release, SQPS has also been incorporated by AT&T's
IMS group into its "Standard Operating Environment" (SOE) for 
internal use, and is being widely sold by AT&T to its customers.

Similar extensions exist in both the UCB and profficient versions.
The version in use at AT&T Bell Labs also includes extensions that 
never made it into the mainstream product (or SQPS for that matter) but 
are documented in Nahrain Gehani's book "Document Formatting and 
Typesetting on the UNIX System".

********************************************************************************
> > > "old troff" comments also apply to "new troff" (i.e., ditroff).
> > I don't think that 1978 is very new...
> 
> The first ditroff appeared more on the order of early '80's.  After that,
> pic was added, then grap was added.  These require changes in troff.  Grap
> corresponds to DWB 2.0, which is probably no older than 1986 or 1987.  The
> recent changes also give a much-improved nroff.

Troff was developed around 1973 by the late Joseph F. Ossanna.  This 
program was based upon an earlier text formatter written by Doug McIlroy.
which in turn was patterned after J. Saltzer's original RUNOFF for the 
Cambridge Time Sharing System in the late 1960's.  Brian Kernighan's 
ditroff appeared in 1979 and DWB 2.0 followed in 1986.

The AT&T/SoftQuad distributed version of troff is the latest step in 
the evolution of RUNOFF-based formatters.  As such, it has supplanted 
ditroff as the so-called `new troff'.

********************************************************************************
> > I chose to use longer names in some of the examples for several reasons.
> > * It is *much* easier to start off with a higher-level representation.
> 
> I agree, but it doesn't work!  I have often wished for longer names, and
> for some safer way to partition the name space.  But one of the uses of
> troff input format is as an exchange format.  If one takes great liberties
> with the notation, that use is lost.  (My own teaching experience suggests
> that one is better to stay on the straight and narrow; students have enough
> to remember just what's correct and what isn't, let alone some sense of
> conditional validity and substitution.)

While troff's use as an interchange format has always been a goal, it has 
never really been a reality.  Not only have successive versions of troff 
included significant changes in the command set, but nroff, troff, and
ditroff have never been 100% compatible.  With so many ROFF-based formatters 
available, each with its personality (in the form of undocumented behavior), 
one would have to be especially careful to remember what's correct with a 
given version, on a given machine, attached to a given printer.

There are, however, quite a number of requests and escape sequences that 
have remained consistent since the V7 version was documented.  By 
restricting yourself to that set, you can be fairly confident of producing
a document that you can distribute freely.  This restriction applies
no matter which version you use.  

There are two provisos in the case of SoftQuad's and UCB's versions 
-- where long name syntax has been added -- 
	(1) You should disable long-name requests.
	(2) You should read a string named `[' with \*[[].
This seems a reasonable price to pay, both in terms of re-education
and added effort in formatting a document.  A simple sed script could
be used to perform the conversion required in (2).

********************************************************************************
> Who are "you"?  Troff input almost always involves two parties--the
> document author and the macro author.  They can (and frequently do) get
> into conflicts.  Suppose that it's the document author who defines ps12 and
> uses it with macros which have been scrunched.  (Note in passing:  The
> business of pulling out the separator between command and arguments is a
> Bad Idea...but it's still common.)

Not only do we agree that the separator should not be removed, we recommend
against it to prevent the possibility of conflicts like the one you describe.
Therefore, scrunching sqtroff macros does not include removing spaces between 
commands and their arguments; our documentation is quite clear on that.  
We also recommend that users and macro writers test for potential conflicts
by using two conditions that were introduced by SoftQuad.  For example,

	.if d name .tm Macro/request/string name already defined
	.if r name .tm Register name already defined

The potential for conflict has always existed.  The author has 
always had the option of defining a macro `p' which could, arguably, 
also cause misinterpretation. For example, 
	.de p
	.tm Argument 1 is: \\$1
	.tm Argument 2 is: \\$2
	..
	.p s 12

should result in the terminal messages:
	Argument 1 is: s
	Argument 2 is: 12

Given the same macro definition,
	.ps12

will not invoke the macro `p' with the argument `s12' on any version of troff.
No documentation ever has touched on this.  So, while you can argue that 
troff has always had semantic inconsistencies, you should also be aware 
that expected behavior is not always documented or otherwise defined.

The interpretation of 
	.ps12 

by sqtroff depends on whether there is a macro called `ps12' or not.
If there is a macro named `ps12', it is invoked as any other macro.
Else if there is a macro/request named `ps', it is invoked with argument "12"
and a warning message (optional) is issued to advise you.

(warning) No macro/request ".ps12", interpreted as ".ps" and argument(s)

********************************************************************************
> > Troff knows whether or not a macro/string/register has been defined.
> > It simply doesn't tell the user (although some versions produce a
> > warning, and it's fairly easy to change ditroff to do this).
> 
> One can make a good case either way for number registers.  However, macros
> and strings share the same name space with one another--and with the
> built-in commands.  It is an important, documented, time-honored property
> of troff that "...control lines with unrecognized names are ignored."

A property that is preserved in sqtroff and augmented by a warning message
to advise the unfortunate troff programmer who might not be able to find 
the source of a problem otherwise.

********************************************************************************
> > So troff can, in fact, do this.  It could probably even work out whether
> > to do [ or xxx in \*[xxx] depending on whether xxx was a defined name,
> > although there seems to be no need for this.
> 
> No, not if the string [ is defined.  If there has been a
> 	.ds [ stuff
> then \*[xxx] *must* produce stuffxxx]

You've got a valid point here.  In order to provide an extended syntax,
SoftQuad had to pick a pair of delimiters so that sqtroff would know 
when long names were being used.  Deciding that it would be prudent to 
provide compatibility with at least one other enhanced ditroff -- used 
at the UCB computer center -- `[' and `]' were selected.  We realized 
that this change could cause problems for user-developed macro packages,
but the majority of those polled felt that the advantages gained
were worth the effort required to comply with the new syntax.

Quoting from the UCB addendum to the Nroff/Troff User's Manual:

	Because of the longer, variable-length names, spaces  are
	now required to separate commands and arguments (e.g., .nr XX 4,
	.nrXX 4, and .nr XX4, etc. are no longer equivalent.

	Strings, number registers and fonts of any length name may be 
	called with \*[x...x], \n[x...x] and \f[x...x], respectively.
	Special characters may also be called with \[x..x].  The format
	of a number register may be accessed with \g[x...x], and the 
	current input-line horizontal position may be stored in 
	register x...x with \k[x...x].  Size changes of any number of
	digits may be called with \s[x...x].

********************************************************************************
> I am interested in the "UCB (non-proprietary) version"--the last I'd heard,
> Berkeley had not managed to "free" nroff/troff from AT&T code and they
> didn't have anyone working on it.  Details?

It's highly unlikely that anyone would be able to write a fully compatible
troff without significant study of the AT&T source code because of the 
complexity of the original code (such a program's legal status would 
probably be unclear at best).  People have written vastly-simplified
nroff-only subsets: see various source archives for copies.

The most recent information I have on UCB's gremlin ditroff is 
article <252@ucbopal.CC.Berkeley.ARPA> in newsgroup `net.text' 
and dated July 1985.  I have no way of knowing if the poster 
is still there or otherwise connected to the network.

If you feel lucky, you can try contacting

	Edward Moy
	Academic Computing Services
	University of California
	Berkeley, CA 94720
	edmoy@ucbopal.ARPA
	ucbvax!ucbopal!edmoy

********************************************************************************
> > ...and there is a strong case for adding better error messages to
> > troff...
> 
> Quite true.  But one ought to be careful to distinguish "errors" from
> "warnings", in order not to bury useful error messages where they won't be
> noticed.  For example, using an undefined command is probably a warning
> that one ought to be able to switch on during debugging, but (per above)
> it's not an error so you don't want to see it normally.

This is something that sqtroff is careful to do.  There are four levels 
of error/warning messages in sqtroff.  The 0th level is for outright 
errors that will cause processing to terminate.  The other levels
are obtained by using the (new) `-wN' option on the command line
or by using the (new) `.warn N' request inside the file.  Each level
provides more extensive error checking, akin to `lint'.

********************************************************************************
Murray C. Maloney		uucp:		{utai|utzoo|uunet}!sq!murray
Documentation Specialist	Internet:	murray@sq.com
SoftQuad Inc.			Phone:		(416) 963-8337

rcd@ico.ISC.COM (Dick Dunn) (05/30/89)

In article <1989May29.165203.17889@sq.com>, murray@sq.com (Murray Maloney) writes:
> I would like to comment on several of the points that have been raised.
. . .
> In fact, Mr Quin's notes apply to many versions of troff, including 
> common troff, ditroff, and nroff as well as UCB's Gremlin ditroff,
> Eroff, Xroff, profficient troff, PWB, DWB, DWB 2.0, and sqtroff.

I was referring to the long-name extensions, which are *not* in ditroff,
nroff, DWB, or DWB 2.0 as AT&T ships them.  I've tried them on programs
built directly from unmodified AT&T source.  I've also checked the source
code.  They just aren't there.

(What does PWB have to do with it?  I think I'm missing context here; I know
PWB as an old UNIX system, one of the two threads of development off V6
UNIX [the other being V7].)
-- 
Dick Dunn      UUCP: {ncar,nbires}!ico!rcd           (303)449-2870
   ...CAUTION:  I get mean when my blood-capsaicin level gets low.

scott@dtscp1.UUCP (Scott Barman) (05/31/89)

In article <1989May29.165203.17889@sq.com> murray@sq.com (Murray Maloney) writes:
>While troff's use as an interchange format has always been a goal, it has 
>never really been a reality.  Not only have successive versions of troff 
>included significant changes in the command set, but nroff, troff, and
>ditroff have never been 100% compatible.  With so many ROFF-based formatters 
>available, each with its personality (in the form of undocumented behavior), 
>one would have to be especially careful to remember what's correct with a 
>given version, on a given machine, attached to a given printer.

I really think you need to be more precise on this statement.  No version
of the *roff programs have been 100% compatible, but I beleive that, at
least up until DWB 2.0, there has been an attempt to make sure the
programs were upward compatible.  To quote Brian Kernighan [Computing
Science Technical Report No. 97, "A Typesetter-independent TROFF"]:

	"... a great deal of software depends on TROFF--the
	preprocesors, the macro packages, and of course all of their
	documentation and our accumulated expretise.  Tossing this
	aside is not something to be done lightly

		Accordingly, ... I set about to modify TROFF so
	that it would run henceforth without change on a variety
	of typesetters.  The ground rule was that TROFF should
	retain its current specifications so that existing software...
	would continue to work with it."

I would say, with experience, that this mission was accomplished when we
(we meaning in a previous job) upgraded our environment from C/A/T-4s to
an APS-u5 with typesetting done with ditroff from PWB 1.0 with the only
modifications being to our own internally hacked eqn.  It would be very
disturbing if any new product--especially sold by AT&T--is not upward
compatible.

>There are, however, quite a number of requests and escape sequences that 
>have remained consistent since the V7 version was documented.  By 
>restricting yourself to that set, you can be fairly confident of producing
>a document that you can distribute freely.  This restriction applies
>no matter which version you use.  
That is just escape sequences--which I am assuming you mean characters.
What about some of the old C/A/Tisms that has survived even DWB?  We all
know that typesetters can do multiple pointsizes, but what about the
ol' \s command?  For example, if I do a \s32X I would get a point size
32 `X' since the C/A/T could not do a point size 3 and "assumed" the 32
to be legal.  Now (assuuming a typesetter can do a point size 3), has
SQ changed this command of print a `2X' in point size 3?  I really hope
not!

Just as a suggestion, one of the things I hacked into ditroff (many
years ago) was to accept "legal" \s but added the ability to do a \s(xx
where the xx can be any point size.  I did it to test some proposed
changes to our internally hacked eqn (something that would not be
released to the public).  The eqn changes were not made, but the change
to the \s stayed and I never heard of any problems because of it.  It's
just a thought...

-- 
scott barman
{gatech, emory}!dtscp1!scott

morrell@hpsal2.HP.COM (Michael Morrell) (06/01/89)

/ hpsal2:comp.text / scott@dtscp1.UUCP (Scott Barman) / 12:24 pm  May 30, 1989 /

Just as a suggestion, one of the things I hacked into ditroff (many
years ago) was to accept "legal" \s but added the ability to do a \s(xx
where the xx can be any point size.
----------

This feature is present in ELAN's Eroff.  I don't know why the original troff
decided to make \s the exception in not requiring the "(" when giving a 2
digit argument.

scott@dtscp1.UUCP (Scott Barman) (06/02/89)

In article <2610025@hpsal2> morrell@hpsal2.HP.COM (Michael Morrell) writes:
>/ hpsal2:comp.text / scott@dtscp1.UUCP (Scott Barman) / 12:24 pm  May 30, 1989 /
>Just as a suggestion, one of the things I hacked into ditroff (many
>years ago) was to accept "legal" \s but added the ability to do a \s(xx
>where the xx can be any point size.
>----------
>This feature is present in ELAN's Eroff.  I don't know why the original troff
>decided to make \s the exception in not requiring the "(" when giving a 2
>digit argument.

You have to look at the characteristics of the C/A/T to understand:
That wonderful device ( :-) ) can only do fonts of size 6-12, 14, 16, 18, 20,
24, 28, and 36.  Therefore, it was safe (at the time) to assume that if
it encountered a 1, 2, or 3 after the \s, then it had to be a two digit
font because the C/A/T does not have a point size 1, 2, or 3.  Yes, it
is not the way things are now, but troff was written to be device dependent
at that time.

A better question is why is \f(xx allowed (C/A/T troff) when the C/A/T had
only four font positions and the fonts R, I, B, and S?
Just something to ponder....

-- 
scott barman
{gatech, emory}!dtscp1!scott