








                MMaakkiinngg PPiiccttuurreess WWiitthh GGNNUU PPIICC

                      _E_r_i_c _S_. _R_a_y_m_o_n_d
                  <_e_s_r_@_s_n_a_r_k_._t_h_y_r_s_u_s_._c_o_m>


                          _A_B_S_T_R_A_C_T

          The  ppiicc  language  is a ttrrooffff extension that
     makes it easy to create  and  alter  box-and-arrow
     diagrams  of the kind frequently used in technical
     papers and  textbooks.   This  paper  is  both  an
     introduction  to  and  reference  for _g_p_i_c(1), the
     implementation distributed by  the  Free  Software
     Foundation for use with _g_r_o_f_f(1).


11..  IInnttrroodduuccttiioonn ttoo PPIICC

11..11..  WWhhyy PPIICC??

     The ppiicc language provides an easy way to write procedu-
ral box-and-arrow diagrams to be  included  in  ttrrooffff  docu-
ments.   The  language  is sufficiently flexible to be quite
useful for state charts, Petri-net  diagrams,  flow  charts,
simple  circuit  schematics, jumper layouts, and other kinds
of illustration involving repetitive uses of simple  geomet-
ric  forms and splines.  Because these descriptions are pro-
cedural and object-based, they are both compact and easy  to
modify.

     The _g_p_i_c(1) implementation of ppiicc is distributed by the
Free Software Foundation for use with their _g_r_o_f_f(1)  imple-
mentation of ttrrooffff.  Because both implementations are widely
available in source form for free, they are  good  bets  for
writing very portable documentation.

11..22..  PPIICC VVeerrssiioonnss

     The original 1984 pre-_d_i_t_r_o_f_f(1) version of ppiicc is long
obsolete.  The rewritten 1991 version is still available  as
part of the Documenter's Work Bench module of System V.

     Where   differences  between  Documenter's  Work  Bench
(1991) ppiicc and GNU ppiicc need to be described, original ppiicc is
referred  to  as  "DWB  pic".  Details on the history of the
program are given at the end of this document.

     In this document, the _g_p_i_c(1) extensions will be marked
as such.










                             -2-


22..  IInnvvookkiinngg PPIICC

     Every  ppiicc  description is a little program, which gets
compiled by _p_i_c(1) into  _g_t_r_o_f_f(1)  macros.   Programs  that
process  or  display  _g_t_r_o_f_f(1) output need not know or care
that parts of the image began life as ppiicc descriptions.

     The _p_i_c(1) program tries to translate anything  between
..PPSS  and  ..PPEE  markers,  and passes through everything else.
The normal definitions of ..PPSS and ..PPEE in the _m_s macro  pack-
age and elsewhere have also the side-effect of centering the
ppiicc output on the page.

22..11..  PPIICC EErrrroorr MMeessssaaggeess

     If you make a ppiicc syntax error, _g_p_i_c(1) will  issue  an
error message in the standard _g_c_c(1)-like syntax.  A typical
error message looks like this,

     pic:pic.ms:<nnn>: parse error before `<token>'
     pic:pic.ms:<nnn>: giving up on this picture


where <nnn> is a line number, and <token> is  a  token  near
(usually just after) the error location.

33..  BBaassiicc PPIICC CCoonncceeppttss

     Pictures  are described procedurally, as collections of
objects connected by motions.  Normally, ppiicc tries to string
together  objects  left-to-right  in  the  sequence they are
described, joining them at visually natural points.  Here is
an example illustrating the flow of data in ppiicc processing:

                        ++++++++++++
        ------     ---_g-_t-_b+_l(1) or _g_e_q+_n-(-1-)--     ------
 document    _g_p_i_c(1)    +(optional)+   _g_t_r_o_f_f(1)  PostScript
                        + ++++++++++

                Figure 3-1: Flow of ppiicc data


     This was produced from the following ppiicc program:




















                             -3-


     .PS
     ellipse "document";
     arrow;
     box width 0.6 "\fIpic\/\fP(1)"
     arrow;
     box width 1.1 "\fIgtbl\/\fP(1) or \fIgeqn\/\fP(1)" "(optional)" dashed;
     arrow;
     box width 0.6 "\fIgtroff\/\fP(1)";
     arrow;
     ellipse "PostScript"
     .PE


This   little   program   illustrates  several  ppiicc  basics.
Firstly, we see how to invoke three object types;  ellipses,
arrows,  and  boxes.  We see how to declare text lines to go
within an object (and that text can  have  font  changes  in
it).   We see how to change the line style of an object from
solid to dashed.  And we see that a box can  be  made  wider
than  its  default size to accommodate more text (we'll dis-
cuss this facility in detail in the next section).

     We also get to see ppiicc's simple syntax.  Statements are
ended by newlines or semicolons.  String quotes are required
around all text  arguments,  whether  or  not  they  contain
spaces.  In general, the order of command arguments and mod-
ifiers like "width 1.2" or "dashed" doesn't  matter,  except
that the order of text arguments is significant.

     Here  are all but one of the basic ppiicc objects at their
default sizes:

 
             --l-i-n-e-    -a-r-r-o-w-
   box                           circle     ellipse
                                                         arc

               Figure 3-2: Basic ppiicc objects


     The missing simple object type is a _s_p_l_i_n_e.   There  is
also  a  way  to collect objects into _b_l_o_c_k _c_o_m_p_o_s_i_t_e_s which
allows you to treat the  whole  group  as  a  single  object
(resembling  a  box) for many purposes.  We'll describe both
of these later on.

     The box, ellipse, circle, and block  composite  objects
are  _c_l_o_s_e_d; lines, arrows, arcs and splines are _o_p_e_n.  This
distinction will often be important  in  explaining  command
modifiers.

     Figure  3-2  was produced by the following ppiicc program,
which introduces some more basic concepts:










                             -4-


     .PS
     box "box";
     move;
     line "line" "";
     move;
     arrow "arrow" "";
     move;
     circle "circle";
     move;
     ellipse "ellipse";
     move;
     arc; down; move; "arc"
     .PE


     The first thing to notice is the  _m_o_v_e  command,  which
moves  a default distance (1/2 inch) in the current movement
direction.

     Secondly, see how we can also decorate lines and arrows
with  text.  The line and arrow commands each take two argu-
ments here, specifying  text  to  go  above  and  below  the
object.   If  you wonder why one argument would not do, con-
template the output of aarrrrooww ""ooww!!"":

                           --o-w-!--

           Figure 3-3: Text centered on an arrow


     When a command takes one  text  string,  ppiicc  tries  to
place  it at the object's geometric center.  As you add more
strings, ppiicc treats them as a vertical block to be centered.
The program

     line "1";
     line "1" "2";
     line "1" "2" "3";
     line "1" "2" "3" "4";
     line "1" "2" "3" "4" "5";


for example, gives you this:

                                       1
                             1    1    2
                 ---1-----1-----2-----2-----3---
                        2    3    3    4
                                  4    5

       Figure 3-4: Effects of multiple text arguments












                             -5-


     The  last  line  of  Figure  3.2's program, `aarrcc;; ddoowwnn;;
mmoovvee;; ""aarrcc""', describing the captioned arc, introduces  sev-
eral new ideas.  Firstly, we see how to change the direction
in which objects are joined.   Had  we  written  aarrcc;;  mmoovvee;;
""aarrcc"",  omitting  ddoowwnn the caption would have been joined to
the top of the arc, like this:

                              arc





              Figure 3-5: Result of aarrcc;; mmoovvee;;


     This is because drawing  an  arc  changes  the  default
direction  to  the one its exit end points at.  To reinforce
this point, consider:






                              arc
            Figure 3-6: Result of aarrcc ccww;; mmoovvee;;


     All we've done differently here is specify "cw"  for  a
clockwise arc ("ccw" specifies counter-clockwise direction).
Observe how it changes the default direction to down, rather
than up.

     Another  good  way  to  see this via with the following
program:

     line; arc; arc cw; line


which yields:

                                ------


                      ------

       Figure 3-7: Result of lliinnee;; aarrcc;; aarrcc ccww;; lliinnee


Notice that we did not have to specify "up" for  the  second
arc to be joined to the end of the first.











                             -6-


     Finally,  observe  that  a string, alone, is treated as
text to be surrounded by an invisible box of a  size  either
specified  by width and height attributes or by the defaults
tteexxttwwiidd and tteexxtthhtt.  Both are  initially  zero  (because  we
don't know the default font size).

44..  SSiizzeess aanndd SSppaacciinngg

     Sizes  are  specified  in  inches.   If  you don't like
inches, it's possible to set a global style  variable  ssccaallee
that  changes  the  unit.   Setting ssccaallee == 22..5544 will effec-
tively change the internal unit to  centimeters  (all  other
size variable values will be scaled correspondingly).

44..11..  DDeeffaauulltt SSiizzeess ooff OObbjjeeccttss

     Here are the default sizes for ppiicc objects:
                     |
             OObbjjeecctt  | DDeeffaauulltt SSiizzee
             --------+-------------------------
             box     | 0.75" wide by 0.5" high
             circle  | 0.5" diameter
             ellipse | 0.75" wide by 0.5" high
             arc     | 0.5" radius
             line    | 0.5" long
             arrow   | 0.5" long
             --------+-------------------------


     The  simplest way to think about these defaults is that
they make the other basic objects fit snugly into a default-
sized box.

44..22..  OObbjjeeccttss DDoo NNoott SSttrreettcchh!!

     Text  is rendered in the current font with normal troff
line spacing.  Boxes, circles, and ellipses do _n_o_t automati-
cally  resize  to  fit  enclosed text.  Thus, if you say bbooxx
""tthhiiss tteexxtt ffaarr ttoooo lloonngg ffoorr aa ddeeffaauulltt bbooxx"" you'll get this:



        this text is far too long for a default box


       Figure 4-1: Boxes do not automatically resize


which is probably not the effect you want.

44..33..  RReessiizziinngg BBooxxeess

     To change the box size, you can  specify  a  box  width
with the "width" modifier:









                             -7-




         this text is far too long for a default box


             Figure 4-2: Result of bbooxx wwiiddtthh 33


     This  modifier  takes  a dimension in inches.  There is
also a "height" modifier that will change  a  box's  height.
The wwiiddtthh keyword may be abbreviated to wwiidd; the hheeiigghhtt key-
word to hhtt.

44..44..  RReessiizziinngg OOtthheerr OObbjjeecctt TTyyppeess

     To change the size of a circle, give it a  rraadd[[iiuuss]]  or
ddiiaamm[[eetteerr]]  modifier; this changes the radius or diameter of
the circle, according to the numeric argument that  follows.



                         0.2       0.3

                    0.1

         Figure 4-3: Circles with increasing radii


     The  mmoovvee command can also take a dimension, which just
tells it how many inches to move in the current direction.

     Ellipses are  sized  to  fit  in  the  rectangular  box
defined  by  their  axes,  and can be resized with wwiiddtthh and
hheeiigghhtt like boxes.

     You can also change the radius of curvature of  an  arc
with  rraadd[[iiuuss]]  (which specifies the radius of the circle of
which the arc is a segment).  Larger  values  yield  flatter
arcs.




                      0.1 0.2  0.3

         Figure 4-4: aarrcc rraadd with increasing radii


     Observe  that  because  an  arc is defined as a quarter
circle, increasing the radius also increases the size of the
arc's bounding box.












                             -8-


44..55..  TThhee ``ssaammee'' KKeeyywwoorrdd

     In  place of a dimension specification, you can use the
keyword ssaammee.  This gives the object the same  size  as  the
previous one of its type.  As an example, the program

     .PS
     box; box wid 1 ht 1; box same; box
     .PE


gives you









                Figure 4-5: The ssaammee keyword



55..  GGeenneerraalliizzeedd LLiinneess aanndd SSpplliinneess

55..11..  DDiiaaggoonnaall LLiinneess

     It  is  possible to specify diagonal lines or arrows by
adding multiple uupp, ddoowwnn, lleefftt, and rriigghhtt modifiers  to  the
line object.  Any of these can have a multiplier.  To under-
stand the effects, think of the drawing area as being  grid-
ded with standard-sized boxes.

  ++++++ +++++++++++ ++++++++++++++++ +++++++++++++++++++++
  +    + +    +    + +    +    +    + +    +    +    +    +
  +    + +    +    + +    +    +    + +    +    +    +    +
  ++++++ +++++++++++ ++++++++++++++++ +++++++++++++++++++++

lliinnee uuppaallrreerrffoottww uupp lleefftt 11aarrrrooww uupp lleefftt 11..55   aarrrrooww uupp lleefftt 22
Figure  5-1:  Diagonal arrows (dotted boxes show the implied
                       0.5-inch grid)


55..22..  MMuullttii--SSeeggmmeenntt LLiinnee OObbjjeeccttss

     A "line" or "arrow" object may actually be a path  con-
sisting  of  any  number  of segments of varying lengths and
directions.  To describe a path,  connect  several  line  or
arrow commands with the keyword tthheenn.












                             -9-


                         -----------


                         -----------

 Figure 5-2: lliinnee rriigghhtt 11 tthheenn ddoowwnn ..55 lleefftt 11 tthheenn rriigghhtt 11


55..33..  SSpplliinnee OObbjjeeccttss

     If  you  start a path with the sspplliinnee keyword, the path
vertices are treated as control points for  a  spline  curve
fit.

                              1 +++++++++++2
                                      ++
                                  ++++
                              3 ++++++++++4
            The spline cu.r.v.ew.i.t.h tangents displayed

Figure 5-3: sspplliinnee rriigghhtt 11 tthheenn ddoowwnn ..55 lleefftt 11 tthheenn rriigghhtt 11


     You  can  describe  many  natural-looking but irregular
curves this way.  For example:

            



sspplliinnee rriigghhtt tthheenn uupp tthheenn lleeffttssttpphhlleeiinnnneeddoollwweennfftt-->>tt;;hheenn uupp rriigghhtt tthheenn ddoowwnn rriigghhtt -->>;;

            Figure 5-4: Two more spline examples


Note the arrow decorations.  Arrowheads can be applied natu-
rally  to  any path-based object, line or spline.  We'll see
how in the next section.

66..  DDeeccoorraattiinngg OObbjjeeccttss

66..11..  DDaasshheedd OObbjjeeccttss

     We've already seen that the modifier ddaasshheedd can  change
the  line style of an object from solid to dashed.  GNU ggppiicc
permits you to dot or dash ellipses, circles, and arcs  (and
splines  in  TeX  mode  only); some versions of DWB may only
permit dashing of lines and boxes.  It's possible to  change
the dash interval by specifying a number after the modifier.














                            -10-


 ++++++++    +++++++++    +------+    |-- -- -+    +--  --+
 +      +    +       +    |      |    |       |    |      |
 +default+    + 0.05  +    | 0.1  |    | 0.15  |    | 0.2  |
 ++++++++    +++++++++    +------+    +- -- --|    +--  --+

                 Figure 6-1: Dashed objects


66..22..  DDootttteedd OObbjjeeccttss

     Another available qualifier is ddootttteedd.  GNU  ggppiicc  per-
mits  you  to  dot  or dash ellipses, circles, and arcs (and
splines in TeX mode only); some versions  of  DWB  may  only
permit  dashing  of lines and boxes.  It too can be suffixed
with a number to specify the interval between dots:

 ++++++++    +++++++++    ++++++++    + ++ ++ +    + + + ++
 +      +    +       +    +      +    +       +    +      +
 +default+    + 0.05  +    + 0.1  +    + 0.15  +    + 0.2  +
 ++++++++    +++++++++    ++++++++    + ++ ++ +    + + + ++

                 Figure 6-2: Dotted objects


66..33..  RRoouunnddiinngg BBooxx CCoorrnneerrss

     It is also possible, in GNU ggppiicc only, to modify a  box
so it has rounded corners:

 -------|    |------       -----        ----         ---
 |      |    |       |    |      |    |       |    +      +
 |rad 0.0|5    |rad 0.1|    |rad 0.1|5    |rad 0.2|    rad 0.25
 |-------      ------|      -----        ----         ---

     Figure 6-3: bbooxx rraadd with increasing radius values


     Radius  values  higher than half the minimum box dimen-
sion are silently truncated to that value.

66..44..  AArrrroowwhheeaaddss

     Lines and arcs can be decorated as well.  Any  line  or
arc  (and  any  spline as well) can be decorated with arrow-
heads by adding one or more as modifiers:

                           ------

    Figure 6-4: Double-headed line made with  lliinnee <<-- -->>


     In fact, the aarrrrooww command is just shorthand  for  lliinnee
-->>.   And there is a double-head modifier <->, so the figure
above could have been made with lliinnee <<-->>.









                            -11-


     Arrowheads have a wwiiddtthh attribute, the distance  across
the  rear;  and a hheeiigghhtt attribute, the length of the arrow-
head along the shaft.

     Arrowhead style is controlled  by  the  style  variable
aarrrroowwhheeaadd.   The  DWB  and GNU versions interpret it differ-
ently.  DWB defaults to open  arrowheads  and  an  aarrrroowwhheeaadd
value  of 2; the Kernighan paper says a value of 7 will make
solid arrowheads.  GNU ggppiicc defaults to solid arrowheads and
an  aarrrroowwhheeaadd  value  of  1;  a value of 0 will produce open
arrowheads.  Note that solid arrowheads  are  always  filled
with the current outline color.

66..55..  LLiinnee TThhiicckknneessss

     It's  also  possible to change the line thickness of an
object (this is a GNU extension,  DWB  ppiicc  doesn't  support
it).   The  default  thickness  of  the  lines  used to draw
objects is controlled by the lliinneetthhiicckk variable.  This gives
the  thickness  of  lines in points.  A negative value means
use the default thickness: in TeX output  mode,  this  means
use  a  thickness  of 8 milliinches; in TeX output mode with
the --cc option, this means use the line  thickness  specified
by  ..ppss lines; in troff output mode, this means use a thick-
ness proportional to the pointsize.  A zero value means draw
the  thinnest  possible line supported by the output device.
Initially it has a value of -1.  There is also  a  tthhiicckknneessss
attribute (which can be abbreviated to tthhiicckk).  For example,
cciirrccllee tthhiicckknneessss 11..55 would draw a circle using a line with a
thickness  of  1.5  points.   The  thickness of lines is not
affected by the value of the  ssccaallee  variable,  nor  by  any
width or height given in the ..PPSS line.

66..66..  IInnvviissiibbllee OObbjjeeccttss

     The  modifier  iinnvviiss[[iibbllee]]  makes  an  object  entirely
invisible.  This used to be useful for positioning  text  in
an  invisible  object that is properly joined to neighboring
ones.  Newer DWB versions and GNU ppiicc treat stand-alone text
in exactly this way.

66..77..  FFiilllleedd OObbjjeeccttss

     It  is  possible  to fill boxes, circles, and ellipses.
The modifier ffiillll[[eedd]] accomplishes this.  You can suffix  it
with  a  fill value; the default is given by the stule vari-
able ffiillllvvaall.

     DWB ppiicc and ggppiicc have  opposite  conventions  for  fill
values  and different defaults.  DWB ffiillllvvaall defaults to 0.3
and smaller values are darker; GNU ffiillllvvaall uses 0 for  white
and 1 for black.











                            -12-


                 




Figure 6-5: cciirrccllee ffiillll;; mmoovvee;; cciirrccllee ffiillll 00..44;; mmoovvee;; cciirrccllee
                         ffiillll 00..99;;


     GNU ggppiicc makes  some  additional  guarantees.   A  fill
value  greater than 1 can also be used: this means fill with
the shade of gray that is currently being used for text  and
lines.   Normally this will be black, but output devices may
provide  a  mechanism  for  changing  this.   The  invisible
attribute  does not affect the filling of objects.  Any text
associated with a filled object  will  be  added  after  the
object  has  been  filled,  so  that  the  text  will not be
obscured by the filling.

     The closed-object modifier ssoolliidd is equivalent to  ffiillll
with the darkest fill value (DWB ppiicc had this capability but
mentioned it only in a reference section).

66..88..  CCoolloorreedd OObbjjeeccttss

     As a GNU  extension,  three  additional  modifiers  are
available  to  specify  colored  objects.   oouuttlliinnee sets the
color of the outline, sshhaaddeedd the fill color, and ccoolloorr  sets
both.   All  three  keywords  expect a suffix specifying the
color.  Example:

                                      
                            ------

                            

Figure 6-6: bbooxx ccoolloorr ""yyeellllooww"";; aarrrrooww ccoolloorr  ""ccyyaann"";;  cciirrccllee
              sshhaaddeedd ""ggrreeeenn"" oouuttlliinnee ""bbllaacckk"";;


     Alternative  spellings  are  ccoolloouurr, ccoolloorreedd, ccoolloouurreedd,
and oouuttlliinneedd.

     Currently, color support is not available in TeX  mode.
Predefined  color names for _g_r_o_f_f(1) are in the device macro
files, for example ps.tmac; additional colors can be defined
with  the  ..ddeeffccoolloorr  request  (see  the  manual page of GNU
_t_r_o_f_f(1) for more details).

     ppiicc assumes that at the beginning  of  a  picture  both
glyph and fill color are set to the default value.












                            -13-


77..  MMoorree AAbboouutt TTeexxtt PPllaacceemmeenntt

     By default, text is centered at the geometric center of
the object it is associated with.  The modifier lljjuusstt causes
the  left end to be at the specified point (which means that
the text lies to the right of  the  specified  place!),  the
modifier  rrjjuusstt  puts the right end at the place.  The modi-
fiers aabboovvee and bbeellooww center the text one half line space in
the given direction.

     Text attributes can be combined:

       |              |
       |              |    ------l-j-u-s-t-abov-e----------
       |ljustrtjeuxstt text|             rjust below
       |              |

                Figure 7-1: Text attributes


     What  actually  happens is that _n text strings are cen-
tered in a box that is tteexxttwwiidd wide by  tteexxtthhtt  high.   Both
these variables are initially zero (that is ppiicc's way of not
making assumptions about _[_t_g_]_r_o_f_f(1)'s default point  size).

     In  GNU  ggppiicc,  objects  can have an aalliiggnneedd attribute.
This will only work when the postprocessor  is  ggrrooppss.   Any
text  associated with an object having the aalliiggnneedd attribute
will be rotated about the center of the object so that it is
aligned  in  the  direction  from the start point to the end
point of the object.  Note that this attribute will have  no
effect  for  objects  whose start and end points are coinci-
dent.

88..  MMoorree AAbboouutt DDiirreeccttiioonn CChhaannggeess

     We've already seen how to change the direction in which
objects are composed from rightwards to downwards.  Here are
some more illustrative examples:
























                            -14-


          rriigghhtt;; bbooxx;; aarrrrooww;; cciirrccllee;; aarrrrooww;; eelllliippssee


                      ------    ------


          lleefftt;; bbooxx;; aarrrrooww;; cciirrccllee;; aarrrrooww;; eelllliippssee


                      ------    ------


Figure 8-1: Effects of different  motion  directions  (right
                         and left)


ddoowwnn;; bbooxx;; aarrrrooww;; cciirrccllee;; aarrrroouuwwpp;;;; eebblloollxxii;;ppssaaeerr;;rrooww;; cciirrccllee;; aarrrrooww;; eelllliippssee;;



                |                          |
                |                          |
                |                          |
                |                          |


                |                          |
                |                          |
                |                          |
                |                          |




Figure 8-2: Effects of different motion directions (up and down)


     Something  that  may  appear  surprising happens if you
change directions in the obvious way:

                   
                          ------    |
                                    |
                                    |
                                    |




    Figure 8-3: bbooxx;; aarrrrooww;; cciirrccllee;; ddoowwnn;; aarrrrooww;; eelllliippssee


You might have expected that program to yield this:










                            -15-


                     
                            ------

                                    |
                                    |
                                    |
                                    |




                Figure 8-4: More intuitive?


But, in fact, to get Figure 8.3 you have to do this:

     .PS
     box;
     arrow;
     circle;
     move to last circle .s;
     down;
     arrow;
     ellipse
     .PE


Why is this?  Because the exit point for the current  direc-
tion  is  already  set when you draw the object.  The second
arrow in Figure 8.2  dropped  downwards  from  the  circle's
attachment point for an object to be joined to the right.

     The  meaning  of  the  command  mmoovvee  ttoo llaasstt cciirrccllee ..ss
should be obvious.  In order  to  see  how  it  generalizes,
we'll  need to go into detail on two important topics; loca-
tions and object names.

99..  NNaammiinngg OObbjjeeccttss

     The most natural way to name locations in ppiicc is  rela-
tive  to  objects.  In order to do this, you have to be able
you have to be able to name objects.  The ppiicc  language  has
rich  facilities  for this that try to emulate the syntax of
English.

99..11..  NNaammiinngg OObbjjeeccttss BByy OOrrddeerr OOff DDrraawwiinngg

     The simplest (and generally the  most  useful)  way  to
name  an  object is with a llaasstt clause.  It needs to be fol-
lowed by an object type name; bbooxx,  cciirrccllee,  eelllliippssee,  lliinnee,
aarrrrooww,  sspplliinnee, """", or [[]] (the last type refers to a _c_o_m_p_o_s_-
_i_t_e _o_b_j_e_c_t which we'll discuss later).  So, for example, the
llaasstt  cciirrccllee  clause in the program attached to Figure 9.1.3
refers to the last circle drawn.









                            -16-


     More generally, objects of a given type are  implicitly
numbered  (starting  from  1).   You  can refer to (say) the
third ellipse in the current picture with 33rrdd eelllliippssee, or to
the first box as 11sstt bbooxx, or to the fifth text string (which
isn't an attribute to another object) as 55tthh """".

     Objects are also numbered backwards by  type  from  the
last  one.   You  can say 22nndd llaasstt bbooxx to get the second-to-
last box, or 33rrdd  llaasstt  eelllliippssee  to  get  the  third-to-last
ellipse.

     In  places  where  _ntthh  is  allowed,  ``_e_x_p_r''tthh  is also
allowed.  Note that ''tthh is  a  single  token:  no  space  is
allowed between the '' and the tthh.  For example,


          for i = 1 to 4 do {
             line from `i'th box.nw to `i+1'th box.se
          }


99..22..  NNaammiinngg OObbjjeeccttss WWiitthh LLaabbeellss

     You can also specify an object by referring to a label.
A label is a word (which must begin with a  capital  letter)
followed  by  a  colon; you declare it by placing it immedi-
ately before the object drawing command.  For  example,  the
program

     .PS
     A: box "first" "object"
     move;
     B: ellipse "second" "object"
     move;
     arrow right at A .r;
     .PE


declares  labels  AA  and BB for its first and second objects.
Here's what that looks like:

                 
                  first ------second
                  object      object


              Figure 9-1: Example of label use

The aatt statement in the fourth line uses the  label  AA  (the
behavior  of  aatt  will  be  explained  in the next section).
We'll see later on that labels are most useful for referring
to block composite objects.











                            -17-


     Labels  are  not  constants but variables (you can view
colon as a sort of assignment).  You can say something  like
AA:: AA ++ ((11,,00));; and the effect will be to reassign the label AA
to designate a position one inch to the  right  of  its  old
value.

1100..  DDeessccrriibbiinngg llooccaattiioonnss

     The location of points can be described in many differ-
ent ways.  All these forms are interchangeable as for as the
ppiicc language syntax is concerned; where you can use one, any
of the others that would make semantic sense are allowed.

     The special label HHeerree always  refers  to  the  current
position.

1100..11..  AAbbssoolluuttee CCoooorrddiinnaatteess

     The  simplest  is  absolute  coordinates in inches; ppiicc
uses a Cartesian system with (0, 0) at the lower left corner
of  the virtual drawing surface for each picture (that is, X
increases to the right and Y increases upwards).   An  abso-
lute location may always be written in the conventional form
as two comma-separated  numbers  surrounded  by  parentheses
(and this is recommended for clarity).  In contexts where it
creates no ambiguity, the pair of X and Y  coordinates  suf-
fices without parentheses.

     It  is  a good idea to avoid absolute coordinates, how-
ever.  They tend to make picture descriptions  difficult  to
understand and modify.  Instead, there are quite a number of
ways to specify locations relative to ppiicc objects and previ-
ous locations.


1100..22..  LLooccaattiioonnss RReellaattiivvee ttoo OObbjjeeccttss

     The  symbol  HHeerree  always refers to the position of the
last object drawn or the destination of the last mmoovvee.

     Alone and unqualified, a llaasstt cciirrccllee or any  other  way
of  specifying  a  closed-object or arc location refers as a
position to the geometric center of  the  object.   Unquali-
fied,  the  name  of  a  line or spline object refers to the
position of the object start.

     Also, ppiicc objects have  quite  a  few  named  locations
associated  with  them.   One of these is the object center,
which can be indicated (redundantly) with the suffix ..cceenntteerr
(or  just  ..cc).   Thus, llaasstt cciirrccllee ..cceenntteerr is equivalent to
llaasstt cciirrccllee.












                            -18-


1100..22..11..  LLooccaattiioonnss RReellaattiivvee ttoo CClloosseedd OObbjjeeccttss

     Every closed object (box,  circle,  ellipse,  or  block
composite) also has eight compass points associated with it;

  ..nnww      ..nn     ..nnee        ..nn               ..nn
                        ..nnww     ..nnee     ..nnww         ..nnee

 ..ww          ..cc     ..ee..ww       ..cc   ..ee..ww         ..cc      ..ee


                        ..ssww     ..ssee     ..ssww         ..ssee
  ..ssww      ..ss     ..ssee        ..ss               ..ss
                Figure 10-1: Compass points


these are the locations where eight compass  rays  from  the
geometric center would intersect the figure.  So when we say
llaasstt cciirrccllee ..ss we are referring to the south  compass  point
of  the  last circle drawn.  The explanation of Figure 7.3's
program is now complete.

     (In case you dislike compass points,  the  names  ..ttoopp,
..bboottttoomm,  ..lleefftt  and ..rriigghhtt are synonyms for ..nn, ..ss, ..ee, and
..ww respectively; they can even be abbreviated to ..tt, ..bb,  ..ll
and ..rr).

     The  names  cceenntteerr,  ttoopp,  bboottttoomm,  lleefftt, rriigghhtt, nnoorrtthh,
ssoouutthh, eeaasstt, and wweesstt can also be used (without the  leading
dot)  in  a  prefix  form marked by ooff; thus, cceenntteerr ooff llaasstt
cciirrccllee and ttoopp ooff 22nndd llaasstt eelllliippssee  are  both  valid  object
references.   Finally,  the names lleefftt and rriigghhtt can be pre-
fixed with uuppppeerr and lloowweerr which both have the obvious mean-
ing.

     Arc  objects also have compass point; they are the com-
pass points of the implied circle.

1100..22..22..  LLooccaattiioonnss RReellaattiivvee ttoo OOppeenn OObbjjeeccttss

     Every open object (line, arrow,  arc,  or  spline)  has
three named points: ..ssttaarrtt, ..cceenntteerr (or ..cc), and ..eenndd.  They
can also be used without leading dots in the ooff prefix form.
The  center  of  an arc is the center of its circle, but the
center of a line, path, or spline  is  halfway  between  its
endpoints.

















                            -19-


                  ..eenndd     ..ssttaarrtt

          ..cceenntteerr
      ..ssttaarrtt              ..cceenntteerr ..eenndd



      ..ssttaarrtt -----------     ..eenndd
          ..cceenntteerr         ..cceenntteerr

             ------..-ee-nn-dd--   ..ssttaarrtt

        Figure 10-2: Special points on open objects



1100..33..  WWaayyss ooff CCoommppoossiinngg PPoossiittiioonnss

     Once  you  have  two  positions to work with, there are
several ways to combine them to specify new positions.

1100..33..11..  VVeeccttoorr SSuummss aanndd DDiissppllaacceemmeennttss

     Positions may be added or subtracted  to  yield  a  new
position  (to  be  more precise, you can only add a position
and an expression pair; the latter must be on the right side
of  the  addition  or  subtraction sign).  The result is the
conventional vector sum or difference of  coordinates.   For
example,  llaasstt bbooxx ..nnee ++ ((00..11,, 00)) is a valid position.  This
example illustrates a  common  use,  to  define  a  position
slightly  offset  from a named one (say, for captioning pur-
poses).

1100..33..22..  IInntteerrppoollaattiioonn BBeettwweeeenn PPoossiittiioonnss

     A position may be interpolated between  any  two  posi-
tions.  The syntax is `_f_r_a_c_t_i_o_n ooff tthhee wwaayy bbeettwweeeenn _p_o_s_i_t_i_o_n_1
aanndd _p_o_s_i_t_i_o_n_2'.  For example, you can say  11//33  ooff  tthhee  wwaayy
bbeettwweeeenn  hheerree  aanndd llaasstt eelllliippssee ..nnee.  The fraction may be in
numerator/denominator form or  may  be  an  ordinary  number
(values  are _n_o_t restricted to [0,1]).  As an alternative to
this verbose syntax, you can  say  `_f_r_a_c_t_i_o_n   <<_p_o_s_i_t_i_o_n_1  ,,
_p_o_s_i_t_i_o_n_2>>';  thus, the example could also be written as 11//33
<<hheerree,, llaasstt eelllliippssee>>.

                           

                             P


Figure 10-3: PP:: 11//33 ooff tthhee wwaayy bbeettwweeeenn llaasstt aarrrrooww ..ssttaarrtt aanndd
                      llaasstt aarrrrooww ..eenndd











                            -20-


     This  facility can be used, for example, to draw double
connections.

                    
                           ------
                      yin  ------ yang


                Figure 10-4: Doubled arrows


You can get Figure 10-4 from the following program:

     .PS
     A: box "yin"; move;
     B: box "yang";
     arrow right at 1/4 <A.e,A.ne>;
     arrow left  at 1/4 <B.w,B.sw>;
     .PE


Note the use of the short form for interpolating points.

1100..33..33..  PPrroojjeeccttiioonnss ooff PPooiinnttss

     Given two positions _p and _q, the position  ((_p,,  _q))  has
the  X  coordinate of _p and the Y coordinate of _q.  This can
be helpful in placing an object at one of the corners of the
virtual box defined by two other objects.

                   A                     ((BB,,AA)) is here






      ((AA,,BB)) is here                      B

           Figure 10-5: Using (_x, _y) composition


1100..44..  UUssiinngg LLooccaattiioonnss

     There are four ways to use locations; aatt, ffrroomm, ttoo, and
wwiitthh.  All three are object modifiers; that is, you use them
as suffixes to a drawing command.

     The  aatt  modifier  says  to draw a closed object or arc
with its center at the following  location,  or  to  draw  a
line/spline/arrow starting at the following location.

     The  ttoo  modifier  can  be used alone to specify a move
destination.  The ffrroomm modifier can be  used  alone  in  the









                            -21-


same way as aatt.

     The  ffrroomm  and  ttoo modifiers can be used with a lliinnee or
aarrcc command to specify start and end points of  the  object.
In  conjunction  with  named  locations,  this offers a very
flexible mechanism for connecting objects.  For example, the
following program

     .PS
     box "from"
     move 0.75;
     ellipse "to"
     arc cw from 1/3 of the way \
         between last box .n and last box .ne to last ellipse .n;
     .PE


yields:




                     from            to



Figure 10-6: A tricky connection specified with English-like syntax


     The  wwiitthh  modifier  allows  you  to  identify  a named
attachment point of an object  (or  a  position  within  the
object)  with  another  point.  This is very useful for con-
necting objects in a natural way.  For an example,  consider
these two programs:









                                  bbooxx wwiidd 00..55 hhtt 00..55;;
bbooxx wwiidd 00..55 hhtt 00..55;; bbooxx wwiibbddooxx00..ww77ii55dd hh00tt..770055..77hh55tt 00..7755 wwiitthh ..ssww aatt llaasstt bbooxx ..ssee;;


    Figure 10-7: Using the wwiitthh modifier for attachments


1100..55..  TThhee ``cchhoopp'' MMooddiiffiieerr

     When drawing lines between circles that don't intersect
them at a compass point, it is useful to be able to  shorten









                            -22-


a  line  by the radius of the circle at either or both ends.
Consider the following program:

     .PS
     circle "x"
     circle "y" at 1st circle - (0.4, 0.6)
     circle "z" at 1st circle + (0.4, -0.6)
     arrow from 1st circle to 2nd circle chop
     arrow from 2nd circle to 3rd circle chop
     arrow from 3rd circle to 1st circle chop
     .PE


It yields the following:

                       

                             x


                         y  ---- z



               Figure 10-8: The cchhoopp modifier


Notice that the cchhoopp attribute moves arrowheads rather  than
stepping  on  them.   By default, the cchhoopp modifier shortens
both ends of the line by cciirrcclleerraadd.  By suffixing it with  a
number you can change the amount of chopping.

     If you say lliinnee ...... cchhoopp _r_1 cchhoopp _r_2 with _r_1 and _r_2 both
numbers, you can vary the amount of chopping at  both  ends.
You can use this in combination with trigonometric functions
to write code that will deal  with  more  complex  intersec-
tions.

1111..  OObbjjeecctt GGrroouuppss

     There  are  two different ways to group objects in ppiicc;
_b_r_a_c_e _g_r_o_u_p_i_n_g and _b_l_o_c_k _c_o_m_p_o_s_i_t_e_s.

1111..11..  BBrraaccee GGrroouuppiinngg

     The simpler method is simply to group a set of  objects
within curly bracket or brace characters.  On exit from this
grouping, the current position and direction are restored to
their value when the opening brace was encountered.

1111..22..  BBlloocckk CCoommppoossiitteess

     A  block  composite  object is created a series of com-
mands enclosed by square brackets.   The  composite  can  be









                            -23-


treated  for most purposes like a single closed object, with
the size and shape of its bounding box.  Here is an example.
The program fragment

     A: [
         circle;
         line up 1 at last circle .n;
         line down 1 at last circle .s;
         line right 1 at last circle .e;
         line left 1 at last circle .w;
         box dashed with .nw at last circle .se + (0.2, -0.2);
         Caption: center of last box;
     ]


yields the block in figure 11-1, which we show both with and
without its attachment points.  The block's location becomes
the value of AA.

              |               ..nnww           ..|nn          ..nnee
              |                              |
              |                              |
              |                              |
              |                              |
              |                              |
              |                              |

  -----------    ----------- ..ww -----------   ..-cc----------..ee
              |                              |
              |   +++++++++                  |  +++++++++
              |   +       +                  |  +       +
              |   +       +                  |  +       +
              |   +++++++++                  |  +++++++++
              |                              |
              |                              |
                              ..ssww           ..ss          ..ssee
           Figure 11-1: A sample composite object


To  refer  to  one of the composite's attachment points, you
can say (for example) AA ..ss.  For purposes of object  naming,
composites  are  a  class.  You could write llaasstt [[]] ..ss as an
equivalent reference, usable anywhere a location is  needed.
This  construction  is  very  important for putting together
large, multi-part diagrams.

     Blocks are also a variable-scoping  mechanism,  like  a
_g_r_o_f_f(1)  environment.  All variable assignments done inside
a block are undone at the end  of  it.   To  get  at  values
within a block, write a name of the block followed by a dot,
followed by the label you want.  For example, we could refer
the  the center of the box in the above composite as llaasstt [[]]
..CCaappttiioonn or AA..CCaappttiioonn.










                            -24-


     This kind of reference to a label can be  used  in  any
way  any  other  location  can be.  For example, if we added
""HHii!!"" aatt AA..CCaappttiioonn the result would look like this:

                             |
                             |
                             |
                             |
                             |
                             |
                             |
                 -----------    -----------

                             |
                             |   +++++++++
                             |   + Hi!   +
                             |   +       +
                             |   +++++++++
                             |
                             |

   Figure 11-2: Adding a caption using interior labeling


     You can also use interior labels in either  part  of  a
wwiitthh  modifier.  This means that the example composite could
be placed relative to its caption box by a command  contain-
ing wwiitthh AA..CCaappttiioonn aatt.

     Note  that both width and height of the block composite
object are always positive:








bbooxx wwiidd --00..55 hhtt 00..55;; bbooxx wwiidd 00[[..bb77oo55xx hhwwttiidd00..--770055..55 hhtt 00..55]];; bbooxx wwiidd 00..7755 hhtt 00..7755

Figure 11-3: Composite block objects  always  have  positive
                      width and height


     Blocks  may  be  nested.   This means you can use block
attachment points to build up  complex  diagrams  hierarchi-
cally,  from  the  inside out.  Note that llaasstt and the other
sequential naming mechanisms don't look inside blocks, so if
you have a program that looks like













                            -25-


     .PS
     P: [box "foo"; ellipse "bar"];
     Q: [
          [box "baz"; ellipse "quxx"]
          "random text";
        ]
     arrow from 2nd last [];
     .PE


the arrow in the last line will be attached to object PP, not
object QQ.

     In  DWB  ppiicc,  only  references  one  level  deep  into
enclosed  blocks  were  permitted.   GNU  ggppiicc  removes this
restriction.

     The combination of block variable scoping,  assignabil-
ity  of  labels  and  the macro facility that we'll describe
later on can be used to simulate functions with local  vari-
ables (just wrap the macro body in block braces).

1122..  SSttyyllee VVaarriiaabblleess

     There  are  a  number  of global style variables in ppiicc
that can be used to change its overall behavior.  We've men-
tioned  several  of  them in previous sections.  They're all
described here.  For each variable, the default is given.
               |         |
SSttyyllee VVaarriiaabbllee | DDeeffaauulltt | WWhhaatt IItt DDooeess
---------------+---------+-----------------------------------------------
boxht          |   0.5   | Default height of a box
boxwid         |   0.75  | Default width of a box
lineht         |   0.5   | Default length of vertical line
linewid        |   0.75  | Default length of horizontal line
linethick      |  -1     | Default line thickness
arcrad         |   0.25  | Default radius of an arc
circlerad      |   0.25  | Default radius of a circle
ellipseht      |   0.5   | Default height of an ellipse
ellipsewid     |   0.75  | Default width of an ellipse
moveht         |   0.5   | Default length of vertical move
movewid        |   0.75  | Default length of horizontal move
textht         |   0     | Default height of box enclosing a text object
textwid        |   0     | Default width of box enclosing a text object
arrowht        |   0.1   | Length of arrowhead along shaft
arrowwid       |   0.05  | Width of rear of arrowhead
arrowhead      |   1     | Enable/disable arrowhead filling
dashwid        |   0.05  | Interval for dashed lines
maxpswid       |  11     | Maximum width of picture
maxpsht        |   8.5   | Maximum height of picture
scale          |   1     | Unit scale factor
fillval        |   0.5   | Default fill value
---------------+---------+-----------------------------------------------










                            -26-


Any of these variables can be set with a  simple  assignment
statement.  For example:









Figure  12-1:  bbooxxhhtt==11;;  bbooxxwwiidd==00..33;; mmoovveewwiidd==00..22;; bbooxx;; mmoovvee;;
                 bbooxx;; mmoovvee;; bbooxx;; mmoovvee;; bbooxx;;


     In GNU ppiicc, setting the ssccaallee  variable  re-scales  all
size-related  state  variables  so  that their values remain
equivalent in the new units.

     The command rreesseett resets all style variables  to  their
defaults.  You can give it a list of variable names as argu-
ments (optionally separated by commas),  in  which  case  it
resets only those.

     State  variables  retain  their  values across pictures
until reset.

1133..  EExxpprreessssiioonnss,, VVaarriiaabblleess,, aanndd AAssssiiggnnmmeenntt

     A number is a valid expression, of course (all  numbers
are  stored  internally  as  floating-point).  Decimal-point
notation is acceptable; in GNU ggppiicc, scientific notation  in
C's `e' format (like 5e-2) is accepted.

     Anywhere  a  number is expected, the language will also
accept a variable.  Variables  may  be  the  built-in  style
variable  described  in  the  last section, or new variables
created by assignment.

     DWB ppiicc supports only the ordinary  assignment  via  ==,
which  defines  the  variable (on the left side of the equal
sign) in the current block if  it  is  not  already  defined
there, and then changes the value (on the right side) in the
current block.  The variable is not visible outside  of  the
block.   This is similar to the C programming language where
a variable within a block shadows a variable with  the  same
name outside of the block.

     GNU ggppiicc supports an alternate form of assignment using
::==.  The variable must already be  defined,  and  the  value
will  be  assigned to that variable without creating a vari-
able local to the current block.  For example, this











                            -27-


     x=5
     y=5
     [
       x:=3
       y=3
     ]
     print x " " y


prints 33 55.

     You can use the height, width,  radius,  and  x  and  y
coordinates of any object or corner in expressions.  If AA is
an object label or name, all the following are valid:

     A.x                  # x coordinate of the center of A
     A.ne.y               # y coordinate of the northeast corner of A
     A.wid                # the width of A
     A.ht                 # and its height
     2nd last circle.rad  # the radius of the 2nd last circle


Note the second expression, showing how to extract a  corner
coordinate.

     Basic  arithmetic  resembling  those of C operators are
available; ++, **, --, //, and %%.  So is ^^  for  exponentiation.
Grouping  is  permitted  in the usual way using parentheses.
GNU ggppiicc allows logical operators to appear in  expressions;
!! (logical negation, not factorial), &&&&, ||||, ====, !!==, >>==, <<==,
<<, >>.

     Various  built-in  functions  are  supported:   ssiinn((_x)),
ccooss((_x)),   lloogg((_x)),  eexxpp((_x)),  ssqqrrtt((_x)),  mmaaxx((_x,,_y)),  aattaann22((_x,,_y)),
mmiinn((_x,,_y)), iinntt((_x)), rraanndd(()), and ssrraanndd(()).  Both eexxpp and lloogg are
base  10; iinntt does integer truncation; rraanndd(()) returns a ran-
dom number in [0-1), and ssrraanndd(()) sets the  seed  for  a  new
sequence  of  pseudo-random numbers to be returned by rraanndd(())
(ssrraanndd(()) is a GNU extension).

     GNU ggppiicc also documents a one-argument  form  or  rand,
rraanndd((_x)),  which returns a random number between 1 and _x, but
this is deprecated and may be removed in a future version.

     The function sspprriinnttff(())  behaves  like  a  C  _s_p_r_i_n_t_f(3)
function that only takes %, %e, %f, and %g format strings.

1144..  MMaaccrrooss

     You  can define macros in ppiicc.  This is useful for dia-
grams with repetitive parts.  In conjunction with the  scope
rules  for  block  composites,  it effectively gives you the
ability to write functions.










                            -28-


     The syntax is

     ddeeffiinnee _n_a_m_e {{ _r_e_p_l_a_c_e_m_e_n_t _t_e_x_t }}


This defines _n_a_m_e as a macro to be replaced by the  replace-
ment  text  (not  including  the  braces).  The macro may be
called as

     _n_a_m_e((_a_r_g_1_, _a_r_g_2_, _._._. _a_r_g_n))


The arguments (if any) will be substituted for tokens $$11, $$22
... $$nn appearing in the replacement text.

     As an example of macro use, consider this:















































                            -29-


     .PS
     # Plot a single jumper in a box, $1 is the on-off state.
     define jumper { [
         shrinkfactor = 0.8;
         Outer: box invis wid 0.45 ht 1;

         # Count on end ] to reset these
         boxwid = Outer.wid * shrinkfactor / 2;
         boxht  = Outer.ht  * shrinkfactor / 2;

         box fill (!$1) with .s at center of Outer;
         box fill ($1)  with .n at center of Outer;
     ] }

     # Plot a block of six jumpers.
     define jumperblock {
         jumper($1);
         jumper($2);
         jumper($3);
         jumper($4);
         jumper($5);
         jumper($6);

         jwidth  = last [].Outer.wid;
         jheight = last [].Outer.ht;

         box with .nw at 6th last [].nw wid 6*jwidth ht jheight;

         # Use {} to avoid changing position from last box draw.
         # This is necessary so move in any direction will work as expected
         {"Jumpers in state $1$2$3$4$5$6" at last box .s + (0, -0.2);}
     }

     # Sample macro invocations.
     jumperblock(1,1,0,0,1,0);
     move;
     jumperblock(1,0,1,0,1,1);
     .PE


It yields the following:

  






    Jumpers in state 110010      Jumpers in state 101011

             Figure 14-1: Sample use of a macro











                            -30-


This macro example illustrates how you can combine [], brace
grouping, and variable assignment to write true functions.

     One detail the example above does not illustrate is the
fact  that macro argument parsing is not token-oriented.  If
you call jjuummppeerr(( 11 )), the value of $1 will  be  "" 11 "".   You
could  even  call  jjuummppeerr((bbiigg ssttrriinngg))  to  give $1 the value
""bbiigg ssttrriinngg"".

     If you want to pass in a coordinate pair, you can avoid
getting  tripped  up  by  the  comma by wrapping the pair in
parentheses.

     Macros persist through pictures.  To undefine a  macro,
say uunnddeeff _n_a_m_e; for example,

     undef jumper
     undef jumperblock


would undefine the two macros in the jumper block example.

1155..  IImmppoorrtt//EExxppoorrtt CCoommmmaannddss

     Commands that import or export data between ppiicc and its
environment are described here.

1155..11..  FFiillee aanndd TTaabbllee IInnsseerrttiioonn

     The statement

     copy _f_i_l_e_n_a_m_e


inserts the contents of _f_i_l_e_n_a_m_e in the  ppiicc  input  stream.
Any ..PPSS/..PPEE pair in the file will be ignored.  This, you can
use this to include pre-generated images.

     A variant of this statement replicates  the  ccooppyy  tthhrruu
feature of _g_r_a_p(1).  The call

     copy _f_i_l_e_n_a_m_e thru _m_a_c_r_o


calls _m_a_c_r_o (which may be either a name or replacement text)
on the arguments obtained by breaking each line of the  file
into  blank-separated  fields.   The  macro  may  have up to
9 arguments.  The  replacement  text  may  be  delimited  by
braces  or  by  a  pair  of  instances  of any character not
appearing in the rest of the text.

     If you write











                            -31-


     copy thru _m_a_c_r_o


omitting the filename, lines to be parsed are taken from the
input source up to the next ..PPEE.

     In  either of the last two ccooppyy commands, GNU ggppiicc per-
mits a trailing `uunnttiill _w_o_r_d' clause to be added which termi-
nates the copy when the first word matches the argument (the
default behavior is therefore equivalent to uunnttiill ..PPEE).

     Accordingly, the command

          .PS
          copy thru % circle at ($1,$2) % until "END"
          1 2
          3 4
          5 6
          END
          box
          .PE

is equivalent to

          .PS
          circle at (1,2)
          circle at (3,4)
          circle at (5,6)
          box
          .PE

1155..22..  DDeebbuugg MMeessssaaggeess

     The command pprriinntt accepts any number of arguments, con-
catenates their output forms, and writes the result to stan-
dard error.  Each argument must be an  expression,  a  posi-
tion, or a text string.

1155..33..  EEssccaappee ttoo PPoosstt--PPrroocceessssoorr

     If you write

     ccoommmmaanndd _a_r_g...


ppiicc  concatenates  the  arguments and pass them through as a
line to troff or TeX.  Each _a_r_g must  be  an  expression,  a
position,  or  text.   This  has  a similar effect to a line
beginning with ..  or \\, but allows the values  of  variables
to be passed through.













                            -32-


1155..44..  EExxeeccuuttiinngg SShheellll CCoommmmaannddss

     The command

     sh { _a_n_y_t_h_i_n_g_._._. }


macro-expands  the  text  in  braces,  then executes it as a
shell command.  This could be used  to  generate  images  or
data tables for later inclusion.  The delimiters shown as {}
here may also be two copies of any one character not present
in  the  shell  command  text.  In either case, the body may
contain balanced {} pairs.  Strings in the body may  contain
balanced or unbalanced braces in any case.

1166..  CCoonnttrrooll--ffllooww ccoonnssttrruuccttss

     The  ppiicc  language  provides  conditionals and looping.
For example,

     pi = atan2(0, -1);
     for i = 0 to 2 * pi by 0.1 do {
         "-" at (i/2, 0);
         "." at (i/2, sin(i)/2);
         ":" at (i/2, cos(i)/2);
     }


which yields this:

              ::::::  ..........                  :::::
                .:.:.:.:.:     .....             :::::
               ...  :::     ....         :::
              -.-.-.------------:-:-:-:-------------.-.-.--------------:-:-:-:-------------.
                      :::      ....   :::     ....
                        ::::      ..:.:.:::     ....
                          ::::::::::::: .............

           Figure 16-1: Plotting with a ffoorr loop


The syntax of the ffoorr statement is:

     ffoorr _v_a_r_i_a_b_l_e == _e_x_p_r_1 ttoo _e_x_p_r_2 [bbyy [**]_e_x_p_r_3] ddoo _X _b_o_d_y _X

The semantics are as follows:  Set _v_a_r_i_a_b_l_e to _e_x_p_r_1.  While
the  value  of  _v_a_r_i_a_b_l_e  is less than or equal to _e_x_p_r_2, do
_b_o_d_y and increment _v_a_r_i_a_b_l_e by _e_x_p_r_3; if bbyy  is  not  given,
increment  _v_a_r_i_a_b_l_e  by  1.   If _e_x_p_r_3 is prefixed by ** then
_v_a_r_i_a_b_l_e will instead be multiplied by _e_x_p_r_3.  _X can be  any
character not occurring in _b_o_d_y; or the two _Xs may be paired
braces (as in the sshh command).











                            -33-


     The syntax of the iiff statement is as follows:

     iiff _e_x_p_r tthheenn _X _i_f_-_t_r_u_e _X [eellssee _Y _i_f_-_f_a_l_s_e _Y]

Its semantics are as follows: Evaluate _e_x_p_r; if it  is  non-
zero  then  do _i_f_-_t_r_u_e, otherwise do _i_f_-_f_a_l_s_e.  _X can be any
character not occurring in _i_f_-_t_r_u_e.  _Y can be any  character
not occurring in _i_f_-_f_a_l_s_e.

     Eithe  or  both of the _X or _Y pairs may instead be bal-
anced pairs of braces ({ and }) as in the  sshh  command.   In
either  case,  the  _i_f_-_t_r_u_e  may  contain  balanced pairs of
braces.  None  of  these  delimiters  will  be  seen  inside
strings.

     All the usual relational operators my be used in condi-
tional expressions; !! (logical negation, not factorial), &&&&,
||||, ====, !!==, >>==, <<==, <<, >>.

     String  comparison  is  also supported using ==== and !!==.
String comparisons may need to  be  parenthesized  to  avoid
syntactic ambiguities.

1177..  IInntteerrffaaccee TToo [[ggtt]]rrooffff

     The  output  of  ppiicc is [[ggtt]]rrooffff drawing commands.  The
GNU _g_p_i_c(1) command warns that it relies on  drawing  exten-
sions  present in _g_r_o_f_f(1) that are not present in _t_r_o_f_f(1).

1177..11..  SSccaalliinngg AArrgguummeennttss

     The DWB _p_i_c(1) program will accept one or two arguments
to ..PPSS, which is interpreted as a width and height in inches
to which the results of _p_i_c(1) should be scaled  (width  and
height scale independently).  If there is only one argument,
it is interpreted as a width to scale the  picture  to,  and
height will be scaled by the same proportion.

     GNU ggppiicc is less general; it will accept a single width
to scale to, or a zero width and a maximum height  to  scale
to.  With two non-zero arguments, it will scale to the maxi-
mum height.

1177..22..  HHooww SSccaalliinngg iiss HHaannddlleedd

     When ppiicc processes a picture description on  input,  it
passes  ..PPSS  and  ..PPEE through to the postprocessor.  The ..PPSS
gets decorated with two numeric arguments which  are  the  X
and Y dimensions of the picture in inches.  The post-proces-
sor can use these to reserve space for the picture and  cen-
ter it.

     The  GNU incarnation of the mmss macro package, for exam-
ple, includes the following definitions:









                            -34-


     .de PS
     .br
     .sp \\n[DD]u
     .ie \\n[.$]<2 .@error bad arguments to PS (not preprocessed with pic?)
     .el \{\
     .    ds@need (u;\\$1)+1v
     .    in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0)
     .\}
     ..
     .de PE
     .par@reset
     .sp \\n[DD]u+.5m
     ..


Equivalent definition will be supplied by GNU _p_i_c(1) if  you
use  the -mpic option; this should make it usable with macro
pages other than _m_s(1).

     If ..PPFF is used instead of ..PPEE, the  ttrrooffff  position  is
restored  to  what  it  was  at the picture start (Kernighan
notes that the F stands for "flyback").

     The invocation

     ..PPSS <<_f_i_l_e


causes the contents of _f_i_l_e to replace the ..PPSS  line.   This
feature is deprecated; use `ccooppyy _f_i_l_e' instead).

     By  default,  input  lines that begin with a period are
passed to the postprocessor, embedded at  the  corresponding
point  in  the  output.  Messing with horizontal or vertical
spacing is an obvious recipe for bugs, but  point  size  and
font changes will usually be safe.

     Point  sizes and font changes are also safe within text
strings, as long as  they  are  undone  before  the  end  of
string.

     The  state  of [[ggtt]]rrooffff's fill mode is preserved across
pictures.

     The Kernighan paper notes that there is a subtle  prob-
lem  with  complicated  equations  inside ppiicc pictures; they
come out wrong if _e_q_n(1) has to leave extra  vertical  space
for  the equation.  If your equation involves more than sub-
scripts and superscripts, you must add to the  beginning  of
each  equation  the extra information ssppaaccee 00.  He gives the
following example:












                            -35-


     arrow
     box "$space 0 {H( omega )} over {1 - H( omega )}$"
     arrow



                     
                     ------      ------
                           1___H-__(_H__)(__)__


           Figure 17-1: Equations within pictures


1188..  IInntteerrffaaccee ttoo TTeeXX


     TeX mode is enabled by the --tt option.  In TeX mode, pic
will define a vbox called \\ggrraapphh for each picture.  You must
yourself print that vbox using, for example, the command

     \centerline{\box\graph}

Actually, since the vbox has a height of zero this will pro-
duce  slightly  more  vertical  space above the picture than
below it;

     \centerline{\raise 1em\box\graph}

would avoid this.

     You must use a TeX driver that supports the  ttppiicc  spe-
cials, version 2.

     Lines  beginning  with  \\  are passed through transpar-
ently; a %% is added to the end of the line to avoid unwanted
spaces.   You can safely use this feature to change fonts or
to change the value of  \\bbaasseelliinneesskkiipp.   Anything  else  may
well  produce  undesirable  results;  use  at your own risk.
Lines beginning with a period  are  not  given  any  special
treatment.

     The  TeX  mode  of _p_i_c(1) will _n_o_t translate ttrrooffff font
and size changes included in text strings!

1199..  OObbssoolleettee CCoommmmaannddss

     GNU _g_p_i_c(1)  has a command

     pplloott _e_x_p_r [""_t_e_x_t""]

This is a text object which is constructed by using _t_e_x_t  as
a  format  string  for sprintf with an argument of _e_x_p_r.  If
_t_e_x_t is omitted a format string of ""%%gg"" is used.  Attributes









                            -36-


can  be  specified  in  the  same  way  as for a normal text
object.  Be very careful that  you  specify  an  appropriate
format  string;  ppiicc  does only very limited checking of the
string.  This is deprecated in favour of sspprriinnttff.

2200..  SSoommee LLaarrggeerr EExxaammpplleess

     Here are a few larger examples,  with  complete  source
code.   One  of  our  earlier  examples  is  generated in an
instructive way using a for loop:

     .PS
     # Draw a demonstration up left arrow with grid box overlay
     define gridarrow
     {
         move right 0.1
         [
             {arrow up left $1;}
             box wid 0.5 ht 0.5 dotted with .nw at last arrow .end;
             for i = 2 to ($1 / 0.5) do
             {
                 box wid 0.5 ht 0.5 dotted with .sw at last box .se;
             }
             move down from last arrow .center;
             [
                 if ( $1 == boxht ) \
                 then { "\fBline up left\fP" } \
                 else { sprintf("\fBarrow up left %g\fP", $1) };
             ]
         ]
         move right 0.1 from last [] .e;
     }
     gridarrow(0.5);
     gridarrow(1);
     gridarrow(1.5);
     gridarrow(2);
     undef gridarrow
     .PE


  ++++++ +++++++++++ ++++++++++++++++ +++++++++++++++++++++
  +    + +    +    + +    +    +    + +    +    +    +    +
  +    + +    +    + +    +    +    + +    +    +    +    +
  ++++++ +++++++++++ ++++++++++++++++ +++++++++++++++++++++

lliinnee uuppaallrreerrffoottww uupp lleefftt 11aarrrrooww uupp lleefftt 11..55   aarrrrooww uupp lleefftt 22
Figure 20-1: Diagonal arrows (dotted boxes show the  implied
                       0.5-inch grid)


     Here's  an example concocted to demonstrate layout of a
large, multiple-part pattern:











                            -37-


     .PS
     define filter {box ht 0.25 rad 0.125}
     lineht = 0.25;
     Top: [
         right;
         box "\fBms\fR" "sources";
         move;
         box "\fBHTML\fR" "sources";
         move;
         box "\fBlinuxdoc-sgml\fP" "sources" wid 1.5;
         move;
         box "\fBTexinfo\fP" "sources";

         line down from 1st box .s lineht;
         A: line down;
         line down from 2nd box .s; filter "\fBhtml2ms\fP";
         B: line down;
         line down from 3rd box .s; filter "\fBformat\fP";
         C: line down;
         line down from 4th box .s; filter "\fBtexi2roff\fP";
         D: line down;
     ]
     move down 1 from last [] .s;
     Anchor: box wid 1 ht 0.75 "\fBms\fR" "intermediate" "form";
     arrow from Top.A.end to Anchor.nw;
     arrow from Top.B.end to 1/3 of the way between Anchor.nw and Anchor.ne;
     arrow from Top.C.end to 2/3 of the way between Anchor.nw and Anchor.ne;
     arrow from Top.D.end to Anchor.ne
     {
         # PostScript column
         move to Anchor .sw;
         line down left then down ->;
         filter "\fBpic\fP";
         arrow;
         filter "\fBeqn\fP";
         arrow;
         filter "\fBtbl\fP";
         arrow;
         filter "\fBgroff\fP";
         arrow;
         box "PostScript";

         # HTML column
         move to Anchor .se;
         line down right then down ->;
         A: filter dotted "\fBpic2img\fP";
         arrow;
         B: filter dotted "\fBeqn2html\fP";
         arrow;
         C: filter dotted "\fBtbl2html\fP";
         arrow;
         filter "\fBms2html\fP";
         arrow;
         box "HTML";









                            -38-


         # Nonexistence caption
         box dashed wid 1 at B + (2, 0) "These tools" "don't yet exist";
         line chop 0 chop 0.1 dashed from last box .nw to A.e ->;
         line chop 0 chop 0.1 dashed from last box .w  to B.e ->;
         line chop 0 chop 0.1 dashed from last box .sw to C.e ->;
     }
     .PE



   mmss         HHTTMMLL        lliinnuuxxddoocc--ssggmmll      TTeexxiinnffoo
sources      sources         sources         sources
    |           |               |                |
    |         --+---          --+---          ---+--
    |       +hhttmmll22mmss+        +ffoorrmmaatt +       tt+eexxii22rrooff+ff
    |         --+---          --+---          ---+--
    |           |               |                |







                         mmss
                    intermediate
                        form

                |                   |
                |                   |
              ------             ++++++++
            + --pp+ii-cc--+           ++pp+ii+cc+22+ii+mm+gg++++++
                |                   |         ++++++++++++++++
              ------             ++++++++          +These tool+s
            + --ee+qq-nn--+           +ee+qq+nn+22+hh+tt+mm+ll++++++++++d+o+n't yet ex+ist
                |                   |            ++++++++ ++++
              ------             ++++++++ +++++++
            + --tt+bb-ll--+           +tt+bb+ll+22+hh+tt+mm+ll++
                |                   |
              ------              ------
            + -gg-rr+oo-ff-ff-+           +mm-ss-22+hh-tt-mm-ll+
                |                   |


           PostScript             HTML


Figure 20-2: Hypothetical production flow for dual-mode publishing















                            -39-


2211..  PPIICC RReeffeerreennccee

     This is an annotated grammar of ppiicc.

2211..11..  LLeexxiiccaall IItteemmss

     In general, ppiicc is a free-format,  token-oriented  lan-
guage  that ignores whitespace outside strings.  But certain
lines and contructs are specially interpreted at the lexical
level:

     A  comment  begins with ## and continues to \\nn (comments
may also follow text in a line).  A line  beginning  with  a
period  or backslash may be interpreted as text to be passed
through to the  post-processor,  depending  on  command-line
options.   An  end-of-line  backslash  is  interpreted  as a
request to continue the line; the  backslash  and  following
newline are ignored.

     Here are the grammar terminals:

     INT  A positive integer.

     NUMBER
          A  floating point numeric constant.  May contain a
          decimal point or be expressed in scientific  nota-
          tion  in  the  style  of _p_r_i_n_t_f(3)'s %e escape.  A
          trailing `i' or `I' (indicating the  unit  `inch')
          is ignored.

     TEXT A  string  enclosed  in  double  quotes.  A double
          quote within TEXT must be preceded by a backslash.
          Instead of TEXT you can use

               sprintf ( TEXT [, <expr> ...] )


          except  after the `until' and `last' keywords, and
          after all ordinal keywords (`th' and friends).

     VARIABLE
          A string starting with a character  from  the  set
          [a-z],  optionally followed by one or more charac-
          ters of the set [a-zA-Z0-9_].   (Values  of  vari-
          ables are preserved across pictures.)

     LABEL
          A  string  starting  with a character from the set
          [A-Z], optionally followed by one or more  charac-
          ters of the set [a-zA-Z0-9_].

     COMMAND-LINE
          A  line  starting with a command character (`.' in
          groff mode, `\' in TeX mode).









                            -40-


     BALANCED-TEXT
          A string either enclosed by `{' and `}' or with  _X
          and _X, where _X doesn't occur in the string.

     BALANCED-BODY
          Delimiters  as  in BALANCED-TEXT; the body will be
          interpreted as `<<ccoommmmaanndd>>......'.

     FILENAME
          The name of a file.  This has the  same  semantics
          as TEXT.

     MACRONAME
          Either VARIABLE or LABEL.

2211..22..  SSeemmii--FFoorrmmaall GGrraammmmaarr

     Tokens not enclosed in <> are literals, except:

1.   \\nn is a newline.

2.   Three  dots is a suffix meaning `replace with 0 or more
     repetitions of the preceding element(s).

3.   An enclosure in square brackets has its  usual  meaning
     of `this clause is optional'.

4.   Square-bracket-enclosed   portions  within  tokens  are
     optional.  Thus, `h[eigh]t' matches either `height'  or
     `ht'.

If  one of these special tokens has to be referred to liter-
ally, it is surrounded with single quotes.

     The top-level ppiicc object is a picture.

     <picture> ::=
       .PS [NUMBER [NUMBER]]\n
       <statement> ...
       .PE \n


     The arguments, if  present,  represent  the  width  and
height of the picture, causing ppiicc to attempt to scale it to
the given dimensions in inches.  In no case,  however,  will
the  X  and Y dimensions of the picture exceed the values of
the style variables mmaaxxppsswwiidd and mmaaxxppsshheeiigghhtt (which  default
to the normal 8.5i by 11i page size).

     If the ending `.PE' is replaced by `.PF', the page ver-
tical position is restored to its value at  the  time  `.PS'
was  encountered.   Another  alternate form of invocation is
`.PS <FILENAME', which replaces the `.PS' line with  a  file
to be interpreted by ppiicc (but this feature is deprecated).









                            -41-


     The `.PS', `.PE', and `.PF' macros to perform centering
and scaling are normally supplied by the post-processor.

     In the following, either `|' or a new  line  starts  an
alternative.

     <statement> ::=
       <command> ;
       <command> \n


     <command> ::=
       <primitive> [<attribute>]
       LABEL : [;] <command>
       LABEL : [;] <command> [<position>]
       { <command> ... }
       VARIABLE [:] = <any-expr>
       up | down | left | right
       COMMAND-LINE
       command <print-arg> ...
       print <print-arg> ...
       sh BALANCED-TEXT
       copy FILENAME
       copy [FILENAME] thru MACRONAME [until TEXT]
       copy [FILENAME] thru BALANCED-BODY [until TEXT]
       for VARIABLE = <expr> to <expr> [by [*] <expr>] do BALANCED-BODY
       if <any-expr> then BALANCED-BODY [else BALANCED-BODY]
       reset [VARIABLE [[,] VARIABLE ...]]


     <print-arg> ::=
       TEXT
       <expr>
       <position>


     The  current  position and direction are saved on entry
to a `{ ... }' construction and restored on exit from it.

     Note that in  `if'  constructions,  newlines  can  only
occur in BALANCED-BODY.  This means that

     if
     { ... }
     else
     { ... }


     will fail.  You have to use the braces on the same line
as the keywords:













                            -42-


     if {
     ...
     } else {
     ...
     }


     This restriction doesn't hold for the  body  after  the
`do' in a `for' construction.

     <any-expr> ::=
       <expr>
       <text-expr>
       <any-expr> <logical-op> <any-expr>
       ! <any-expr>


     <logical-op> ::=
       == | != | && | '||'


     <text-expr> ::=
       TEXT == TEXT
       TEXT != TEXT


     Logical  operators  are  handled specially by ppiicc since
they can deal with text strings also.  ppiicc uses _s_t_r_c_m_p(3) to
test  for equality of strings; an empty string is considered
as `false' for `&&' and `||'.

     <primitive> ::=
       box                   # closed object -- rectangle
       circle                # closed object -- circle
       ellipse               # closed object -- ellipse
       arc                   # open object -- quarter-circle
       line                  # open object -- line
       arrow                 # open object -- line with arrowhead
       spline                # open object -- spline curve
       move
       TEXT TEXT ...         # text within invisible box
       plot <expr> TEXT      # formatted text
       '[' <command> ... ']'


     Drawn objects within `[ ... ]' are treated as a  single
composite  object  with  a  rectangular  shape  (that of the
bounding box of  all  the  elements).   Variable  and  label
assignments  within a block are local to the block.  Current
direction of motion is restored to the  value  at  start  of
block  upon  exit.  Position is _n_o_t restored (unlike `{ }');
instead, the current position becomes the exit position  for
the current direction on the block's bounding box.










                            -43-


     <attribute> ::=
       h[eigh]t <expr>       # set height of closed figure
       wid[th] <expr>        # set width of closed figure
       rad[ius] <expr>       # set radius of circle/arc
       diam[eter] <expr>     # set diameter of circle/arc
       up [<expr>]           # move up
       down [<expr>]         # move down
       left [<expr>]         # move left
       right [<expr>]        # move right
       from <position>       # set from position of open figure
       to <position>         # set to position of open figure
       at <position>         # set center of open figure
       with <path>           # fix corner/named point at specified location
       with <position>       # fix position of object at specified location
       by <expr-pair>        # set object's attachment point
       then                  # sequential segment composition
       dotted [<expr>]       # set dotted line style
       dashed [<expr>]       # set dashed line style
       thick[ness] <expr>    # set thickness of lines
       chop [<expr>]         # chop end(s) of segment
       '->' | '<-' | '<->'   # decorate with arrows
       invis[ible]           # make primitive invisible
       solid                 # make closed figure solid
       fill[ed] [<expr>]     # set fill density for figure
       colo[u]r[ed] TEXT     # set fill and outline color for figure
       outline[d] TEXT       # set outline color for figure
       shaded TEXT           # set fill color for figure
       same                  # copy size of previous object
       cw | ccw              # set orientation of curves
       ljust | rjust         # adjust text horizontally
       above | below         # adjust text vertically
       aligned               # align parallel to object
       TEXT TEXT ...         # text within object
       <expr>                # motion in the current direction


     Missing attributes are supplied from defaults; inappro-
priate ones are silently ignored.  For lines,  splines,  and
arcs, height and width refer to arrowhead size.

     The  `at'  primitive  sets  the  center  of the current
object.  The `with' attribute fixes the specified feature of
the given object to a specified location.  (Note that `with'
is incorrectly described in the Kernighan paper.)

     The `by' primitive is not documented  in  the  tutorial
portion  of the Kernighan paper, and should probably be con-
sidered unreliable.

     The primitive `arrow' is a synonym for `line ->'.

     Text is normally an attribute of some object, in  which
case  successive strings are vertically stacked and centered
on the object's  center  by  default.   Standalone  text  is









                            -44-


treated as though placed in an invisible box.

     A text item consists of a string or sprintf-expression,
optionally followed by positioning  information.   Text  (or
strings  specified with `sprintf' may contain [gtn]roff font
changes, size changes, and  local  motions,  provided  those
changes are undone before the end of the current item.

     A position is an (x,y) coordinate pair.  There are lots
of different ways to specify positions:

     <position> ::=
       <position-not-place>
       <place>


     <position-not-place> ::=
       <expr-pair>
       <position> + <expr-pair>
       <position> - <expr-pair>
       ( <position> , <position> )
       <expr> [of the way] between <position> and <position>
       <expr> '<' <position> , <position> '>'


     <expr-pair> ::=
       <expr> , <expr>
       ( expr-pair )


     <place> ::=
       <label>
       <label> <corner>
       <corner> [of] <label>
       Here


     <label> ::=
       LABEL [. LABEL ...]
       <nth-primitive>


     <corner> ::=
       .n | .e | .w | .s
       .ne | .se | .nw | .sw
       .c[enter] | .start | .end
       .t[op] | .b[ot[tom]] | .l[eft] | .r[ight]
       left | right | <top-of> | <bottom-of>
       <north-of> | <south-of> | <east-of> | <west-of>
       <center-of> | <start-of> | <end-of>
       upper left | lower left | upper right | lower right












                            -45-


     <xxx-of> ::=
       xxx                   # followed by `of'


     <nth-primitive> ::=
       <ordinal> <object-type>
       [<ordinal>] last <object-type>


     <ordinal> ::=
       INT th
       INT st | INT nd | INT rd
       ` <any-expr> 'th


     <object-type> ::=
       box
       circle
       ellipse
       arc
       line
       arrow
       spline
       '[]'
       TEXT


     As Kernighan notes, "since barbarisms like 11tthh and  33tthh
are  barbaric,  synonyms  like  11sstt  and 33rrdd are accepted as
well."  Objects of a given type are numbered from 1  upwards
in order of declaration; the llaasstt modifier counts backwards.

     The "'th" form (which allows you to select  a  previous
object  with an expression, as opposed to a numeric literal)
is not documented in DWB's _p_i_c(1).

     The <_x_x_x-of> rule is special: The lexical parser checks
whether  _x_x_x is followed by the token `of' without eliminat-
ing it so that the grammar parser can still see `of'.  Valid
examples  of  specifying  a  place with corner and label are
thus

     A .n
     .n of A
     .n A
     north of A


while

     north A
     A north

both cause a syntax error.  (DWB ppiicc also allows  the  weird









                            -46-


form `A north of'.)

     Here  the  special rules for the `with' keyword using a
path:

     <path> ::=
       <relative-path>
       ( <relative-path> , <relative-path> )


     <relative-path> ::=
       <corner>
       . LABEL [. LABEL ...] [<corner>]


     The following style variables control output:
               |         |
SSttyyllee VVaarriiaabbllee | DDeeffaauulltt | WWhhaatt IItt DDooeess
---------------+---------+-----------------------------------------------
boxht          |   0.5   | Default height of a box
boxwid         |   0.75  | Default height of a box
lineht         |   0.5   | Default length of vertical line
linewid        |   0.75  | Default length of horizontal line
arcrad         |   0.25  | Default radius of an arc
circlerad      |   0.25  | Default radius of a circle
ellipseht      |   0.5   | Default height of an ellipse
ellipsewid     |   0.75  | Default width of an ellipse
moveht         |   0.5   | Default length of vertical move
movewid        |   0.75  | Default length of horizontal move
textht         |   0     | Default height of box enclosing a text object
textwid        |   0     | Default width of box enclosing a text object
arrowht        |   0.1   | Length of arrowhead along shaft
arrowwid       |   0.05  | Width of rear of arrowhead
arrowhead      |   1     | Enable/disable arrowhead filling
dashwid        |   0.05  | Interval for dashed lines
maxpswid       |  11     | Maximum width of picture
maxpsht        |   8.5   | Maximum height of picture
scale          |   1     | Unit scale factor
fillval        |   0.5   | Default fill value
---------------+---------+-----------------------------------------------

Any of these can be set by assignment, or  reset  using  the
rreesseett  statement.   Style  variables  assigned  within `[ ]'
blocks are restored to  their  beginning-of-block  value  on
exit; top-level assignments persist across pictures.  Dimen-
sions are divided by ssccaallee on output.

     All ppiicc expressions are evaluated  in  floating  point;
units  are always inches (a trailing `i' or `I' is ignored).
Expressions have the following simple grammar,  with  seman-
tics very similar to C expressions:












                            -47-


     <expr> ::=
       VARIABLE
       NUMBER
       <place> <place-attribute>
       <expr> <op> <expr>
       - <expr>
       ( <any-expr> )
       ! <expr>
       <func1> ( <any-expr> )
       <func2> ( <any-expr> , <any-expr> )
       rand ( )


     <place-attribute>
      .x | .y | .h[eigh]t | .wid[th] | .rad


     <op> ::=
       + | - | * | / | % | ^ | '<' | '>' | '<=' | '>='


     <func1> ::=
       sin | cos | log | exp | sqrt | int | rand | srand


     <func2> ::=
       atan2 | max | min


Both  eexxpp  and lloogg are base 10; iinntt does integer truncation;
and rraanndd(()) returns a random number in [0-1).

     There are ddeeffiinnee and uunnddeeff  statements  which  are  not
part  of the grammar (they behave as pre-processor macros to
the language).  These may be  used  to  define  pseudo-func-
tions.

     ddeeffiinnee _n_a_m_e {{ _r_e_p_l_a_c_e_m_e_n_t_-_t_e_x_t }}


This  defines _n_a_m_e as a macro to be replaced by the replace-
ment text (not including the  braces).   The  macro  may  be
called as

     _n_a_m_e((_a_r_g_1_, _a_r_g_2_, _._._._, _a_r_g_n))


The arguments (if any) will be substituted for tokens $1, $2
... $n appearing in the replacement  text.   To  undefine  a
macro,  say uunnddeeff _n_a_m_e, specifying the name to be undefined.













                            -48-


2222..  HHiissttoorryy aanndd AAcckknnoowwlleeddggeemmeennttss

     Original ppiicc was written to go  with  Joseph  Ossanna's
original  _t_r_o_f_f(1)  by Brian Kernighan, and later re-written
by Kernighan with substantial  enhancements  (apparently  as
part  of the evolution of _t_r_o_f_f(1) into _d_i_t_r_o_f_f(1) to gener-
ate device-independent output).

     The language had been inspired by some earlier graphics
languages including iiddeeaall and ggrraapp.  Kernighan credits Chris
van Wyk (the designer of iiddeeaall) with many of the ideas  that
went into ppiicc.

     The  ppiicc  language  was  originally  described by Brian
Kernighan in Bell Labs Computing  Science  Technical  Report
#116  (you  can obtain a PostScript copy of the revised ver-
sion,    [1],    by    sending    a    mail    message    to
_n_e_t_l_i_b_@_r_e_s_e_a_r_c_h_._a_t_t_._c_o_m  with  a  body  of  `send  116  from
research/cstr').  There have been two revisions, in 1984 and
1991.

     The  document  you  are  reading  effectively  subsumes
Kernighan's description; it was written to fill  in  lacunae
in  the  exposition and integrate in descriptions of the GNU
_g_p_i_c(1) features.

     The GNU ggppiicc implementation was written by James  Clark
<_j_j_c_@_j_c_l_a_r_k_._c_o_m>.  It is currently maintained by Werner Lem-
berg <_w_l_@_g_n_u_._o_r_g>.

2233..  BBiibblliiooggrraapphhyy

1.   Kernighan, B. W.  PPIICC ---- AA GGrraapphhiiccss LLaanngguuaaggee ffoorr  TTyyppee--
     sseettttiinngg  ((RReevviisseedd  UUsseerr  MMaannuuaall)).   Bell Labs Computing
     Science Technical Report #116, December 1991.

2.   Van Wyk, C. J.  AA hhiigghh--lleevveell  llaanngguuaaggee  ffoorr  ssppeecciiffyyiinngg
     ppiiccttuurreess.   _A_C_M  _T_r_a_n_s_a_c_t_i_o_n_s  _O_n  _G_r_a_p_h_i_c_s  1,2 (1982)
     163-182.





















