Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - info/docond.info
There are no other files named docond.info in the archive.
-*-Text-*-

DOCOND		Node: Top	Up: (EMACS)	Next: Flags

DOCOND is a program for putting "assembly conditionals" in
in text files.  At the beginning of the DOCOND input file go
declarations of the names of various "flags" or assembly switches,
Throughout the rest of the file may appear conditionals which test the
state of a flag.  Processing the input file with DOCOND causes the
contents of failing conditionals to be deleted.  The contents of
successful conditionals remain, but the conditional syntax itself is
deleted, leaving text which is free of DOCOND commands.  In addition
to conditionals within the text, conditional replacements may be
specified as declarations, and macros written in TECO can be called
from points in the text.

* Menu:

* Flags::	How to declare flags.
* Relate::	Expressing relationships between flags.
* Condit::	How to put conditionals in the text.
* Macros::	Macro calls in the text.
* Replace::	Conditional global replacements.
* Run::		Running DOCOND.

DOCOND		Node: Flags, Previous: Top, Up: Top, Next: Relate

Declaring DOCOND Flags.

  DOCOND processing is controlled by binary flags, whose names are
chosen by the user.  Each flag has a "setting", which iseither "+" or
"-" (or, in the source file, "?", meaning that the setting is unknown
as yet).  A DOCOND conditional always tests the setting of some flag.
The first stage of DOCOND processing asks the user what setting to use
for each flag;  when all the settings are known, DOCOND processes the
conditionals in the text according to those settings.

  Each DOCOND input file must begin with a DOCOND declarations section
which is terminated with the string "{end}" followed by a CRLF.  Each
flag used in the file must be declared in this section.  Implications
and conditional replacements are also declared there.  Since each
DOCOND construct is enclosed in braces, nothing stops you from having
other sorts of text (such as -*-Text-*-) in the DOCOND declarations
section, but whatever it is will all be deleted when DOCOND is
finished running.

  A flag declaration looks like {Flag:?<flagname>}.  Notice the "?"!
The "?" is a placeholder which you must specify;  it will be replaced
by the setting of the flag, either "+" or "-", when that is known.
Here are some examples:

	{Flag:?FOO} {Flag:?DoubleFoo}

You can actually provide a setting for the flag in the source file, 
by writing "+" or "-" instead of the "?".  This is actually useful,
since you can declare a flag named "Comment" which is always off,

	{Flag:-Comment}

and then use conditionals on this flag as comments:

	{+Comment:  anything at all}

  If you have no declarations but Flag declarations, DOCOND will ask
you for the settings of all the flags, in the order they are declared.

  The Print declaration allows you to print out an arbitrary string at
declaration processing time (presumably, to give the user directions
on how to decide what flag settings to specify).  Here is an example:

	{Print:FOO should be "+" if your version can process Lisp code.
	}
	{Flag:?FOO}

DOCOND		Node: Relate, Previous: Flags, Up: Top, Next: Condit

Expressing Relationships between Flags.

  Although DOCOND conditionals can be nested, it is often convenient
to have redundant flags which express combinations of other flags.
Or, you might have several mutually exclusive alternatives, with a
flag for each alternative.  In that case, it would be a nuisance to be
asked for the setting of each flag separately, when all but one must
be "-".  For these situations, DOCOND provides the "relationship
declarations" Implies, Alternatives, and Default.  Implies allows you
to set one flag conditional on the setting of another.  Alternatives
tells DOCOND that exactly one of a list of flags must be "+" and the
others "-".  DOCOND then knows just to ask for the name of the one
which is "+".  Default allows you to provide a flag with a default
setting which is used unless overridden by an Implies or Alternative
(or by a manual setting made before doing MM DOCOND).

  A DOCOND implication says that if one flag is set on (or off),
another flag should be set automatically.  In general, an implication
specifies a flag and setting as the condition, and a flag to be set in
response.  The setting always precedes the flagname (it is always
thus, in DOCOND), and no extra spaces are allowed anywhere in the
construct.  Here is the general pattern:

	{Implies:+FOO=>-BAR}

  A default declaration says that rather than ask the user for the
value of a certain flag, a specific default setting should be assumed.

	{Default:-FOO}

says that FOO is off by default.  This is not the same as giving FOO a
constant value of "-" -- that is, declaring FOO with

	{Flag:-FOO}

because implications of flags set earlier can override the default.
The user can also override it using the DOCOND Set Flag command.

  For example, you can use Implies and Default together to declare
that the FOO-or-BAR flag should be "+" if either FOO or BAR is "+":

	FOO-or-BAR is + if FOO or BAR is:
	 {Implies:+FOO=>+FOO-or-BAR}
	 {Implies:+BAR=>+FOO-or-BAR}
	 {Default:-FOO-or-BAR}
	 {Flag:?FOO-or-BAR}

Note that text not within brackets in the declaration section is in
effect a comment, since it will be deleted without affecting DOCOND.

  That the Implies declarations which can set FOO-or-BAR precede the
Flag declaration for FOO-or-BAR is essential, because both types are
processed in one pass through the declarations section, and if the
Flag declaration were seen first, since the flag would still be unset,
DOCOND would ask the user for the setting.  For the same reason, the
above example must come after the declarations of FOO and BAR.  The
location of the Default declaration doesn't actually matter, because
it is processed, not by its position, but at the time when the Flag
declaration is processed.  However, it is good practise to put it in
the position which would be correct if it were processed in sequence.

  The remaining type of relationship declaration is the Alternatives
declaration, which says that, of a list of flags, exactly one should
be "+" and the rest "-".  When the Alternatives declaration is
processed (in sequential order, like Implies and Flag), if none of the
flags in the list is set to "+", the user is asked to specify one of
them.  The specified one is set to "+", and the rest to "-".  If one
is already set to "+", Alternatives just sets the rest to "-" without
having to ask.  Thus, an alternative can be selected by an earlier
Implies, or by the MM DOCOND Set Flag command (*Note Run: Run.).
Here is an example of the Alternatives declaration:

	{Alternatives:ITS,Twenex,Lispm}
	{Flag:?ITS} {Flag:?Twenex} {Flag:?Lispm}

Note that the Alternatives declaration does not eliminate the need to
declare the individual flags in Flag declarations, but the latter must
come after the Alternatives, or else DOCOND would ask about each flag
individually when it came to the Flag declarations.

DOCOND		Node: Condit, Previous: Relate, Up: Top, Next: Macros

In-text Conditionals.

  The fundamental feature of DOCOND is the conditional which causes a
string of text to appear or not appear in the output according to the
setting of some flag.  Each conditional tests only one flag, but
conditionals can be nested to test more than one;  in addition, the
Implies and Default constructs can be used to make a new flag
correspond to any Boolean combination of other flag settings.
*Note Boole: Relate.

  A conditional must contain the name of the flag, the setting to test
for, and the conditionalized text.  Here is an example:

	{+FOO: text to appear only if FOO is "on" (or "+")}

A conditional appears vaguely like the other DOCOND constructs, but
note these differences:

	1) in a conditional, the "{" is followed by a "+" or a "-".
	2) conditionals appear PAST the {end} of the declarations
	   section, whereas the other constructs appear only WITHIN
	   the declarations section.

Note that all text not within a conditional will always appear in the
output, so that

	I want to
	{+FOO:win}
	{-FOO:lose}
	.

will result, if FOO is +, in

	I want to
	win

	.

or, if FOO is -, in

	I want to

	lose
	.

If you want no spurious CRLFs in the output, put none in the input:

	I want to {+FOO:win}{-FOO:lose}.

Note also that there is no difficulty in having braces in
unconditional text, since "{" is recognized as a conditional only when
followed by a "+" or "-", but braces appearing inside a conditional
must be balanced (because nested conditionals work).

Note that conditional global replacements can affect the conditionals,
both the text they contain and the flag names!

DOCOND		Node: Macros, Previous: Condit, Up: Top, Next: Replace

In-text Macro Calls.

  In addition to conditionals, DOCOND provides a feature for including
macro calls in the text.  Unlike most macro processors, DOCOND does
not need to define a macro-writing language, because the macros are
just named EMACS commands written in TECO.

	{*macroname:stringarg}

specifies a call to the command named <macroname> with the string
argument <stringarg> provided to it.  The macro call is deleted from
the buffer when it is processed, and replaced by the string (if any)
returned by the called macro (in which case, the newly inserted string
is rescanned for conditionals and macro calls).  For example, suppose
we have a macro named MM Type Out which takes a string argument and
types it out;  then

	{*Type Out:FOO}

would print "FOO" when executed.

  Macro calls can successfully be included in conditionals;  they will
be expanded only if the conditionals succeed.  Conditionals can also
be included in a macro call, but the macro call is processed first, so
that the string argument passed to the macro will unconditionally
contain the conditionals.  Only if the macro returns those
conditionals to be reinserted and rescanned will those conditionals
actually be processed as such.

  One macro provided by DOCOND for just this purpose is called Refill.
Call Refill on the line after the end of a paragraph

	... last line of paragraph.
	{+FOO:{*Refill:}}

to refill that paragraph, if conditionals or replacements have caused
it not to be properly filled.

  To provide a macro FOO for use in DOCOND macro calls, you must
define it yourself.  Any method of defining a named EMACS command will
do, including putting a specification of the variable MM FOO in the
source file's local modes, but there is also a special facility called
the Local Variable declaration in DOCOND itself which can be used:

	{Local Variable:MM FOO=lots of TECO commands}

which can be used to define the variable MM FOO only during actual
DOCOND processing.  Putting "MM FOO:lots of TECO commands" in the
local modes of the source file would define MM FOO at all times when
the file was being edited, not just during DOCOND processing.

DOCOND		Node: Replace, Previous: Macros, Up: Top, Next: Run

Conditional Global Replacements.

  If one pair of alternatives appears very frequently throughout the
text, it would be painful to replace it with a pair of conditionals
each time it is needed.  The alternative is to use a conditional
global replacement declaration.  One version can actually be used in
the text and then replaced by the other on the appropriate condition.

  A global replacement declaration must appear in the declarations
section, and specifies a flag and setting as the condition, a string
to replace, and a string to replace with.  For example,

	{Replace:+FOO=>old->new}

says to replace old with new throughout, if FOO is +.  Replacement is
done using 1mmReplace Stringoldnew, so that, among other things,
instances of "old" are found only when surrounded by delimiter
characters, and certain control characters must be quoted as described
under Replace String (*Note Repl: (EMACS)Replace.).  Spaces are
significant, so don't put in any excess ones.  Replacements, like
other declarations, are processed in serial order, but they do not
apply to the declarations section;  only to the text after it.

  For a more complicated action than just replacing one string with
another, you can direct an arbitrary TECO program to be run to turn
the old string into what you want.  Do this by using "-->>" instead of
"->" and writing the TECO code instead of the string to replace with.
The difference between a -> replacement and a -->> replacement is the
difference between MM Query Replace and 1,MM Query Replace.  Here is
an example:

	{Replace:+FOO=>**-->>fkd fwk}

deletes every instance of "**" together with the following word.

DOCOND		Node: Run, Previous: Replace, Up: Top

Running DOCOND.

  The previous nodes tell everything about what to put in an input
file for DOCOND.  This is how to use DOCOND to process one.

  First, visit the input file, and do M-X Load LibDOCOND to load the
DOCOND program itself.  Then, in the simplest case, just do M-X DOCOND.
DOCOND will ask you for the setting of each flag, processing
implications of settings as you tell them to it.  When it knows all
the flag settings, it will process the buffer and return with
everything done.

  To protect you from filing the output back over the input file,
DOCOND clears the visit file names as soon as it starts.  Thus, C-X
C-S after DOCOND finishes will not be allowed.  In addition, if there
are any changes in the buffer when DOCOND is started, it offers to
save them for you (if you don't save them, they will be lost).

  Before starting the complete DOCOND processing, you can set
individual flags by means of the DOCOND Set Flag command present in
the DOCOND library.  This command expects an argument which contains a
setting followed by a flag name, as in

	M-X DOCOND Set Flag+FOO

The implications of the flags you set in this way will be processed as
soon as you do M-X DOCOND.  DOCOND Set Flag is useful primarily for
having a large number of flags which are all normally "-".  Rather
than asking you about each of them, you might prefer to have to do
DOCOND Set Flag for any that you wish to have "+", and let the rest be
forced to "-" by Default declarations.