

            














                        UUUssseeerrr'''sss GGGuuuiiidddeee fffooorrr ttthhheee RRRaaatttfffooorrr PPPrrreeeppprrroooccceeessssssooorrr
                                            
                                     SSSeeecccooonnnddd EEEdddiiitttiiiooonnn












                                      T. Allen Akin
                                  Terrell L. Countryman
                                     Perry B. Flinn
                                 Daniel H. Forsyth, Jr.
                                    Jeanette T. Myers
          |                         Arnold D. Robbins
                                      Peter N. Wan












          |            School of Information and Computer Science
          |                  Georgia Institute of Technology
          |                      Atlanta, Georgia  30332


          |                            July, 1984






            




            


                                        FFFooorrreeewwwooorrrddd


                 Ratfor  ("Rational  Fortran")  is an extension of Fortran-66
            that serves as the basis for the Software  Tools  Subsystem.   It
            provides  a  number  of  enhancements  to Fortran that facilitate
            structured design and programming, as  well  as  enhance  program
            readability and ease the burden of program coding.

                 This guide is intended to explain and demonstrate the use of
            Ratfor  as  a programming language within the Software Tools Sub-
            system.  In addition, applications notes  are  provided  to  help
            users build on the experience of others.













































                                         - vii -                             




            Ratfor User's Guide                                              


                                  ___RRR___aaa___ttt___fff___ooo___rrr___ ___LLL___aaa___nnn___ggg___uuu___aaa___ggg___eee___ ___GGG___uuu___iii___ddd___eee




                                     WWWhhhaaattt iiisss RRRaaatttfffooorrr???


                 The  Ratfor  ("Rational Fortran") language was introduced in
            the book _S_o_f_t_w_a_r_e _T_o_o_l_s by Brian W. Kernighan and P.  J.  Plauger
            (Addison-Wesley,  1976).  There, the authors use it as the medium
            for the development of programs that may be used  as  cooperating
            tools.   Ratfor  offers many extensions to Fortran that encourage
            and facilitate structured design and programming, enhance program
            readability and ease the burden of  coding.   Through  some  very
            simple mechanisms, Ratfor helps the programmer to isolate machine
            and implementation dependent sections of his code.

                 Among  the  many  programs  developed in _S_o_f_t_w_a_r_e _T_o_o_l_s is a
            Ratfor preprocessor --  a  program  for  converting  Ratfor  into
            equivalent  ANSI-66 Fortran.  'Rp', the preprocessor described in
            this guide, is an original version based on the program presented
            in _S_o_f_t_w_a_r_e _T_o_o_l_s.



                         DDDiiiffffffeeerrreeennnccceeesss BBBeeetttwwweeeeeennn RRRaaatttfffooorrr aaannnddd FFFooorrrtttrrraaannn


                 As we mentioned, Ratfor and Fortran are very similar.   Per-
            haps  the best introduction to their differences is given by Ker-
            nighan and Plauger in _S_o_f_t_w_a_r_e _T_o_o_l_s:

                 "But  bare  Fortran  is  a  poor  language  indeed  for
                 programming  or  describing  programs.  .  .  .  Ratfor
                 provides modern control flow statements like  those  in
                 PL/I,  Cobol, Algol, or Pascal, so we can do structured
                 programming properly.  It is easy to  read,  write  and
                 understand,  and readily translates into Fortran. . . .
                 Except for a handful of new statements like iiifff ---  eeelllssseee,,,
                 wwwhhhiiillleee,,, and rrreeepppeeeaaattt --- uuunnntttiiilll,,, Ratfor _i_s Fortran."


            SSSooouuurrrccceee PPPrrrooogggrrraaammm FFFooorrrmmmaaattt

                 _C_a_s_e  _S_e_n_s_i_t_i_v_i_t_y.   In  most  cases,  the  format of Ratfor
            programs is much less restricted than that of  Fortran  programs.
            Since  the  Software  Tools Subsystem encourages use of terminals
            with multi-case capabilities, 'rp' accepts input  in  both  upper
            and  lower  case.   'Rp' is case sensitive.  Keywords, such as iiifff
            and ssseeellleeecccttt,,, must appear in lower case.  Case  is  significant  in
            identifiers;  they may appear in either case, but upper case let-
            ters are not equivalent to lower case letters.  For example,  the
            words  "blank"  and "Blank" do _n_o_t represent the same identifier.
            For circumstances in which case sensitivity  is  a  bother,  'rp'
            accepts  a command line option ("-m") that instructs it to ignore


                                          - 1 -                              




            Ratfor User's Guide                                              


            the case of all identifiers and keywords.  See  the  applications
            notes or the 'help' command for more details.

                 _B_l_a_n_k  _S_e_n_s_i_t_i_v_i_t_y.   Unlike most Fortran compilers, 'rp' is
            very sensitive to  blanks.   'Rp'  requires  that  all  words  be
            separated  by  at  least  one  blank or special character.  Words
            containing imbedded blanks are not allowed.   The  best  rule  of
            thumb is to remember that if it is incomprehensible to you, it is
            probably incomprehensible to 'rp.'  (Remember, we humans normally
            leave  blank  spaces  between  words and tend not to place blanks
            inside words.  Such things make text difficult to understand.)

                 As a bad example, the following Ratfor code is incorrect and
            will not be interpreted properly:

                      subroutineexample(a,b,c)
                      integera,b,c
                      
                      repeatx=x+1
                         until(x>1)

            A few well placed blanks will have to be added  before  'rp'  can
            understand it:

                      subroutine example(a,b,c)
                      integer a,b,c
                      
                      repeat x=x+1
                         until(x>1)

            You  should  note  that extra spaces are allowed (and encouraged)
            everywhere except inside words and literals.  Extra spaces make a
            program much more readable by humans:

                      subroutine example (a, b, c)
                      integer a, b, c
                      
                      repeat x = x + 1
                         until (x > 1)


                 _C_a_r_d _C_o_l_u_m_n_s.  As should  be  expected  of  any  interactive
            software   system,  'rp'  is  completely  insensitive  to  "card"
            columns; statements may begin and end at any position in a  line.
            Lines  may  be  of any length, but identifiers and quoted strings
            may not be longer than 100  characters.   'Rp'  will  output  all
            statements  beginning  in  column  7,  and automatically generate
            continuation lines for statements extending past column 72.   All
            of  the  following  are  valid  Ratfor  statements, although such
            erratic indentation is definitely frowned upon.

                      integer i, j
                         i = 1
                            j = 2
                      stop
                         end


                                          - 2 -                              




            Ratfor User's Guide                                              


                 _M_u_l_t_i_p_l_e _S_t_a_t_e_m_e_n_t_s _p_e_r _L_i_n_e.   'Rp'  also  allows  multiple
            statements  per line, although indiscriminate use of this feature
            is not encouraged.  Just place a semicolon between statements and
            'rp' will generate two Fortran statements from  them.   You  will
            find

                      integer i
                      real a
                      logical l

            to be completely equivalent to

                      integer i; real a; logical l


                 _S_t_a_t_e_m_e_n_t _L_a_b_e_l_s _a_n_d _C_o_n_t_i_n_u_a_t_i_o_n.  You may wonder what hap-
            pens  to statement labels and continuation lines, since 'rp' pays
            no attention to card columns.  It turns out that statement labels
            and continuation lines  are  not  often  necessary.   While  'rp'
            minimizes  the  need  for  statement  labels  (except  on  fffooorrrmmmaaattt
            statements) and is quite intelligent  about  continuation  lines,
            there  are  conventions  to take care of those situations where a
            label is required or the need for  a  continuation  line  is  not
            obvious to 'rp.'

                 A  statement  may be labeled simply by placing the statement
            number, starting  in  any  column,  before  the  statement.   Any
            executable  statement,  including  the Ratfor control statements,
            may be labeled, and 'rp' will place the label  correctly  in  the
            Fortran  output.   It  is  wise  to refrain from using five-digit
            statement numbers; 'rp' uses these statement labels to  implement
            the  Ratfor control statements, and consequently will complain if
            it encounters them in a source program.  As examples of statement
            labels,

                      2     read (1, 10) a, b, c
                                     10  format (3e10.0)
                            write (1, 20) a, b, c; 20 format (3f20.5)
                               go to 2

            all show statement numbers in use.  You  should  note  that  with
            proper  use  of  Ratfor  and the Software Tools Subsystem support
            subroutines, statement labels are almost never required.

                 As for continuation lines, 'rp' is usually able to recognize
            when the current line needs to be continued.  A line ending  with
            a  comma,  unbalanced  parentheses  in  a condition, or a missing
            statement (such as at the end of an iiifff)))  are  all  situations  in
            which 'rp' correctly anticipates a continuation line:









                                          - 3 -                              




            Ratfor User's Guide                                              


                      integer a, b, c, d,
                         e, f, g
                      
                      if (a == b & c == d & e == f &
                          g == h & i == j & k == l)  call eql
                      
                      if (a == b)
                      
                         c = -2


                 If  an  explicit continuation is required, such as in a long
            assignment statement, 'rp' can be made  to  continue  a  line  by
            placing a trailing underscore ("_") at the end of the line.  This
            underscore must be preceded by a space.  You should note that the
            underscore  is  placed on the end of _l_i_n_e _t_o _b_e _c_o_n_t_i_n_u_e_d, rather
            than on the _c_o_n_t_i_n_u_a_t_i_o_n _l_i_n_e as in Fortran.  If you  are  unsure
            whether  Ratfor will correctly anticipate a continuation line, go
            ahead and place an underscore on the line to be continued -- 'rp'
            will ignore redundant continuation indicators.

                 Identifiers may not be split between lines; continuation  is
            allowed  only  between  tokens.   If  you  have an extremely long
            string  constant  that  requires  continuation,  you   can   take
            advantage  of the fact that 'rp' always concatenates two adjacent
            string constants.  Just close the first part of the literal  with
            a  quote, space, and underscore, and begin the second part on the
            next line with a quote.  'Rp' will ignore the line break (because
            of the trailing underscore) and concatenate the two literals.

                 The  following  are   some   examples   of   explicit   line
            continuations:

                      i = i + j + k + l + m + n + o + p + q + r + _
                         s + t + u + v
                      
                      1 format ("for inputs of ", i5, " and ", i5/ _
                            "the expected output should be ", i5)
                      
                      string heading   _
                         "----------------------------------------------"  _
                         "----------------------------------------------"


                 _C_o_m_m_e_n_t_s.   Comments,  an important part of any program, can
            be entered on any line; a comment begins with a sharp sign  ("#")
            and  continues  until  the  end  of the line.  In addition, blank
            lines and lines containing only comments may be freely placed  in
            the  source program.  Here are some appropriate and (correct but)
            inappropriate uses of Ratfor comments:








                                          - 4 -                              




            Ratfor User's Guide                                              


                      if (i > 48)
                         # do this only if i is greater than 48
                         j = j + 1
                      
                      data array / 1,    # element 1
                                   2,    # element 2
                                   3,    # element 3
                                   4/    # element 4
                      
                      integer cnt,         # counter for controlling the
                                           #    outer loop
                              total_errs,  # total number of errors
                                           #    encountered
                              last_pass    # flag for determining the
                                           #    last pass; init = 0



            IIIdddeeennntttiiifffiiieeerrrsss

                 A major difference between Ratfor and  Fortran  is  Ratfor's
            acceptance  of arbitrarily long identifiers.  A Ratfor identifier
            may be up to 100 characters long, beginning with  a  letter,  and
            may  contain  letters,  digits,  dollar  signs,  and underscores.
            However, it may _n_o_t be a Ratfor or Fortran keyword, such  as  iiifff,,,
            eeelllssseee,,,  iiinnnttteeegggeeerrr,,,  rrreeeaaalll,,,  or  lllooogggiiicccaaalll...   Underscores are allowed in
            identifiers only for the sake  of  readability,  and  are  always
            ignored.   Thus,  "these_tasks" and "the_set_asks" are equivalent
            Ratfor identifiers.

                 'Rp' guarantees that an identifier longer than  six  charac-
            ters  will  be  transformed  into  a  _u_n_i_q_u_e  _F_o_r_t_r_a_n _i_d_e_n_t_i_f_i_e_r.
            Normally, the process of  transforming  Ratfor  identifiers  into
            Fortran  identifiers  is  transparent;  you need not be concerned
            with how this transformation is accomplished.   The  one  notable
            exception is the effect on external symbols (i.e.  subroutine and
            function  names,  common block names).  When the declaration of a
            subprogram and its invocation are preprocessed together,  in  the
            same run, no problems will occur.  However, if the subprogram and
            its invocation are preprocessed separately, there is no guarantee
            that  a  given  Ratfor  name  will  be  transformed into the same
            Fortran name in the two different runs.  This  situation  can  be
            avoided  in  either of three ways:  (1) use the llliiinnnkkkaaagggeee statement
            described in the next section, (2) use six-character  or  shorter
            identifiers  for  subprogram names, or (3) preprocess subprograms
            and their invocations in the same run.

                 Just for pedagogical reasons, here are  a  few  correct  and
            incorrect Ratfor identifiers:









                                          - 5 -                              




            Ratfor User's Guide                                              


                      _C_o_r_r_e_c_t

                      long_name_1
                      long_name_2
                      prwf$$
                      I_am_a_very_long_Ratfor_name_that_is_perfectly_correct
                      a_a    # You should note that 'a_a', 'a__a', and 'aa'
                      a__a   # are all absolutely identical in Ratfor --
                      aa     # underscores are always ignored in identifiers,
                      AA     # but 'AA' is very different.


                      _I_n_c_o_r_r_e_c_t

                      123_part    # starts with a digit
                      _part1      # starts with an underscore
                      part 2      # contains a blank
                      a*b         # contains an asterisk


                 The  following  paragraph  contains a description of exactly
            how Ratfor identifiers are transformed into Fortran  identifiers.
            You need not know how this transformation is accomplished to make
            full  use  of  Ratfor; hence, you probably need not read the next
            paragraph.

                 If a Ratfor identifier is  longer  than  six  characters  or
            contains an upper case letter, it is made unique by the following
            procedure:

            (1)  The  identifier  is  padded  with  'a's or truncated to five
                 characters.  Remaining characters are mapped to lower case.
            (2)  The first character is retained to preserve implicit typing.
            (3)  The sixth character is changed  to  a  "uniquing  character"
                 (normally a zero).
            (4)  If  necessary,  the second, third, fourth, and fifth charac-
                 ters are altered to make sure there is no  conflict  with  a
                 previously used identifier.

            'Rp'  also  examines  six-character  identifiers  containing  the
            uniquing character in the sixth position, to ensure that no  con-
            flicts arise.


            IIInnnttteeegggeeerrr CCCooonnnssstttaaannntttsss

                 Since  it  is  sometimes necessary to use other than decimal
            integer constants in a program, 'rp' accepts integers in bases  2
            through  16.   Integers consisting of only digits are, of course,
            considered decimal integers.  Other bases can be  indicated  with
            the following notation:

                      <base>r<number>

            where  <base> is the base of the number (in decimal) and <number>
            is number in the desired base (the letters 'a'  through  'f'  are


                                          - 6 -                              




            Ratfor User's Guide                                              


            used  to  represent the digits '10' through '15' in bases greater
            than 10).  For example, here are some  Ratfor  integer  constants
            and the decimal values they represent:

                      _N_u_m_b_e_r     _D_e_c_i_m_a_l _V_a_l_u_e
                      
                      8r77       63
                      16rff      255
                      -2r11      -3
                      7r13       10


                 Some care must be exercised when using this form of constant
            to  generate bit-masks with the high-order bit set.  For example,
            to set the high-order bit in a 16-bit word, one might be  tempted
            to use one of the constants

                      16r8000   or   8r100000

            Either  of these would cause incorrect results, because the value
            that they represent, in decimal, is  65536.   This  number,  when
            encountered  by  Prime Fortran, is converted to a 32-bit constant
            (with the high order bit  in  the  second  word  set).   This  is
            probably  not  the  desired  result.   The only solutions to this
            problem (which occurs when trying to represent a  negative  twos-
            complement  number  as a positive number) are (1) use the correct
            twos-complement representation (-32768 in this case), or (2) fall
            back to Prime Fortran's octal constants (e.g.  :100000).


            SSStttrrriiinnnggg CCCooonnnssstttaaannntttsss

                 Under the Software Tools Subsystem, character  strings  come
            in various flavors.  Because various internal representations are
            used  for  character strings, Fortran Hollerith constants are not
            sufficient to easily provide all the different formats required.

                 All types of Ratfor string constants  consist  of  a  string
            body followed by a string format indicator.  The body of a string
            constant  consists  of  strings of characters bounded by pairs of
            quotes (either single or double quotes),  possibly  separated  by
            blanks.  All the character strings in the body (not including the
            bounding quotes) are concatenated to give the value of the string
            constant.   For  example,  here  are three string constant bodies
            that contain the same string:

                      "I am a string constant body"
                      "I" ' am ' "a" ' string ' "constant" ' body'
                      "I am a string "'constant body'


                 The string format  indicator  is  an  optional  letter  that
            determines  the  internal  format  to  be  used  when storing the
            string.    Currently   there   are    five    different    string
            representations available:



                                          - 7 -                              




            Ratfor User's Guide                                              


            omitted  Fortran   Hollerith  string.   When  the  string  format
                     indicator  is  omitted,  a  standard  Fortran  Hollerith
                     constant  is  generated.  Characters are left-justified,
                     packed in words (two characters per word on the  Prime),
                     and  unused  positions  on  the  right  are  filled with
                     blanks.

            c        Single  character  constant.   The  'c'  string   format
                     indicator  causes  a  single  character  constant  to be
                     generated.  The character is right-justified  and  zero-
                     filled  on  the  left  in a word.  Only one character is
                     allowed in the body of the constant.  Since it  is  easy
                     to  manipulate and compare characters in this format, it
                     is the preferred format for all single characters in the
                     Software Tools Subsystem.

            p        Packed (Hollerith) period-terminated  string.   The  'p'
                     format indicator causes the generation of a Fortran Hol-
                     lerith  constant containing the characters in the string
                     body followed by a period.  In addition, all periods  in
                     the  string  body  are  preceded  by an escape character
                     ("@").  The advantage of a  "p"  format  string  over  a
                     Fortran  Hollerith  string is that the length of the "p"
                     format string can be determined at run time.

            v        PL/I character varying string.  For  compatibility  with
                     Prime's PL/I and because this data format is required by
                     some   system  calls,  the  "v"  format  indicator  will
                     generate Fortran declarations to create a PL/I character
                     varying string.  The first word of the constant contains
                     the number of characters; subsequent words  contain  the
                     characters  of the string body packed two per word.  "V"
                     format string constants may only be used  in  executable
                     statements.

            s        EOS-terminated  unpacked  string.  The "s" string format
                     indicator causes 'rp' to generated  declarations  neces-
                     sary to construct an array of characters containing each
                     character  in the string body in a separate word, right-
                     justified and zero-filled (each character is in the same
                     format as is generated by  the  "c"  format  indicator).
                     Following  the  characters  is a word containing a value
                     different from any character value that marks the end of
                     the string.  This ending value is defined  as  the  sym-
                     bolic  constant  EOS.   EOS-terminated  strings  are the
                     preferred format for multi-character strings in the Sub-
                     system, and are used by most Subsystem routines  dealing
                     with character strings.  "S" format string constants may
                     only be used in executable statements.

                 Here  are some examples of strings and the result that would
            be generated for Prime Fortran.  On a machine  with  a  different
            character set or word length, different code might be generated.





                                          - 8 -                              




            Ratfor User's Guide                                              


                      _S_t_r_i_n_g _C_o_n_s_t_a_n_t     _R_e_s_u_l_t_i_n_g _C_o_d_e
                                          
                      'v'c                the integer constant 246
                      "=doc="s            an   integer   array  of  length  6
                                          containing 189, 228, 239, 227, 189,
                                          0
                      "a>b c>d"v          an  integer  array  containing   7,
                                          "a>", "b ", "c>", "d "
                      ".main."p           the constant 9h@.main@..
                      "Hollerith"         the constant 9hHollerith



            LLLooogggiiicccaaalll aaannnddd RRReeelllaaatttiiiooonnnaaalll OOOpppeeerrraaatttooorrrsss

                 Ratfor  allows  the  use  of graphic characters to represent
            logical and relational operators instead of  the  Fortran  ".EQ."
            and  such.   While use of these graphic characters is encouraged,
            it is not incorrect to use the Fortran operators.  The  following
            table shows the equivalent syntaxes:


                      _R_a_t_f_o_r   _F_o_r_t_r_a_n   _F_u_n_c_t_i_o_n

                      >        .GT.      Greater than
                      >=       .GE.      Greater or equal
                      <        .LT.      Less than
                      <=       .LE.      Less or equal
                      ==       .EQ.      Equal to
                      ~=       .NE.      Not equal to

                      ~        .NOT.     Logical negation
                      &        .AND.     Logical conjunction
                      |        .OR.      Logical disjunction


            Note than the digraphs shown in the table must appear in the Rat-
            for program with no imbedded spaces.

                 For  example, the two following iiifff statements are equivalent
            in every way:

                      if (a .eq. b .or. .not. (c .ne. d .and. f .ge. g))
                      
                      if (a == b | ~ (c ~= d & f >= g))


                 In addition to graphics representing Fortran operators,  two
            additional operators are available in any logical expression par-
            sed  by  'rp'  (i.e.  anywhere but assignment statements).  These
            operators, '&&' ("and if") and '||' ("or if")  perform  the  same
            action  as  the  logical  operators '&' and '|', except that they
            guarantee that the expression is evaluated from  left  to  right,
            and  that  evaluation  is  terminated when the truth value of the
            expression is known.  They may appear within the scope of the '~'
            operator, but they may not grouped within the scope  of  '&'  and


                                          - 9 -                              




            Ratfor User's Guide                                              


            '|'.

                 These  operators  find  use in situations in which it may be
            illegal or undesirable to  evaluate  the  right-hand  side  of  a
            logical  expression  based  on  the  truth value of the left-hand
            side.  For example, in

                      while (i > 0 && str (i) == ' 'c)
                         i = i - 1

            it is necessary that the subscript be checked before it is  used.
            The  order  of  evaluation  of Fortran logical expressions is not
            specified, so in this example, it would be technically illegal to
            use '&' in place of '&&'.  If the value of 'i' were less than  1,
            the  illegal  subscript reference might be made regardless of the
            range check of the subscript.  The Ratfor short-circuited logical
            operators prevent this problem  by  insuring  that  "i  >  0"  is
            evaluated first, and if it is false, evaluation of the expression
            terminates, since its value (false) is known.


            AAAssssssiiigggnnnmmmeeennnttt OOOpppeeerrraaatttooorrrsss

                 Ratfor  provides  shorthand  forms for the Fortran idioms of
            the form

                      <variable> = <variable> <operator> <expression>

            In Ratfor, this assignment can be simplified to the form

                      <variable> <assignment operator> <expression>

            with the use of assignment operators.  The  following  assignment
            operators are available:

                   _O_p_e_r_a_t_o_r       _U_s_e             _R_e_s_u_l_t
                      
                      +=       <v> += <e>      <v> = <v> + (<e>)
                      -=       <v> -= <e>      <v> = <v> - (<e>)
                      *=       <v> *= <e>      <v> = <v> * (<e>)
                      /=       <v> /= <e>      <v> = <v> / (<e>)
                      %=       <v> %= <e>      <v> = mod (<v>, <e>)
                      &=       <v> &= <e>      <v> = and (<v>, <e>)
                      |=       <v> |= <e>      <v> = or (<v>, <e>)
                      ^=       <v> ^= <e>      <v> = xor (<v>, <e>)

            The  Ratfor  assignment  operators may be used wherever a Fortran
            assignment statement is allowable.  Regrettably,  the  assignment
            operators  provide  only  a shorthand for the programmer; they do
            not affect the efficiency of the object code.

                 The assignment operators are  especially  useful  with  sub-
            scripted  variables;  since  a  complex subscript expression need
            appear only once, there is no possibility of mistyping or forget-
            ting to change one.   Here  are  some  examples  of  the  use  of
            assignment operators


                                         - 10 -                              




            Ratfor User's Guide                                              


                      i += 1
                      fact *= i + 10
                      subs (2 * i - 2, 5 * j - 23) -= 1
                      int %= 10 ** j
                      mask &= 8r12

            For  comparison, here are the same assignments without the use of
            assignment operators:

                      i = i + 1
                      fact = fact * (i + 10)
                      subs (2*i-2, 5*j-23) = subs (2*i-2, 5*j-23) - 1
                      int = mod (int, (10 ** j))
                      mask = and (mask, 8r12)



            FFFooorrrtttrrraaannn SSStttaaattteeemmmeeennntttsss iiinnn RRRaaatttfffooorrr PPPrrrooogggrrraaammmsss

                 Ratfor  provides  the  escape  statement  to  allow  Fortran
            statements  to be passed directly to the output without the usual
            processing, such as case mapping and automatic continuation.  The
            escape statement has three forms, summarized below.  In the first
            form listed below, the first non-blank character of  the  Fortran
            statement  is  output  in  column seven.  In the second form, the
            first non-blank character of the Fortran statement is  output  in
            column  seven,  but  column  six  contains  a  "$"  to continue a
            previous Fortran statement to that stream.  In  the  third  form,
            the  Fortran  statement is output starting in column one, so that
            the user has full control of the placement of items on the  line.
            The following is a summary of this description:

                      _E_s_c_a_p_e _S_t_a_t_e_m_e_n_t _F_o_r_m_a_t            _O_u_t_p_u_t _C_o_l_u_m_n

                      %<stream><Fortran statement>             7
                      %<stream>&<Fortran statement>            6
                      %<stream>%<Fortran statement>            1

            "Stream" can take on the following values:

                      1           declaration
                      2           data
                      3           code

            If  no  stream  is  specified  (i.e.  %%<Fortran statement>), the
          | Fortran statement is sent to the code stream.

          |      Escaped statements _m_u_s_t occur inside a program  unit,  i.e.,
          | between a fffuuunnnccctttiiiooonnn or sssuuubbbrrrooouuutttiiinnneee statement, and its corresponding
          | eeennnddd  statement.   Otherwise  'rp'  gets  confused about where the
          | escaped statements should go, since it  won't  have  any  streams
          | open.   If you have a large amount of self contained FORTRAN that
          | you want 'rp' to include in its output, you can  accomplish  this
          | in  two  steps.   First, put '%1%' at the beginning of each line,
          | and then put the FORTRAN at the _b_e_g_i_n_n_i_n_g of your  ratfor  source
          | file.


                                         - 11 -                              




            Ratfor User's Guide                                              


            IIInnncccooommmpppaaatttiiibbbiiillliiitttiiieeesss

                 Even with the great similarities between Fortran and Ratfor,
            an  arbitrary Fortran program is _n_o_t necessarily a correct Ratfor
            program.  Several areas of incompatibilities exist:

            -    In Ratfor, blanks are significant -- at least one space
                 must separate adjacent identifiers.

            -    The Ratfor dddooo statement, as we shall soon see, does not
                 contain  the  statement  number  following  the   "do".
                 Instead, its range extends over the next (possibly com-
                 pound) statement.

            -    Two  word Fortran key phrases such as dddooouuubbbllleee ppprrreeeccciiisssiiiooonnn,,,
                 bbbllloooccckkk dddaaatttaaa,,, and ssstttaaaccckkk hhheeeaaadddeeerrr must  be  presented  as  a
                 single   Ratfor   identifier   (e.g.    "blockdata"  or
                 "block_data").

            -    Fortran statement functions must  be  preceded  by  the
                 Ratfor  keyword  ssstttmmmtttfffuuunnnccc...   To  assure  that they will
                 appear in the correct order in the Fortran, they should
                 immediately precede the eeennnddd statement for  the  program
                 unit.

            -    Hollerith  literals  (i.e.   5HABCDE)  are  not allowed
                 anywhere in a Ratfor program.   Instead,  'rp'  expects
                 all  Hollerith  literals  to  be  enclosed in single or
                 double quotes (i.e.  "ABCDE" or  'ABCDE').   'Rp'  will
                 convert  the  quoted  string into a proper Fortran Hol-
                 lerith string.

            -    'Rp' does not allow Fortran comments.  In Ratfor,  com-
                 ments  are  introduced  by a sharp sign ("#") appearing
                 anywhere on a line, and continue  to  the  end  of  the
                 line.

            -    'Rp'  does  not  accept  the  Fortran continuation con-
                 vention.  Continuation is implicit for any line  ending
                 with  a  comma, or any conditional statement containing
                 unbalanced parentheses.  Continuation between arbitrary
                 words  may  be  indicated  by  placing  an  underscore,
                 preceded  by at least one space, at the end of the line
                 to be continued.

            -    'Rp' does not ignore text beyond column 72.

            -    Fortran  and  Ratfor  keywords  may  not  be  used   as
                 identifiers in a Ratfor program.  Their use will result
                 in unreasonable behavior.








                                         - 12 -                              




            Ratfor User's Guide                                              


                           RRRaaatttfffooorrr TTTeeexxxttt SSSuuubbbssstttiiitttuuutttiiiooonnn SSStttaaattteeemmmeeennntttsss


                 'Rp'   provides  several  text  substitution  facilities  to
            improve the readability and maintainability of  Ratfor  programs.
            You  can  use these facilities to great advantage to hide tedious
            implementation details and to  assist  in  writing  transportable
            code.


            DDDeeefffiiinnneee

                 The  Ratfor dddeeefffiiinnneee statement bears a vague similarity to the
            non-standard Fortran pppaaarrraaammmeeettteeerrr  declaration,  but  is  much  more
            flexible.   In  Ratfor,  any  legal  identifier may be defined as
            almost any string of characters.  Thereafter, 'rp'  will  replace
            all  occurrences  of  the  defined identifier with the definition
            string.  In addition, identifiers may be defined  with  a  formal
            parameter  list.   Then,  during  replacement,  actual parameters
            specified in the invocation are substituted  for  occurrences  of
            the formal parameters in the replacement text.

                 Defines  find  their principle use in helping to clarify the
            meaning of "magic numbers" that appear frequently.  For example,

                      while (getlin (line, -10) ~= -1)
                         call putlin (line, -11)

            is syntactically correct, and even does  something  useful.   But
            what?   The  use  of  dddeeefffiiinnneee  to  hide the magic numbers not only
            allows them to be changed easily and uniformly,  but  also  gives
            the  program reader a helpful hint as to what is going on.  If we
            rewrite  the  example,   replacing   the   numbers   by   defined
            identifiers,  not only are the numbers easier to change uniformly
            at some later date, but also, the reader is given a little bit of
            a hint as to what is intended.

                      define (EOF, -1)
                      define (STANDARD_INPUT, -10)
                      define (STANDARD_OUTPUT, -11)

                      while (getlin (line, STANDARD_INPUT) ~= EOF)
                         call putlin (line, STANDARD_OUTPUT)


                 The last example  also  shows  the  syntax  for  definitions
            without formal parameters.

                 Often  there  are  situations  in which the replacement text
            must vary slightly from place to place.  For example, let's  take
            the   last   situation   in  which  the  programmer  must  supply
            "STANDARD_INPUT" and "STANDARD_OUTPUT" in calls to the line input
            and output routines.  Since this occurs in a  large  majority  of
            cases,  it would be more convenient to have procedures named, say
            "getl" and  "putl"  that  take  only  one  parameter  and  assume
            "STANDARD_INPUT"  or  "STANDARD_OUTPUT".   We  could,  of course,


                                         - 13 -                              




            Ratfor User's Guide                                              


            write two new procedures to fill this need, but  that  would  add
            more  code  and more procedure calls.  Two dddeeefffiiinnneee statements will
            serve the purpose very well:

                      define (STANDARD_INPUT, -10)
                      define (STANDARD_OUTPUT, -11)
                      define (getl (ln), getlin (ln, STANDARD_INPUT))
                      define (putl (ln), putlin (ln, STANDARD_OUTPUT))

                      while (getl (line) ~= EOF)
                         call putl (line)

            In this case, when the string  "getl  (line)"  is  replaced,  all
            occurrences  of  "ln"  (the formal parameter) will be replaced by
            "line" (the actual parameter).  This example  will  give  exactly
            the same results as the first, but with a little less typing when
            "getl" and "putl" are called often.

                 The full syntax for a dddeeefffiiinnneee statement follows:

                    define (<identifier> [(<formal params>)], <replacement>)

            When  such  a  dddeeefffiiinnneee  statement is encountered, <replacement> is
            recorded as the value of <identifier>.  At  any  later  time,  if
            <identifier>  is  encountered  in the text, it is replaced by the
            text of <replacement>.  If the original dddeeefffiiinnneee contained a formal
            parameter  list,  the  list  of   actual   parameters   following
            <identifier>  is  collected,  and  the actual parameters are sub-
            stituted for the corresponding formal parameters in <replacement>
            before the replacement is made.

                 There is a file of "standard" definitions used by  all  Sub-
            system   programs   called   "=incl=/swt_def.r.i".    The  dddeeefffiiinnneee
            statements in this file are automatically  inserted  before  each
            source  file  (unless  'rp' is told otherwise by the "-f" command
            line option).  For information on  the  exact  contents  of  this
            file, see Appendix D.

                 There are also a few other facts that are helpful when using
            dddeeefffiiinnneee:::

            -    The  <replacement>  may  be  any  string  of  characters not
                 containing unbalanced parentheses or unpaired quotes

            -    <Formal parameters> must be identifiers.

            -    <Actual parameters> may be  any  string  of  characters  not
                 containing  unbalanced parentheses, unpaired quotes, or com-
                 mas not surrounded by quotes or parentheses.

            -    Formal parameter replacement in  <replacement>  occurs  even
                 inside of quoted strings.  For example,






                                         - 14 -                              




            Ratfor User's Guide                                              


                           define (assert (cond), {
                              if (~(cond))
                                 call error ("assertion cond not valid"p)}
                           assert (i < j)

                 would generate

                           {
                              if (~(i < j))
                                 call error ("assertion i < j not valid"p)}


            -    During replacement of an identifier defined without a formal
                 parameter  list,  an  actual  parameter  list  will never be
                 accessed.  For example,

                           define (ARRAYNAME, table1)
                           ARRAYNAME (i, j) = 0

                 would generate

                           table1 (i, j) = 0


            -    The number of actual and formal parameters need  not  match.
                 Excess  formal  parameters will be replaced by null strings;
                 excess actual parameters will be ignored.

            -    A dddeeefffiiinnneee statement affects only those identifiers  following
                 it.   In  the following example, STDIN would nnnooottt be replaced
                 by -11, unless a dddeeefffiiinnneee statement  for  STDIN  had  occurred
                 previously:

                           l = getlin (buf, STDIN)
                           define (STDIN, -11)


            -    A  dddeeefffiiinnneee statement applies to all lines following it in the
                 input to 'rp',  regardless  of  subroutine,  procedure,  and
                 source file boundaries.

            -    After  replacement,  the substituted text itself is examined
                 for further defined identifiers.  This allows  such  defini-
                 tion sequences as

                           define (DELCOMMAND, LETD)
                           define (LETD, 100)

                 to   result   in   the  desired  replacement  of  "100"  for
                 "DELCOMMAND".  Actual parameters are  not  reexamined  until
                 the entire replacement string is reexamined.

            -    Identifiers may be redefined without error.  The most recent
                 definition supersedes all previous ones.  Storage space used
                 by superseded definitions is reclaimed.



                                         - 15 -                              




            Ratfor User's Guide                                              


                 Here are a few more examples of how defines can be used:

                      _B_e_f_o_r_e _D_e_f_i_n_e_s _H_a_v_e _B_e_e_n _P_r_o_c_e_s_s_e_d:
                      
                      define (NO, 0)
                      define (YES, 1)
                      define (STDIN, -11)
                      define (EOF, -2)
                      define (RESET (flag), flag = NO)
                      define (CHECK_FOR_ERROR (flag, msg),
                         if (flag == YES)
                            call error (msg)
                         )
                      define (FATAL_ERROR_MESSAGE,
                         "Fatal error -- run terminated"p)
                      define (PROCESS_LINE,
                         count = count + 1
                         call check_syntax (buf, count, error_flag)
                         )
                      
                      while (getlin (buf, STDIN) ~= EOF) {
                         RESET (error_flag)
                         PROCESS_LINE
                         CHECK_FOR_ERROR (error_flag, FATAL_ERROR_MESSAGE)
                         }
                      
                      
                      _A_f_t_e_r _D_e_f_i_n_e_s _H_a_v_e _B_e_e_n _P_r_o_c_e_s_s_e_d:
                      
                      while (getlin (buf, -11) ~= -2) {
                         error_flag = 0
                         count = count + 1
                         call check_syntax (buf, count, error_flag)
                         if (error_flag == 1)
                            call error ("Fatal error -- run terminated"p)
                         }



            UUUnnndddeeefffiiinnneee

                 The  Ratfor  uuunnndddeeefffiiinnneee  statement  allows  termination of the
            range of a dddeeefffiiinnneee statement.  The identifier  named  in  the  uuunnn-
            dddeeefffiiinnneee  statement  is  removed  from  the  define  table if it is
            present; otherwise, no action is  taken.   Storage  used  by  the
            definition is reclaimed.  For example, the statements

                      define (xxx, a = 1)
                      xxx
                      undefine (xxx)
                      xxx

            would produce the following code:





                                         - 16 -                              




            Ratfor User's Guide                                              


                      a = 1
                      xxx



            IIInnncccllluuudddeee

                 The Ratfor iiinnncccllluuudddeee statement allows you to include arbitrary
            files  in  a Ratfor program (much like the COBOL cccooopppyyy verb).  The
            syntax of an iiinnncccllluuudddeee statement is as follows:

                      include "<file name>"

            If the file name  is  six  or  fewer  characters  in  length  and
            contains only alphanumeric characters, the quotes may be omitted.
            For  the sake of uniformity, we suggest that the quotes always be
            used.

                 When 'rp' encounters an iiinnncccllluuudddeee statement, it begins  taking
            input  from  the  file specified by <file name>.  When the end of
            the included file is encountered, 'rp' resumes reading the preem-
            pted file.  Files named  in  iiinnncccllluuudddeee  statements  may  themselves
            contain  iiinnncccllluuudddeee  statements;  this  nesting  may  continue to an
            arbitrary depth (which, by the way,  is  arbitrarily  limited  to
            five).

                 For  an  example of iiinnncccllluuudddeee at work, assume the existence of
            the following files:

                      f1:
                           include "f2"
                           i = 1
                           include "f3"

                      f2:
                           include "f4"
                           m = 1

                      f3:
                           j = 1

                      f4:
                           k = 1

            If "f1" were the original file, the following text is what  would
            actually be processed:

                      k = 1
                      m = 1
                      i = 1
                      j = 1







                                         - 17 -                              




            Ratfor User's Guide                                              


                                   RRRaaatttfffooorrr DDDeeeccclllaaarrraaatttiiiooonnnsss


                 There  are several declarations available in Ratfor in addi-
            tion to those usually supported in Fortran.  They provide  a  way
            of  conveniently  declaring  data  structures  not  available  in
            Fortran,  assist  in  supporting  separate   compilation,   allow
            declaration  of  local  variables within compound statements, and
            allow the declaration of internal  procedures.   Declarations  in
            Ratfor may be intermixed with executable statements.


            SSStttrrriiinnnggg

                 The  ssstttrrriiinnnggg  statement  is  provided  as  a shorthand way of
            creating and naming EOS-terminated strings.   The  structure  and
            use  of  an  EOS-terminated string is described in the section on
            Subsystem Conventions.  Here it is sufficient to say that such  a
            string  is an integer array containing one character per element,
            right justified and zero filled, and ending with a special  value
            (EOS)  designating  the  "end  of  string."  Since Fortran has no
            construct for specifying such a data structure, it must either be
            declared manually, as a Ratfor string constant, or by the  Ratfor
            ssstttrrriiinnnggg statement.

                 The  ssstttrrriiinnnggg  statement is a declaration that creates a named
            string in an integer array using a Fortran dddaaatttaaa  statement.   The
            syntax of the ssstttrrriiinnnggg statement is as follows:

                      string <name> <quoted string>

            where  <name>  is  the Ratfor identifier to be used in naming the
            string and <quoted string> specifies the string's  contents.   As
            you  might  expect, either single or double quotes may be used to
            delimit <quoted string>.  In either  case,  only  the  characters
            between  the  quotes  become part of the string; the quotes them-
            selves are not included.

                 SSStttrrriiinnnggg statements  are  quite  often  used  for  setting  up
            constant strings such as file names or key words.  For instance,

                      string file_name "//mydir/myfile"
                      string change_command "change"
                      string delete_command "delete"

            define such character arrays.


            SSStttrrriiinnngggtttaaabbbllleee

                 The  ssstttrrriiinnngggtttaaabbbllleee statement creates a rather specialized data
            structure --  a  marginally  indexed  array  of  variable  length
            strings.  This data structure provides the same ease of access as
            an array, but it can contain entries of varying sizes.  A ssstttrrriiinnnggg-
            tttaaabbbllleee declaration defines two data items:  a marginal index and a
            table  body.   The  marginal index is an integer array containing


                                         - 18 -                              




            Ratfor User's Guide                                              


            indices into the table body.  The first element of  the  marginal
            index  is  the number of entries following in the marginal index.
            Subsequent elements of the marginal index  are  pointers  to  the
            beginning of items in the table body.  Since the beginning of the
            table  body  is always the beginning of an item, the second entry
            of the marginal index is always 1.

                 The syntax of a ssstttrrriiinnngggtttaaabbbllleee declaration is as follows:

                      string_table <marginal index>, <table body>,
                         [ / ] <item> { / <item> }

            <Marginal index> and <table body> are identifiers  that  will  be
            declared  as  the  marginal  index  and table body, respectively.
            <Item> is a comma-separated list  of  single-character  constants
            (with a "c" string format indicator), integers, or EOS-terminated
            character  strings  (with  _n_o string format indicator -- a little
            inconsistency here).  The  values  contained  in  an  <item>  are
            stored  contiguously  in  <table  body>  with no separator values
            (save for an EOS at the end of each EOS-terminated  string).   An
            entry  is  made  in the marginal index containing the position of
            the first word of each <item>.

                 For example, assume that you have a  program  in  which  you
            wish  to  obtain  one  of  three integer values based on an input
            string.  You want to allow an arbitrary number of synonyms in the
            input (like "add", "insert", etc.).

                      string_table cmdpos, cmdtext,
                         / ADD,      "add" _
                         / ADD,      "insert" _
                         / CHANGE,   "change" _
                         / CHANGE,   "update" _
                         / DELETE,   "delete" _
                         / DELETE,   "remove"

            This declaration creates a  structure  something  like  the  fol-
            lowing:

                         cmdpos                   cmdtext
                      
                      1:    6
                      2:    1          1:  ADD,    'a'c, 'd'c, 'd'c, EOS
                      3:    6          6:  ADD,    'i'c, 'n'c, 's'c, 'e'c,
                                                   'r'c, 't'c, EOS
                      4:   14         14:  CHANGE, 'c'c, 'h'c, 'a'c, 'n'c,
                                                   'g'c, 'e'c, EOS
                      5:   22         22:  CHANGE, 'u'c, 'p'c, 'd'c, 'a'c,
                                                   't'c, 'e'c, EOS
                      6:   29         29:  DELETE, 'd'c, 'e'c, 'l'c, 'e'c,
                                                   't'c, 'e'c, EOS
                      7:   36         36:  DELETE, 'r'c, 'e'c, 'm'c, 'o'c,
                                                   'v'c, 'e'c, EOS





                                         - 19 -                              




            Ratfor User's Guide                                              


                 There are several routines in the Subsystem library that can
            be  used  to  search for strings in one of these structures.  You
            can find details on the use of these procedures in the  reference
            manual/'help' entries for 'strlsr' and 'strbsr'.


            LLLiiinnnkkkaaagggeee

                 The sole purpose of the llliiinnnkkkaaagggeee declaration is to circumvent
            problems   with   transforming   Ratfor  identifiers  to  Fortran
            identifiers when compiling program modules separately.  To  relax
            the  restriction that externally visible names (subroutine, func-
            tion, and common block names)  must  contain  no  more  than  six
            characters,  each  separately  compiled module must begin with an
            identical llliiinnnkkkaaagggeee declaration containing the names of _a_l_l  exter-
            nal symbols -- subroutine names, function names, and common block
            names  (the  identifiers  inside  the slashes -- not the variable
            names).  Except for text  substitution  statements,  the  llliiinnnkkkaaagggeee
            declaration  _m_u_s_t  be  the  first  statement in each module.  The
            order of names in the statement _i_s _s_i_g_n_i_f_i_c_a_n_t --  as  a  general
            rule,  you  should  iiinnncccllluuudddeee  the same file containing the llliiinnnkkkaaagggeee
            declaration in each module.

                 LLLiiinnnkkkaaagggeee looks very much like a Fortran type declaration:

                      linkage identifier1, identifier2, identifier3

            Each of the identifiers is an external  name  (i.e.   subroutine,
            function,  or  common  block name).  If this statement appears in
            each source module, _w_i_t_h _t_h_e  _i_d_e_n_t_i_f_i_e_r_s  _i_n  _e_x_a_c_t_l_y  _t_h_e  _s_a_m_e
            _o_r_d_e_r,  it  is  guaranteed  that  in  all  cases,  each  of these
            identifiers will be transformed  into  the  _s_a_m_e  unique  Fortran
            identifier.   For Subsystem-specific information on the mechanics
            of  separate  compilation,  you  can  see  the  section  in   the
            applications notes devoted to this topic.


            LLLooocccaaalll

                 With  the  lllooocccaaalll  declaration, you can indicate that certain
            variables are "local" to  a  particular  compound  statement  (or
            block)  just as in Algol.  LLLooocccaaalll declarations are most often used
            inside internal procedures (which are described later), but  they
            can appear in any compound statement.

          |      The  type  declarations for local variables must be preceded
          | by a lllooocccaaalll declaration containing the names of all variables that
            are to be local to the block:

                      local i, j, a
                      
                      integer i, j
                      real a

            The lllooocccaaalll statement  must  precede  the  first  appearance  of  a
          | variable  inside the block.  While this isn't the greatest syntax


                                         - 20 -                              




            Ratfor User's Guide                                              


          | in the world, it is easy to implement  local  variables  in  this
          | fashion.

                 Scope  rules  similar  to  those  of  most  block-structured
            languages apply to nested compound statements:  A local  variable
            is  visible  to all blocks nested within the block in which it is
            declared.  Declaration of a local variable obscures a variable by
            the same name declared in an outer block.

                 There are several cautions you must observe when using local
            variables.  'Rp' is currently not well-versed in the semantics of
            Fortran declarations and therefore cannot diagnose the  incorrect
            use  of  lllooocccaaalll  declarations.  Misuse can then result in semantic
            errors in the Fortran output that are often  not  caught  by  the
            Fortran  compiler.   If  the  declaration  of a variable within a
            block  appears  before  the  variable  is  named   in   a   lllooocccaaalll
            declaration,  'rp'  will not detect the error, and an "undeclared
            variable" error will be generated in the Fortran.  External names
            (i.e.  function, subroutine, and common block names)  must  never
            be  named  in  a  lllooocccaaalll declaration, unless you want to declare a
            local variable of the same name.  Finally, the formal  parameters
            of internal procedures should never appear in a lllooocccaaalll declaration
            in the body of the procedure, again, unless you want to declare a
            local variable of the same name.

                 Here is an example showing the scopes of variables appearing
            in a lllooocccaaalll declaration:

                      ### level 0
                      subroutine test
                      
                      integer i, j, k
                      
                      {  ### level 1
                         local i, m; integer i, m
                         # accessible: level 0 j, k; level 1 i, m
                         {  ### level 2
                            local m, k; real m, k
                            # accessible: level 0 j; level 1 i; level 2 m, k
                            }
                         }
                      
                      end















                                         - 21 -                              




            Ratfor User's Guide                                              


                                RRRaaatttfffooorrr CCCooonnntttrrrooolll SSStttaaattteeemmmeeennntttsss


                 As  was  said  by  Kernighan  and Plauger in _S_o_f_t_w_a_r_e _T_o_o_l_s,
            except for the control  structures,  "Ratfor  is  Fortran."   The
            additional  control  structures  just  serve  to give Fortran the
            capabilities that already exist in Algol, Pascal, and PL/I.


            CCCooommmpppooouuunnnddd SSStttaaattteeemmmeeennntttsss

                 Ratfor allows the specification of a compound  statement  by
            surrounding a group of Ratfor statements with braces ("{}"), just
            like bbbeeegggiiinnn --- eeennnddd in Algol or Pascal, or dddooo --- eeennnddd in PL/I.  A com-
            pound  statement  may  appear  anywhere  a  single  statement may
            appear, and is considered to be equivalent to a single  statement
            when used within the scope of a Ratfor control statement.

                 There is normally no need for a compound statement to appear
            by itself -- compound statements usually appear in the context of
            a  control  structure -- but for completeness, here is an example
            of a compound statement.

                      {     # end of line -- set to beginning of next line
                         line = line + 1
                         col = 1
                         end_of_line = YES
                         }



            IIIfff --- EEElllssseee

                 The Ratfor iiifff statement  is  much  more  flexible  than  its
            Fortran   counterpart.    In  addition  to  allowing  a  compound
            statement as an alternative, the Ratfor iiifff includes  an  optional
            eeelllssseee  statement  to  allow  the  specification  of an alternative
            statement.   Here  is  the  complete  syntax  of  the  Ratfor  iiifff
            statement:

                      if (<condition>) <statement1>
                      [else <statement2>]

            <Condition>  is  an  ordinary  Fortran  logical  expression.   If
            <condition>  is  true,  <statement1>  will   be   executed.    If
            <condition>  is  false  and  the  eeelllssseee  alternative is specified,
            <statement2> will be  executed.   Otherwise,  if  <condition>  is
            false  and the eeelllssseee alternative has not been specified, no action
            occurs.

                 Both  <statement1>  and   <statement2>   may   be   compound
            statements  or  may  be  further  iiifff  statements.  In the case of
            nested iiifff statements where one or more eeelllssseee alternatives are  not
            specified,  each  eeelllssseee is paired with the most recently occurring
            iiifff that has not already been paired with an eeelllssseee...



                                         - 22 -                              




            Ratfor User's Guide                                              


                 Although deep nesting of iiifff  statements  hinders  understan-
            ding,  one  situation often occurs when it is necessary to select
            one and only one of a set of alternatives based on  several  con-
            ditions.  This can be nicely represented with a chain of iiifff --- eeelll-
            ssseee iiifff --- eeelllssseee iiifff ... ... ... eeelllssseee statements.  For example,

                      if (color == RED)
                         call process_red
                      else if (color == BLUE | color == GREEN)
                         call process_blue_green
                      else if (color == YELLOW)
                         call process_yellow
                      else
                         call color_error

            could be used to select a routine for processing based on color.


            WWWhhhiiillleee

                 The  Ratfor  wwwhhhiiillleee  statement  allows  the  repetition  of a
            statement (or compound statement) as long as a  specified  condi-
            tion  is  met.  The Ratfor wwwhhhiiillleee loop is a "test at the top" loop
            exactly like the Pascal wwwhhhiiillleee and the PL/I dddooo wwwhhhiiillleee...   The  wwwhhhiiillleee
            statement has the following syntax:

                      while (<condition>)
                         <statement>

            If  <condition>  is  false, control passes beyond the loop to the
            next  statement  in  the  program;  if   <condition>   is   true,
            <statement>  is  executed and <condition> is retested.  As should
            be expected, if <condition> is false  when  the  wwwhhhiiillleee  is  first
            entered, <statement> will be executed _z_e_r_o times.

                 The  wwwhhhiiillleee  statement  is  very  handy  for controlling such
            things as skipping blanks in strings:

                      while (str (i) == BLANK)
                         i = i + 1

            And of course, <statement> may also be a compound statement:

                      while (getlin (buf, STDIN) ~= EOF) {
                         call process (buf)
                         call output (buf)
                         }



            RRReeepppeeeaaattt

                 The Ratfor rrreeepppeeeaaattt loop  allows  repetitive  execution  of  a
            statement  until  a  specified condition is met.  But, unlike the
            wwwhhhiiillleee loop, the test is made at the bottom of the loop,  so  that
            the  controlled  statement  will  be executed at least once.  The


                                         - 23 -                              




            Ratfor User's Guide                                              


            rrreeepppeeeaaattt loop has syntax as follows:

                      repeat
                         <statement>
                         [until (<condition>)]

            When  the  rrreeepppeeeaaattt  statement  is  encountered,   <statement>   is
            executed.   If  <condition>  is found to be false, <statement> is
            reexecuted and the <condition> is  retested.   Otherwise  control
            passes  to the statement following the rrreeepppeeeaaattt loop.  If the uuunnntttiiilll
            portion of the  loop  is  omitted,  the  loop  is  considered  an
            "infinite  repeat"  and  must  be  terminated  within <statement>
            (usually with a bbbrrreeeaaakkk or rrreeetttuuurrrnnn statement).  Pascal users  should
            note  that  the  scope  of  the  Ratfor  rrreeepppeeeaaattt  is only a single
            <statement> (which of course may be compound).

                 RRReeepppeeeaaattt loops, as opposed to wwwhhhiiillleee loops, are used  when  the
            controlled  statement must be evaluated at least once.  For exam-
            ple,

                      repeat
                         call get_next_token (token)
                         until (token ~= BLANK_TOKEN)

            The "infinite repeat"  is  often  useful  when  a  loop  must  be
            terminated "in the middle:"

                      repeat {
                         call get_next_input (inp)
                         call check_syntax (inp, error_flag)
                         if (error_flag == NO)
                            return
                         call syntax_error (inp)    # go back and get another
                         }



            DDDooo

                 Ratfor  provides  access  to  the Fortran dddooo statement.  The
            Ratfor dddooo statement is identical to the Fortran dddooo except that it
            does not use a statement label to delimit its scope.  The  Ratfor
            dddooo statement has the following syntax:

                      do <limits>
                         <statement>

            <Limits>  is  the normal Fortran notation for the limits of a dddooo,,,
            such as "i = 1, 10" or "j = 5, 20,  2".   The  same  restrictions
            apply  to  <limits>  as  apply  to  the limits in the Fortran dddooo...
            <Statement> is any Ratfor statement (which may be compound).

                 The Ratfor dddooo statement is just like  the  standard  Fortran
            one-trip  dddooo  loop -- <statement> will be executed at least once,
            regardless of the limits.  Also, the  value  of  the  dddooo  control
            variable is not defined on exit from the loop.


                                         - 24 -                              




            Ratfor User's Guide                                              


                 The  dddooo  loop can be used for array initialization and other
            such things  that  can  never  require  "zero  trips",  since  it
            produces  _s_l_i_g_h_t_l_y  more  efficient  object  code  than  the  fffooorrr
            statement (which we will get to next).

                      do i = 1, 10
                         array (i) = 0


                 One slight irregularity in the  Ratfor  syntax  occurs  when
            <statement> appears on the same line as the dddooo...  Since 'rp' knows
            very  little about Fortran, it assumes that the <limits> continue
            until a statement delimiter.  This means that the  <limits>  must
            be followed by a semicolon if <statement> is to begin on the same
            line.  This often occurs when a compound statement is to be used:

                      do i = 1, 10; {
                         array_1 (i) = 0
                         array_2 (i) = 0
                         }



            FFFooorrr

                 The Ratfor fffooorrr statement is an all-purpose looping construct
            that takes the best features of both the wwwhhhiiillleee and dddooo statements,
            while allowing more flexibility.  The syntax of the fffooorrr statement
            is as follows:

                      for (<initialize>; <condition>; <reinitialize>)
                         <statement>

            When   the   fffooorrr   is  executed,  the  statement  represented  by
            <initialize>  is  executed.   Then,  if  <condition>   is   true,
            <statement> is executed, followed by the statement represented by
            <reinitialize>.   Then, <condition> is retested, etc.  Any or all
            of <initialize>, <condition>, or <reinitialize> may  be  omitted;
            the   semicolons,  however,  must  remain.   If  <initialize>  or
            <reinitialize> is omitted, no action is performed in their place.
            If <condition> is omitted, an "infinite loop" is assumed.   (Both
            <initialize> or <reinitialize> may be compound statements).

                 As   you  can  see,  the  fffooorrr  loop  with  <initialize>  and
            <reinitialize> omitted is identical to the wwwhhhiiillleee loop.  With  the
            addition  of <initialize> and <reinitialize>, a zero-trip dddooo loop
            can be constructed.  For instance,

                      for (i = 1; i <= 10; i += 1) {
                         array_1 (i) = 0
                         array_2 (i) = 0
                         }

            is identical to the last dddooo example, but given a certain combina-
            tion of limits, the fffooorrr loop would execute <statement> zero times
            while the dddooo loop would execute it once.


                                         - 25 -                              




            Ratfor User's Guide                                              


                 The fffooorrr loop can do many things not possible with a dddooo loop,
            since  the  fffooorrr  loop  is  not  constrained  to   the   ascending
            incrementation  of an index.  As an example, assume a list struc-
            ture in which "list" contains the index of the first  item  in  a
            list, and the first position in each list item contains the index
            of the next.  The fffooorrr statement could be used to serially examine
            the list:

                      for (ptr = list; ptr ~= NULL; ptr = array (ptr)){
                         [ examine the item beginning at array (ptr + 1) ]
                         }



            BBBrrreeeaaakkk

                 The  bbbrrreeeaaakkk statement allows the early termination of a loop.
            The statement

                      break [<level>]

            will cause the immediate  termination  of  <level>  loops,  where
            <level>,  if specified, is an integer in the range 1 to the depth
            of loop nesting at the point the bbbrrreeeaaakkk statement appears.   Where
            <level> is omitted, only the innermost loop surrounding the bbbrrreeeaaakkk
            is terminated.

                 In the following example, the bbbrrreeeaaakkk statement will cause the
            termination  of  the  inner fffooorrr loop if a blank is encountered in
            'str':

                      while (getlin (str, STDIN) ~= EOF) {
                         for (i = 1; str (i) ~= EOS; i += 1)
                            if (str (i) == BLANK)
                               break
                      
                         str (i) = EOS        # output just the first word
                         call putlin (str, STDOUT)
                         call putch (NEWLINE, STDOUT)
                         }

            Replacing the bbbrrreeeaaakkk statement with "break 1" would  have  exactly
            the  same  effect.   However,  replacing  it with "break 2" would
            cause termination of both the inner fffooorrr and  outer  wwwhhhiiillleee  loops.
            Unless  this  fragment  is  nested  inside  other  loops, a value
            greater than 2 would be an error.


            NNNeeexxxttt

                 The nnneeexxxttt statement is very similar to the  bbbrrreeeaaakkk  statement,
            except that a statement of the form

                      next [<level>]

            causes termination of <level> - 1 nested loops (zero when <level>


                                         - 26 -                              




            Ratfor User's Guide                                              


            is  omitted).   Execution then resumes with the _n_e_x_t iteration of
            the innermost active loop.  <Level>, if specified,  is  again  an
            integer  in  the  range  1  to  the  depth  of  loop nesting that
            specifies which loop (from inside  out)  is  to  begin  its  next
            iteration.

                 In  this  example, the nnneeexxxttt statement will cause the proces-
            sing to be skipped when an array element with the value  "UNUSED"
            is encountered.

                      for (i = 1; i <= 10; i += 1)
                         for (j = 1; j <= 10; j += 1) {
                            if (array (i, j) == UNUSED)
                               next
                      
                            # process array (i, j)
                      
                            }

            When  an  array  element  with the value "UNUSED" is encountered,
            execution of the nnneeexxxttt statement causes the <reinitialize> portion
            of the innermost fffooorrr statement, "j += 1", to be  executed  before
            the  next  iteration  of  the inner loop begins.  You should note
            that when used with a fffooorrr statement, nnneeexxxttt  always  skips  to  the
            <reinitialize> part of the appropriate fffooorrr loop.

                 If  the statement "next 2" had been used in place of "next",
            the inner fffooorrr loop would have been terminated, and the "i  +=  1"
            of the outer fffooorrr loop would have been executed in preparation for
            its next iteration.


            RRReeetttuuurrrnnn

                 The  Ratfor  rrreeetttuuurrrnnn  statement normally behaves exactly like
            the Fortran rrreeetttuuurrrnnn statement in all but one case.  In this  case,
            Ratfor  allows  a  parenthesized expression to follow the keyword
            rrreeetttuuurrrnnn inside a function subprogram.  The value of  this  expres-
            sion  is  then  assigned to the function name as the value of the
            function before the return is executed.   This  is  just  another
            shorthand and does not provide any additional functionality.

                 Normally  in  a  Fortran  function  subprogram, you place an
            assignment statement that assigns a value to  the  function  name
            before the rrreeetttuuurrrnnn statement, like this:

                      integer function calc (x, y, z)
                      ...
                      calc = x + y - z
                      return
                      ...

            If  you  like, Ratfor allows you to express the same actions with
            one line less code:




                                         - 27 -                              




            Ratfor User's Guide                                              


                      integer function calc (x, y, z)
                      ...
                      return (x + y - z)
                      ...

            This segment performs exactly the same function as the  preceding
            segment.


            SSSeeellleeecccttt

                 The  Ratfor  ssseeellleeecccttt  statement  allows  the  selection  of a
            statement from several alternatives, based either on the value of
            an integer variable or on the outcome  of  several  logical  con-
            ditions.  A ssseeellleeecccttt statement of the form

                      select
                         when (<expression list 1>)
                            <statement 1>
                         when (<expression list 2>)
                            <statement 2>
                         ...
                         when (<expression list n>)
                            <statement n>
                      [ifany
                         <statement n+1>]
                      [else
                         <statement n+2>]

            (where  <expression  list>  is  a comma-separated list of logical
            expressions) performs almost the same function as a chain of iiifff ---
            eeelllssseee iiifff ...  ...  ...  eeelllssseee statements.  Each <logical  expression>  is
          | evaluated  in  turn,  and  when  the  first  true  expression  is
          | encountered, the corresponding statement  is  executed.   If  any
            wwwhhheeennn  alternative is selected, the statement in the iiifffaaannnyyy part is
            executed.  If none of the wwwhhheeennn  alternatives  are  selected,  the
            statement in the eeelllssseee part is executed.

                 Although its function is very similar to an iiifff --- eeelllssseee chain,
            a ssseeellleeecccttt statement has two distinct advantages.  First, it allows
            the "ifany" alternative -- a way to implement a rather frequently
            encountered  control structure without repeated code or procedure
            calls.  Second, it places all the logical expressions in the same
            basic optimization block, so that even a  dumb  Fortran  compiler
            can optimize register loads and stores.

                 For  example,  assume  that  we  want to check to see if the
            variable 'color' contains a valid color, namely 'RED',  'YELLOW',
            'BLUE',  or  'GREEN'.  If it does, we want to executed one of the
            three    subroutines    'process_red',    'process_yellow',    or
            'process_blue_green'  and  set  the  flag  'color_valid'  to YES.
            Otherwise, we want to set the  'color_valid'  to  NO.   A  ssseeellleeecccttt
            statement performs this trick nicely, with no repeated code:





                                         - 28 -                              




            Ratfor User's Guide                                              


                      select
                         when (color == RED)
                            call process_red
                         when (color == YELLOW)
                            call process_yellow
                         when (color == BLUE, color == GREEN)
                            call process_blue_green
                      ifany
                         color_valid = YES
                      else
                         color_valid = NO


                 The second variant of the select statement allows the selec-
            tion  of a statement based on the value of an integer (or charac-
            ter) expression.  It has almost exactly the same  syntax  as  the
            logical variant:

                      select (<integer expression>)
                         when (<expression list 1>)
                            <statement 1>
                         when (<expression list 2>)
                            <statement 2>
                         ...
                         when (<expression list n>)
                            <statement n>
                      [ifany
                         <statement n+1>]
                      [else
                         <statement n+2>]

            Using  this  variant,  a  statement  is  selected when one of its
            corresponding integer expressions  has  the  same  value  as  the
            <integer  expression> following the 'select'.  The iiifffaaannnyyy and eeelllssseee
            clause behave as they  do  in  the  logical  variant.   The  most
            visible  difference,  though,  is that the order of evaluation of
            the integer expressions is not specified.  If two values  in  two
            expression  lists  are identical, it is difficult to say which of
            the statements will be executed; it can only be said that one and
            only one will be executed.

                 The  integer  variant  offers  one  further  advantage.   If
            elements  in the expression lists are integer or single-character
            constants, 'rp' will generate Fortran computed  gggoootttooo  statements,
            rather  than Fortran iiifff statements, where possible.  This code is
            usually considerably  faster  and  more  compact  than  the  code
            generated by iiifff statements.

                 The  example  given  for the logical variant of ssseeellleeecccttt would
            really be much more easily done with the integer variant:








                                         - 29 -                              




            Ratfor User's Guide                                              


                      select (color)
                         when (RED)
                            call process_red
                         when (YELLOW)
                            call process_yellow
                         when (BLUE, GREEN)
                            call process_blue_green
                      ifany
                         color_valid = YES
                      else
                         color_valid = NO


                 As a final example of ssseeellleeecccttt,,, the following program fragment
            selects an insert, update, delete, or print routine based on  the
            input codes "i", "u", "d" or "p":

                      while (getlin (buf, STDIN) ~= EOF)
                      
                         select (buf (1))
                            when ('i'c, 'I'c)    # insert record
                               call insert_record
                            when ('u'c, 'U'c) {  # update record
                               call delete_record
                               call insert_record
                               }
                            when ('d'c, 'D'c)    # delete record
                               call delete_record
                            when ('p'c, 'P'c)    # print record
                               ;
                         ifany                   # always print after command
                            call print_record
                         else                    # illegal input
                            call command_error

            This example shows the use of both a compound statement within an
            alternative  (the  "update"  action deletes the target record and
            then inserts a new version), and a null statement consisting of a
            single semicolon.


            PPPrrroooccceeeddduuurrreee

                 Procedures are a convenient and useful structuring mechanism
            for programs, but in Fortran there often reasons for  restricting
            the unbridled use of procedures.  Among these reasons are (1) the
            run-time  expense  of  procedure  calls,  and argument and common
            block addressing; (2) external name  space  congestion;  and  (3)
            difficulty  in  detecting  errors  in  parameter and common-block
            correspondence.  Ratfor attempts to  address  these  problems  by
            allowing  declaration  of  procedures  within Fortran subprograms
            that are inexpensive to call (an assignment and two  gggoootttooosss))),,,  are
            not externally visible, and allow access to global variables.  In
            addition, when correctly declared, Ratfor internal procedures can
            call   each   other   recursively   without  requiring  recursive
            procedures in the host Fortran.


                                         - 30 -                              




            Ratfor User's Guide                                              


                 Currently, Ratfor internal procedures  do  not  provide  the
            same level of functionality as Fortran subroutines and functions:
            internal  procedure  parameters must be scalars and are passed by
            value, internal procedures cannot be used as functions (they can-
            not return values), and no automatic storage  is  available  with
            recursive  integer procedures.  But even with these restrictions,
            internal procedures can significantly improve the readability and
            modularity of Ratfor code.

                 Internal procedures are declared with the  Ratfor  ppprrroooccceeeddduuurrreee
            statement.   Internal  procedures  may  be declared anywhere in a
            program, but a declaration must appear before any of  its  calls.
            Here is an example of a non-recursive procedure declaration:

                      # putchar --- put a character in the output string
                         procedure putchar (ch) {
                      
                            character ch
                      
                            str (i) = ch
                            i += 1
                            }

            This  procedure  has  one parameter, "ch", which must appear in a
            type declaration inside the procedure.

                 Internal procedures always exit by falling through  the  end
            of  the  compound  statement.   A rrreeetttuuurrrnnn statement in an internal
            procedure will return from the Fortran subprogram  in  which  the
            internal procedure is declared.

                 After  the  above declaration, "putchar" can be subsequently
            called in one of two ways:

                      putchar ('='c)
                      
                      -or-
                      
                      call putchar ('='c)

            The second form is preferable, so that a procedure  can  be  con-
            verted to a subroutine, and vice-versa.  The number of parameters
            in  the  call  must  always match the number of parameters in the
            declaration.  If parameter list is omitted  in  the  declaration,
            then it also must be omitted in its calls.

                 If "putchar" were recursive, the declaration would be

                      procedure putchar (ch) recursive 128

            The value "128" is an integer constant that is the maximum number
            of recursive calls to "putchar" outstanding at any one time.

                 Since  internal  procedures  may  be mutually recursive, and
            since they must be  declared  textually  before  they  are  used,
            procedures  may be declared "forward" by separating the procedure


                                         - 31 -                              




            Ratfor User's Guide                                              


            declaration from its body.  Here is "putchar"  declared  using  a
            "forward" declaration:

                      procedure putchar (ch) forward
                      
                      ...
                      
                      # putchar --- put a character in the output string
                         procedure putchar {
                      
                            character ch
                      
                            str (i) = ch
                            i += 1
                            }

            As  you  can  see,  the  parameters  must appear in the "forward"
            declaration; they may appear in the  body  declaration,  but  are
            ignored.   For maximum efficiency, all internal procedures should
            be presented in a "forward" declaration.   The  procedure  bodies
          | should  then be declared after the final rrreeetttuuurrrnnn or ssstttoooppp statement
          | in the body of the Fortran subprogram, but before the terminating
          | eeennnddd statement (then the program never  has  to  jump  around  the
            procedure body).

                 In  general,  a  ppprrroooccceeeddduuurrreee  declaration contains five parts:
            the word "procedure", the procedure name,  an  optional  list  of
            formal  parameters,  an  optional "recursive <integer>" part, and
            either a compound statement or the word "forward".   An  internal
            procedure  call  consists  of  three  parts:  optionally the word
            "call", the procedure name, and an optional parameter list.



























                                         - 32 -                              




            Ratfor User's Guide                                              


                                ___RRR___aaa___ttt___fff___ooo___rrr___ ___LLL___aaa___nnn___ggg___uuu___aaa___ggg___eee___ ___RRR___eee___fff___eee___rrr___eee___nnn___ccc___eee




                 This section contains a summary of  the  Ratfor  syntax  and
            source program format.  In addition to serving as a reference for
            Ratfor,  it  can  also  be  used  by someone who is familiar with
            Fortran and wants to quickly gain a reading knowledge of Ratfor.



                         DDDiiiffffffeeerrreeennnccceeesss BBBeeetttwwweeeeeennn RRRaaatttfffooorrr aaannnddd FFFooorrrtttrrraaannn


            SSSooouuurrrccceee PPPrrrooogggrrraaammm FFFooorrrmmmaaattt

            -    'Rp' is sensitive to letter case.  Keywords must appear
                 in lower case.  Case is significant in identifiers.

            -    'Rp' is blank sensitive in  that  words  (sequences  of
                 letters, digits, dollar signs, and underscores) must be
                 separated by special characters _o_r blanks.

            -    'Rp'  is not sensitive to card columns.  Statements may
                 begin at any position on a line.

            -    'Rp' allows multiple statements per line by  separating
                 the statements with semicolons.

            -    A  Ratfor  statement  may  be  labeled  by  placing the
                 numeric label in front of  the  statement.   The  label
                 must  be  separated  from the statement by at least one
                 space.

            -    'Rp' will expect a continuation line if it encounters a
                 line ending with a trailing  comma,  a  condition  with
                 unbalanced parentheses, a missing statement following a
                 control  statement,  or  a  line ending with a trailing
                 underscore.

            -    Any line may contain a comment.  Comments begin with  a
                 sharp  sign  ("#")  and  continue  until the end of the
                 line.



            IIIdddeeennntttiiifffiiieeerrrsss

                 Ratfor identifiers consist of letters, digits,  underscores,
            dollar  signs,  and  may  be  up  to  100  characters  long.   An
            identifier must begin with a letter.  Underscores may be included
            for readability, but are completely ignored.  An  identifier  may
            not  be the same as a Fortran or Ratfor keyword.  'Rp' transforms
            all long Ratfor identifiers into unique Fortran identifiers.



                                         - 33 -                              




            Ratfor User's Guide                                              


            IIInnnttteeegggeeerrr CCCooonnnssstttaaannntttsss

                 'Rp' allows integer constants of the form  "<base>r<number>"
            where  <base>  is an integer between 2 and 16.  The letters "a" -
            "f" are used for digits in bases greater than 10.


            SSStttrrriiinnnggg CCCooonnnssstttaaannntttsss

                 String constants in Ratfor consist of a string  body  and  a
            string  format indicator.  The string body is a group of strings,
            bounded by quotes, and possibly separated by blanks.  The  string
            format  indicator  designates  the data representation to be used
            for the characters in the string body.  It has one of the follow-
            ing values:

            omitted  Fortran Hollerith string.  A standard Fortran  Hollerith
                     constant  is  generated.  Characters are left-justified,
                     packed in words (two characters per word on the  Prime),
                     and  unused  positions  on  the  right  are  filled with
                     blanks.

            c        Single character constant.  A single character  constant
                     is  generated.   The  character  is  right-justified and
                     zero-filled on the left in a word.  Only  one  character
                     is  allowed  in  the  body of the constant.  This is the
                     preferred  format  for  all  single  characters  in  the
                     Software Tools Subsystem.

            p        Packed  (Hollerith)  period-terminated  string.  The 'p'
                     format indicator causes the generation of a Fortran Hol-
                     lerith constant.  All periods in  the  string  body  are
                     preceded by an escape character ("@").

            v        PL/I character varying string.  Fortran declarations are
                     generated  to  create  a  PL/I character varying string.
                     "V"  format  string  constants  may  only  be  used   in
                     executable statements.

            s        EOS-terminated  unpacked  string.   Fortran declarations
                     are generated  to  construct  an  array  in  which  each
                     element  contains  one  character  of  the  string body,
                     right-justified and zero-filled (each  character  is  in
                     the  same  format  as  is  generated  by  the "c" format
                     indicator).  Following the characters is a word contain-
                     ing the  value  EOS.   EOS-terminated  strings  are  the
                     preferred format for multi-character strings in the Sub-
                     system.  "S" format string constants may only be used in
                     executable statements.


            LLLooogggiiicccaaalll aaannnddd RRReeelllaaatttiiiooonnnaaalll OOOpppeeerrraaatttooorrrsss

                 Ratfor  allows  the  use  of graphic characters to represent
            logical and relational operators instead of  the  Fortran  ".EQ."
            and  such.   These  characters  will be replaced by their Fortran


                                         - 34 -                              




            Ratfor User's Guide                                              


            equivalents during preprocessing.  The following table shows  the
            equivalent syntaxes:


                      _R_a_t_f_o_r   _F_o_r_t_r_a_n   _F_u_n_c_t_i_o_n

                      >        .GT.      Greater than
                      >=       .GE.      Greater or equal
                      <        .LT.      Less than
                      <=       .LE.      Less or equal
                      ==       .EQ.      Equal to
                      ~=       .NE.      Not equal to

                      ~        .NOT.     Logical negation
                      &        .AND.     Logical conjunction
                      |        .OR.      Logical disjunction

                      &&       (none)    Short-circuited conjunction
                      ||       (none)    Short-circuited disjunction


            Note that the digraphs shown in the table must appear in the Rat-
            for   program  with  no  imbedded  spaces.   The  short-circuited
            operators may appear only  in  the  <condition>  part  of  Ratfor
            control statements.


            AAAssssssiiigggnnnmmmeeennnttt OOOpppeeerrraaatttooorrrsss

                 Assignment  operators  provide  a  shorthand  for the common
            Fortran idiom "<v> = <v> <op> <expr>".  Assignment operators  may
            appear  anywhere  a Fortran assignment statement may appear.  The
            following assignment operators are available in Ratfor:

                   _O_p_e_r_a_t_o_r       _U_s_e             _R_e_s_u_l_t
                      
                      +=       <v> += <e>      <v> = <v> + (<e>)
                      -=       <v> -= <e>      <v> = <v> - (<e>)
                      *=       <v> *= <e>      <v> = <v> * (<e>)
                      /=       <v> /= <e>      <v> = <v> / (<e>)
                      %=       <v> %= <e>      <v> = mod (<v>, <e>)
                      &=       <v> &= <e>      <v> = and (<v>, <e>)
                      |=       <v> |= <e>      <v> = or (<v>, <e>)
                      ^=       <v> ^= <e>      <v> = xor (<v>, <e>)



            EEEssscccaaapppeee SSStttaaattteeemmmeeennntttsss

                 Escape statements can be used to output  Fortran  statements
            that  will not be touched by the Ratfor preprocessor.  The escape
            statement has three possible forms.  In  the  first  form  listed
            below,  the first non-blank character of the Fortran statement is
            output in column seven.  In the second form, the first  non-blank
            character of the Fortran statement is output in column seven, but
            column  six  contains  a  "$"  to  continue  a  previous  Fortran


                                         - 35 -                              




            Ratfor User's Guide                                              


            statement to  that  stream.   In  the  third  form,  the  Fortran
            statement  is output starting in column one, so that the user has
            full control of the placement of items on the line.  The  follow-
            ing is a summary of this description:

                      _E_s_c_a_p_e _S_t_a_t_e_m_e_n_t _F_o_r_m_a_t            _O_u_t_p_u_t _C_o_l_u_m_n

                      %<stream><Fortran statement>             7
                      %<stream>&<Fortran statement>            6
                      %<stream>%<Fortran statement>            1

            "Stream" can take on the following values:

                      1           declaration
                      2           data
                      3           code

          | If no stream value is given, it is assumed to be the code stream.
          | Escaped  statements have to come between a fffuuunnnccctttiiiooonnn or sssuuubbbrrrooouuutttiiinnneee
          | statement and the corresponding eeennnddd statement.


            IIInnncccooommmpppaaatttiiibbbiiillliiitttiiieeesss

                 Even with the great similarities between Fortran and Ratfor,
            an arbitrary Fortran program is _n_o_t necessarily a correct  Ratfor
            program.  Several areas of incompatibilities exist:

            -    Blanks are significant -- at least one space or special
                 character   must   separate   adjacent   keywords   and
                 identifiers.

            -    The Ratfor dddooo statement does not  contain  a  statement
                 number  following  the  "do".  Its range always extends
                 over the next statement.

            -    Two word Fortran key phrases such as  dddooouuubbbllleee  ppprrreeeccciiisssiiiooonnn
                 must  be  presented as a single Ratfor identifier (e.g.
                 "doubleprecision" or "double_precision").

            -    Fortran statement functions must  be  preceded  by  the
                 Ratfor  keyword  ssstttmmmtttfffuuunnnccc...   To  assure  that they will
                 appear in the correct order in the Fortran, they should
                 immediately precede the eeennnddd statement  of  the  program
                 unit.

            -    Hollerith  literals  (i.e.   5HABCDE)  are  not allowed
                 anywhere in a Ratfor program.   Instead,  'rp'  expects
                 all  Hollerith  literals  to  be  enclosed in single or
                 double quotes (i.e.  "ABCDE" or 'ABCDE').

            -    'Rp' does not allow Fortran comments.  Ratfor  comments
                 must be introduced by a sharp sign ("#").

            -    'Rp'  does  not  accept  the  Fortran continuation con-
                 vention.  Continuation is implicit for any line  ending


                                         - 36 -                              




            Ratfor User's Guide                                              


                 with  a  comma, or any conditional statement containing
                 unbalanced parentheses.  Continuation between arbitrary
                 words  may  be  indicated  by  placing  an  underscore,
                 preceded  by at least one space, at the end of the line
                 to be continued.

            -    'Rp' does not ignore text beyond column 72.

            -    Fortran  and  Ratfor  keywords  may  not  be  used   as
                 identifiers in a Ratfor program.  Their use will result
                 in unreasonable behavior.



                           RRRaaatttfffooorrr TTTeeexxxttt SSSuuubbbssstttiiitttuuutttiiiooonnn SSStttaaattteeemmmeeennntttsss


            dddeeefffiiinnneee (((<<<iiidddeeennntttiiifffiiieeerrr>>> [[[(((<<<fffooorrrmmmaaalll pppaaarrraaammmsss>>>)))]]],,, <<<rrreeeppplllaaaccceeemmmeeennnttt ttteeexxxttt>>>)))

                 When  a dddeeefffiiinnneee statement is encountered in a source program,
            <replacement  text>  is   recorded   as   the   replacement   for
            <identifier>.   If  <identifier>  is  encountered  later  in  the
            program, it will be replaced by <replacement text>.   If  <formal
            params>  was  present  in the definition of <identifier>, and the
            subsequent  occurrence  of  <identifier>   is   followed   by   a
            parenthesized,  comma-separated  list  of strings, occurrences of
            the formal parameters in <replacement text> will be  replaced  by
            the corresponding strings in the actual parameter list.

                 <Identifier>  must be an alphabetic Ratfor identifier, while
            <replacement text> may contain any  characters  except  unmatched
            quotes or parentheses.  <Formal params> must be a comma-separated
            list  of identifiers; corresponding actual parameters may contain
            any characters except unmatched quotes,  unbalanced  parentheses,
            or  unnested  commas.   During replacement, <replacement text> is
            also examined for occurrences  of  dddeeefffiiinnneeeddd  identifiers.   Formal
            parameter  replacement  occurs  on  identifiers  in  <replacement
            text>, even if  the  identifiers  are  surrounded  by  quotes  or
            parentheses.   Redefinition  of  an  <identifier>  causes the new
            <replacement text> to replace the old.


            uuunnndddeeefffiiinnneee (((<<<iiidddeeennntttiiifffiiieeerrr>>>)))

                 The   uuunnndddeeefffiiinnneee   statement   removes   the   definition   of
            <identifier>  from  the  list of defined identifiers.  Subsequent
            occurrences of <identifier> in the program will not  be  replaced
            unless <identifier> appears in a subsequent dddeeefffiiinnneee statement.


            iiinnncccllluuudddeee '''<<<pppaaattthhh nnnaaammmeee>>>'''

                 An  iiinnncccllluuudddeee  statement  instructs 'rp' to begin taking input
            from the file specified by <path name>.  When the end of the file
            is reached, 'rp' resumes taking input from  the  file  containing
            the iiinnncccllluuudddeee statement.  The path name may be surrounded by either


                                         - 37 -                              




            Ratfor User's Guide                                              


            single  or  double quotes.  The file specified by <path name> may
            contain further iiinnncccllluuudddeee statements, up to a maximum depth of 5.



                                   RRRaaatttfffooorrr DDDeeeccclllaaarrraaatttiiiooonnnsss


            llliiinnnkkkaaagggeee <<<iiidddeeennntttiiifffiiieeerrr>>> {{{ ,,, <<<iiidddeeennntttiiifffiiieeerrr>>> }}}

                 The llliiinnnkkkaaagggeee declaration  is  used  to  guarantee  that  long
            external names are transformed into the same unique Fortran name.
            Names  are  transformed  as  they  are  presented  in the llliiinnnkkkaaagggeee
            declaration.  The same llliiinnnkkkaaagggeee statement  should  appear  as  the
            first  statement  of  each separately compiled source module, and
            should contain the names of all subroutines, functions, and  com-
            mon blocks in the program.


            lllooocccaaalll <<<iiidddeeennntttiiifffiiieeerrr>>> {{{ ,,, <<<iiidddeeennntttiiifffiiieeerrr>>> }}}

                 The  lllooocccaaalll  declaration  allows the declaration of variables
            with names local to the scope of a  compound  statement  (block).
            The  lllooocccaaalll  declaration should appear inside a compound statement
            and must  precede  all  occurrences  of  the  identifiers  to  be
            declared  local  to  the  block.   All identifiers appearing in a
            lllooocccaaalll declaration must subsequently appear in a type  declaration
            in the same compound statement.


            ssstttrrriiinnnggg <<<nnnaaammmeee>>> <<<qqquuuooottteeeddd ssstttrrriiinnnggg>>>

                 The  ssstttrrriiinnnggg  statement  generates declarations to produce an
            EOS-terminated string  in  the  integer  array  <name>.   <Quoted
            string> must be surrounded by either single or double quotes.


            ssstttrrriiinnngggtttaaabbbllleee <<<iiinnndddeeexxx>>>,,, <<<bbbooodddyyy>>>,,, [[[ /// ]]] <<<iiittteeemmm>>> {{{ /// <<<iiittteeemmm }}}

                 The  ssstttrrriiinnngggtttaaabbbllleee  declaration  creates  a marginally indexed
            array of integers and character strings.  <Index> and <body>  are
            variables  to  be  declared  as the index and body arrays respec-
            tively.  <Body> is a one-dimensional array in  which  the  values
            generated  by  the  <item>s  are stored consecutively.  The first
            element of <index> contains the number of remaining  elements  in
            <index>;  subsequent elements each contain the index in <body> of
            the first position of the corresponding <item>.

            <Item>s are comma-separated lists of  integers,  single-character
            constants,  and  strings  (with  no  string  format  indicators).
            Integers and EOS-terminated  strings  are  generated  and  stored
            consecutively  in  <body>.   The first position of each <item> in
            <body> is stored in the corresponding entry of <index>.





                                         - 38 -                              




            Ratfor User's Guide                                              


                                RRRaaatttfffooorrr CCCooonnntttrrrooolll SSStttaaattteeemmmeeennntttsss


            bbbrrreeeaaakkk [[[<<<iiinnnttteeegggeeerrr>>>]]]

                 The bbbrrreeeaaakkk statement allows the user to terminate the  execu-
            tion  of  a  for, while, or repeat loop and resume control at the
            first statement following the loop.  The <integer> specifies  the
            number  of  loops to terminate; if absent, 1 is assumed (only the
            innermost loop is terminated).  If the integer is N, then  the  N
            innermost loops currently active are terminated.


            dddooo <<<llliiimmmiiitttsss>>>;;; <<<ssstttaaattteeemmmeeennnttt>>>

                 The  dddooo  statement  provides  a means of accessing the local
            Fortran do-statement.  <Limits> includes whatever parameters  are
            necessary  to  satisfy Fortran, minus the statement number of the
            last statement to be performed, which  is  generated  by  Ratfor.
            The  semicolon  must  not be used if the statement to be iterated
            does not appear on the same line as the dddooo...


            fffooorrr '''(((''' <<<iiinnniiittt>>>;;; <<<cccooonnndddiiitttiiiooonnn>>>;;; <<<rrreeeiiinnniiittt>>> ''')))''' <<<ssstttaaattteeemmmeeennnttt>>>

                 The fffooorrr statement  is  a  very  general  looping  construct.
            <init>  is  a  statement  to be executed before loop entry; it is
            frequently used to initialize a counter.  <Condition> is a condi-
            tion to be satisfied for every iteration; the condition is tested
            at the top of the loop.  <Condition> becoming false is  the  most
            often  used  method  of  terminating  the  loop.   <Reinit>  is a
            statement to be executed at the bottom of the loop, just before a
            jump is made to the top to test  the  <condition>.   <Reinit>  is
            usually  used  to  increment or decrement a counter.  <Statement>
            may be any legal Ratfor statement.


            iiifff '''(((''' <<<cccooonnndddiiitttiiiooonnn>>> ''')))''' <<<ssstttaaattteeemmmeeennnttt>>> [[[eeelllssseee <<<ssstttaaattteeemmmeeennnttt>>>]]]

                 IIIfff is a generalization of the Fortran logical-if  statement.
            If  the condition is true, the first <statement> is executed.  If
            the optional eeelllssseee clause is missing, control is  then  passed  to
            the  statement  following the iiifff;;; otherwise, the <statement> fol-
            lowing the eeelllssseee is executed before passing control.


            nnneeexxxttt [[[<<<iiinnnttteeegggeeerrr>>>]]]

                 The nnneeexxxttt statement complements the bbbrrreeeaaakkk statement.   It  is
            used  to  force the next iteration of a for, repeat or while loop
            to occur.  The parameter <integer> specifies the number of levels
            of nested loops to jump out; if omitted, the  innermost  loop  is
            continued;  otherwise,  for  <integer> = 2, the next-to-innermost
            loop is continued, etc.




                                         - 39 -                              




            Ratfor User's Guide                                              


            ppprrroooccceeeddduuurrreee <<<ppprrroooccciiiddd>>> [[[ '''(((''' <<<iiiddd>>> {{{,,, <<<iiiddd>>> }}} ''')))''' ]]]
                  [[[rrreeecccuuurrrsssiiivvveee <<<iiinnnttteeegggeeerrr>>>]]]
                  ((( fffooorrrwwwaaarrrddd ||| <<<cccooommmpppooouuunnnddd ssstttaaattteeemmmeeennnttt>>> )))
            
            [[[cccaaallllll]]] <<<ppprrroooccciiiddd>>> [[[ '''(((''' <<<eeexxxppprrr>>> {{{,,, <<<eeexxxppprrr>>> }}} ''')))''' ]]]

                 The ppprrroooccceeeddduuurrreee declaration allows the declaration of internal
            Ratfor  procedures.   <Procid>  is  the  name  of  the   internal
            procedure.    Formal   parameters   (scalar,  pass-by-value)  are
            declared following the <procid>.  Formal parameters  must  appear
            in  a  type  declaration  in  the  body of the procedure.  If the
            procedure is to be called recursively,  the  rrreeecccuuurrrsssiiivvveee  <<<iiinnnttteeegggeeerrr>>>
            clause  must  be  included;  <integer>  is  the maximum number of
            recursive calls in process at  any  given  time.   Following  the
            heading,  either  a  compound  statement or the word fffooorrrwwwaaarrrddd must
            appear.  If the fffooorrrwwwaaarrrddd option is used, a  ppprrroooccceeeddduuurrreee  declaration
            containing  <compound statement> must follow at some point in the
            program unit.  Formal parameters specified on the second declara-
            tion may be present, but are ignored.

                 A <procid> must be defined before  it  is  referenced  by  a
            call.  The call can appear exactly as a Fortran call, or the word
            cccaaallllll can be omitted.  Actual parameters must correspond in number
            to  formal  parameters.  If the formal parameters list is omitted
            in the declaration, no actual parameter list may be present.


            rrreeepppeeeaaattt <<<ssstttaaattteeemmmeeennnttt>>> [[[uuunnntttiiilll '''(((''' <<<cccooonnndddiiitttiiiooonnn>>> ''')))''']]]

                 The rrreeepppeeeaaattt statement is used to generate  a  loop  with  the
            iteration test at the bottom.  The <statement> is performed, then
            the  <condition>  checked; if false, the <statement> is repeated.
            If true, control passes to the statement following the uuunnntttiiilll...  If
            the uuunnntttiiilll is omitted, the loop is repeated indefinitely, and must
            be terminated with a ssstttoooppp,,, bbbrrreeeaaakkk,,, or gggoootttooo...


            rrreeetttuuurrrnnn [[['''(((''' <<<eeexxxppprrreeessssssiiiooonnn>>> ''')))''']]]

                 The  rrreeetttuuurrrnnn  statement  behaves  exactly  like  its  Fortran
            counterpart, except that if the optional parenthesized expression
            is   included   inside   a  function  subprogram,  the  value  of
            <expression> will be assigned to the function name as  the  func-
            tion value before the return is executed.


            ssseeellleeecccttt
                {{{wwwhhheeennn '''(((''' <<<cccooonnndddiiitttiiiooonnn>>> {{{,,, <<<cccooonnndddiiitttiiiooonnn>>>}}} ''')))''' <<<ssstttaaattteeemmmeeennnttt>>> }}}
                [[[iiifffaaannnyyy <<<ssstttaaattteeemmmeeennnttt>>>]]] [[[eeelllssseee <<<ssstttaaattteeemmmeeennnttt>>>]]]
            
            ssseeellleeecccttt '''(((''' <<<iiinnnttteeegggeeerrr eeexxxppprrr>>> ''')))'''
                {{{wwwhhheeennn '''(((''' <<<iiinnnttteeegggeeerrr eeexxxppprrr>>> {{{,,, <<<iiinnnttteeegggeeerrr eeexxxppprrr>>>}}} ''')))''' <<<ssstttaaattteeemmmeeennnttt>>>
                [[[iiifffaaannnyyy <<<ssstttaaattteeemmmeeennnttt>>>]]] [[[eeelllssseee <<<ssstttaaattteeemmmeeennnttt>>>]]]

                 SSSeeellleeecccttt  is  a  generalization  of  the iiifff statement.  In its
            first alternative, the wwwhhheeennn <conditions>s are evaluated in order;


                                         - 40 -                              




            Ratfor User's Guide                                              


            the <statement> associated with the first one found to be true is
            executed.  If any <condition>  is  found  true,  the  <statement>
            associated  with  iiifffaaannnyyy  is executed; if none are found true, the
            <statement> associated with eeelllssseee is executed.

                 Similarly, in the second  alternative,  the  <integer  expr>
            associated with ssseeellleeecccttt is evaluated.  The result is then compared
            to  the  <integer  expr>s  associated  with  the wwwhhheeennn parts in an
            unspecified  order.   When  an  equal  comparison  is  made,  the
            <statement>  following the corresponding wwwhhheeennn is executed.  If an
            equal comparison is made,  the  <statement>  following  iiifffaaannnyyy  is
            executed; if no equal comparison is made, the <statement> follow-
            ing eeelllssseee is executed.


            wwwhhhiiillleee '''(((''' <<<cccooonnndddiiitttiiiooonnn>>> ''')))''' <<<ssstttaaattteeemmmeeennnttt>>>

                 The  wwwhhhiiillleee statement is the basic test-at-the-top loop.  The
            <condition> is evaluated; if true, the  <statement>  is  executed
            and  the  loop  is  repeated,  otherwise  control  passes  to the
            statement following the loop.





































                                         - 41 -                              




            Ratfor User's Guide                                              


                         ___RRR___aaa___ttt___fff___ooo___rrr___ ___PPP___rrr___ooo___ggg___rrr___aaa___mmm___mmm___iii___nnn___ggg___ ___UUU___nnn___ddd___eee___rrr___ ___ttt___hhh___eee___ ___SSS___uuu___bbb___sss___yyy___sss___ttt___eee___mmm




                 This chapter describes the use of Ratfor in the  programming
            environment  provided  by the Software Tools Subsystem.  In addi-
            tion to demonstrating use of  the  Ratfor  preprocessor,  Fortran
            compiler,  and linking loader, the programming conventions neces-
            sary for  the  use  of  the  Subsystem  support  subprograms  are
            described.

                 In  this  chapter,  a  number of programming conventions are
            presented.  Since very few of the conventions can be enforced  by
            the  Subsystem, adherence to these conventions must be left to up
            to the programmer.  Many conventions, such as those dealing  with
            indentation  and comment placement, are shown because they assist
            in producing readable, maintainable programs.  Violation of these
            conventions, while not critical,  may  result  in  unmaintainable
            programs  and  extended debugging times.  Other conventions, such
            as  those  dealing  with  character  string  representations  and
            input/output,  are  crucial  to  the proper operation of the Sub-
            system  and  its  support  subprograms.    _V_i_o_l_a_t_i_o_n   _o_f   _t_h_e_s_e
            _c_o_n_v_e_n_t_i_o_n_s _c_a_n _a_n_d _w_i_l_l _c_a_u_s_e _u_n_d_e_s_i_r_a_b_l_e _r_e_s_u_l_t_s.



                            RRReeeqqquuuiiirrreeemmmeeennntttsss fffooorrr RRRaaatttfffooorrr PPPrrrooogggrrraaammmsss


                 The  Software  Tools  Subsystem  is not an operating system.
            Rather, it is a collection of _c_o_o_p_e_r_a_t_i_n_g user programs.  To  run
            successfully  under  the Subsystem, a program _m_u_s_t cooperate with
            it.  Several things are required of Subsystem programs:

            -    The program must terminate with a ssstttoooppp statement, or a  call
                 to the routine "error".  The program _m_u_s_t _n_o_t "call exit" or
                 invoke  any  of  the Primos error reporting subroutines with
                 the the "immediate return"  key.   A  program's  failure  to
                 terminate  properly  will  also  cause the Subsystem command
                 interpreter to be terminated, leaving the user  face-to-face
                 with Primos.

            -    The  program should not have initialized common blocks (i.e.
                 bbbllloooccckkk dddaaatttaaa)))...  Initialize the common  areas  with  executable
                 statements.   (To  link a program that must have initialized
                 common, see appendix b.)

            -    Local variables in a subprogram  are  placed  on  the  stack
                 unless they appear in a dddaaatttaaa or sssaaavvveee declaration.  The value
                 of  variables  not appearing in one of these declarations is
                 not defined on entry to a subprogram.

                 Several conventions apply to the file containing the  Ratfor
            source statements:



                                         - 42 -                              




            Ratfor User's Guide                                              


            -    The file name should end with the suffix ".r".

            -    Any  number  of  program units (main program, functions, and
                 subroutines) may be included  in  the  file,  but  the  main
                 program must be first.

            -    All  variables  and  functions  must  be  declared  in  type
                 statements  (the  Primos  Fortran  compiler  enforces   this
                 restriction, except in the case of function names).

            -    Each program unit must end with an eeennnddd statement.

            -    Since  dddeeefffiiinnneeesss  apply  globally  to  all  subsequent program
                 units, a main program and all of its associated  subprograms
                 can  be  contained  in  the  same  file.   Only  one copy of
                 definitions need be included at the beginning of the  source
                 file.



                       RRRuuunnnnnniiinnnggg RRRaaatttfffooorrr PPPrrrooogggrrraaammmsss UUUnnndddeeerrr ttthhheee SSSuuubbbsssyyysssttteeemmm


                 Three  steps  are  required  to obtain an executable program
            from Ratfor source statements.  The  first  step,  preprocessing,
            produces   ANSI   Fortran   statements  from  the  Ratfor  source
            statements.   The  second  step,  compilation,   results   in   a
            relocatable binary module, which lacks all of the Primos, Fortran
            and  Subsystem  subroutines.  The last step, linking, produces an
            executable object  program  by  linking  the  relocatable  binary
            module  with  the  Primos, Fortran and Subsystem support routines
            necessary for its execution.  The object program produced  during
            linking may then be executed.


            PPPrrreeeppprrroooccceeessssssiiinnnggg

                 In the preprocessing step, the Ratfor preprocessor, 'rp,' is
            used  to  translate  Ratfor  source  statements into semantically
            equivalent ANSI  Fortran  statements  acceptable  to  the  Primos
            Fortran compiler.  The Ratfor preprocessor is invoked with a com-
            mand line of the following syntax:

                      rp [-o <output file>] <input file> [<rp options>]


                 If  you  do not want a conventionally named output file, you
            may specify the option "-o <output file>", where <output file> is
            the name you want given to the Fortran output.   If  you  do  not
            include  a  "-o  <output file>" option, 'rp' will name the output
            file by appending ".f" to the name of the first <input file>.  If
            the name of the first <input file> ends in ".r", the ".r" will be
            replaced by the ".f".

                 Next comes a list of  the  files  containing  Ratfor  source
            statements to be preprocessed.  'Rp' reads the files in the order


                                         - 43 -                              




            Ratfor User's Guide                                              


            specified  on the command line and treats the contents as if they
            were together in one big file.  This means that dddeeefffiiinnneeesss  in  each
            input file apply to all subsequent input files.

                 Finally,   there  are  preprocessor  options  which  may  be
            specified to change the output in some way or affect preprocessor
            operation.  For a complete list of available options and  a  more
            detailed description of the command line syntax, see Appendix F.

                 In  spite of all this complicated stuff, the 'rp' preproces-
            sor is quite easy to use if you  follow  the  recommended  naming
            conventions  for  files.   For  instance,  if  you  have a Ratfor
            program in a file called "prog.r", you can have  it  preprocessed
            by just typing

                      rp prog.r

            This  command  will cause the program contained in "prog.r" to be
            preprocessed, and the Fortran output to be produced on  the  file
            "prog.f" (which is exactly what the Fortran compiler expects).

                 Here are some more examples to show other ways in which 'rp'
            can be called:

                      # preprocess the files "p1.r", "p2.r", and "p3.r"
                      #    and produce Fortran output on "p1.f"
                      
                        rp p1.r p2.r p3.r
                      
                      
                      # preprocess the files "p1.r", "p2.r", and "p3.r"
                      #    and produce Fortran output on "ftn_out"
                      
                        rp p1.r p2.r p3.r -o ftn_out
                      
                      
                      # preprocess the file "p1.r", produce the Fortran
                      #    on "ftn_out" and include code to produce
                      #    subprogram level trace
                      
                        rp -t p1.r -o ftn_out



            CCCooommmpppiiillliiinnnggg

                 After  turning your Ratfor source code into Fortran with the
            preprocessor, the next step  is  to  compile  the  Fortran  code.
            Since  the  Subsystem  uses the Primos Fortran compiler, the 'fc'
            command just produces a sequence of Primos commands to cause  the
            compilation.   The  following  command will call the Fortran com-
            piler for a compilation:

                      fc [<options>] <input> [-b [<binary>]] [-l [<listing>]]

            The Fortran source  code  must  be  in  the  file  <input>.   The


                                         - 44 -                              




            Ratfor User's Guide                                              


            relocatable  binary  output  will be placed in the file <binary>,
            unless "-b <binary>" is omitted.  Then, following Subsystem  con-
            ventions,  the  binary  file name is constructed by appending the
            input file name with ".b"; if the input file ends with ".f",  the
            "f"  will  be  replaced  by  the  "b".   Normally  no  listing is
            produced; however, if one is requested, it  will  appear  on  the
            file  <listing>, or if the listing file name is omitted, the name
            will be constructed by appending the ".l" to the input file name;
            again, if the input file name ends  in  ".f",  the  "f"  will  be
            replaced with the "l".

                 <Options>  is a series of single letter options that specify
            how the compiler is to generate the object code.  Since there are
            too many options to completely describe here, we will  only  men-
            tion  a  few  of  the more important ones.  For those who wish to
            make full use of the Fortran compiler, or for those just curious,
            the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l, or the 'help' com-
            mand will give complete information.

                 Here are brief descriptions of the options of interest:

                 -v        Generate  pseudo-assembly  code   describing   the
                           object code produced.

                 -i        Unless  otherwise specified, consider all integers
                           to be "long" (32-bit)  rather  than  "short"  (16-
                           bit).   (This  is  useful for programs ported from
                           machines with longer word lengths.)

                 -t        Insert code to  produce  a  statement-level  trace
                           during execution.

            Of course, more than one of these options may be specified.

                 Again, even though all of this looks very complicated, it is
            really  very  simple,  if you have used the Subsystem file naming
            conventions.  If you have your  Fortran  code  in  a  file  named
            "prog.f"  (remember where Ratfor put its output), you may compile
            it, using the default options, by just entering

                      fc prog.f

            The command will call the Fortran compiler to produce binary out-
            put in the file "prog.b".  Just for completeness, here  are  some
            other examples of 'fc' commands:













                                         - 45 -                              




            Ratfor User's Guide                                              


                      # Compile "p1.f" to produce the binary "p1.b" and
                      #    and a listing on "p1.l"
                      
                        fc p1.f -l
                      
                      
                      # Compile "p1.f" to produce the binary "bin" and
                      #    the listing on "list"
                      
                        fc p1.f -b bin -l list
                      
                      
                      # Compile "p3.f", produce a pseudo-assembly code
                      #    listing and default to 32-bit integers
                      
                        fc -v -i p3.f -l


                 One  problem  you  may encounter when using 'fc' is that the
            Primos Fortran compiler pays no attention to i/o redirection when
            it is writing error messages to the terminal.  This is a  problem
            common  to all Primos commands called from the Subsystem.  If you
            want to record the terminal output of the Fortran  compiler,  you
            must  use  the  Primos command output facility.  This facility is
            accessed through the Subsystem 'como' command; for  details,  see
            the  _S_o_f_t_w_a_r_e  _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l or use the 'help'
            command.


            LLLiiinnnkkkiiinnnggg

                 The last step in preparing the program for execution is lin-
            king.  The linking step fixes the memory locations  of  the  Sub-
            system  common  areas;  assigns  the  binary module for each sub-
            program to an absolute memory location; and links in the required
            Subsystem support routines, Fortran run-time routines, and Primos
            system calls.  The memory image file produced by  this  step  may
            then  be  executed.  It should be noted here that programs linked
            under the Subsystem can run _o_n_l_y under the  Subsystem;  they  may
            not run without it.

                 The  'ld'  command is used to invoke the Primos loader to to
            do the linking.  Its syntax is as follows:

                      ld [-u] <binary file> . . . [-l <library file>] . . .
                           [-t -m] [-o <output file>]

            This is not the entire syntax accepted by 'ld,'  but  a  complete
            discussion  requires  detailed  knowledge  of the Primos loaders.
            For more information, see the Subsystem reference manual.

                 The "-u" option  causes  the  loader  to  print  a  list  of
            undefined subprograms.  Any number of binary files to be included
            may  be  listed.   The  only restriction is that the main program
            _m_u_s_t be the first binary subprogram encountered -- it must be the
            first program unit in a binary file, and that binary file must be


                                         - 46 -                              




            Ratfor User's Guide                                              


            the first <binary file> to appear on the command line.  Any  num-
            ber of libraries (residing in "=lib=") may then be specified with
            the  "-l"  option.   The  "-t  -m" options cause a load map to be
            produced on a file with the name as the  output  file  (or  first
            <binary  file>,  if  an  output  file is not specified) with ".m"
            appended.  If the file name ends with ".b", the ".b" is  replaced
            by  the  ".m".   The "-o" option specifies the name of the output
            file.  If the "-o" option is omitted, the output file  will  have
            the same name as the first <binary file>, with ".o" appended.  If
            the  name  of the first <binary file> ends in ".b", the ".b" will
            be replaced by the ".o".

                 Even though linking is a mysterious process, it need not  be
            traumatic.  Most of the time, you will be linking a single binary
            file  with  no  additional libraries.  For instance, if you had a
            binary file named "prog.b," you could produce an  object  program
            by just typing the command

                      ld prog.b

            The  Primos  loader  would  be invoked, and after a great deal of
            garbage was printed  on  the  terminal,  the  executable  program
            "prog.o" would be produced.

                 The  only  thing  that  you  must do is look for the message
            "LOAD COMPLETE" lurking somewhere near the end of  this  garbage.
            If  you  find  this  message,  it  means that all of the external
            references in your program (subroutine and function  calls)  have
            been  satisfied, and linking is complete.  If you don't find this
            message, there are unsatisfied references in your  program.   You
            may then call 'ld' with the "-u" option and the loader will print
            the  names  of  the  unsatisfied references on the terminal.  You
            will probably then find that these references are caused by  mis-
            spelled  subprogram  names, missing subprograms, or undimensioned
            arrays  (remember,  the  Fortran  compiler  treats  undimensioned
            arrays  as  functions  calls,  so you may not always get an error
            message from the compiler).





















                                         - 47 -                              




            Ratfor User's Guide                                              


                 Again, for completeness, here are some examples of  'ld'  at
            work:

                      # link the binary files "p1.b", "p2.b", and "p3.b"
                      #    to produce "p1.o" as output
                      
                        ld p1.b p2.b p3.b
                      
                      
                      # link the binary file "nprog.b",
          |           #    include the library "vshlib",
                      #    and produce the output file "nprog"
                      
          |             ld nprog.b -l vshlib -o nprog
                      
                      
                      # link the binary files "np1" and "np2",
                      #    produce a load map,
                      #    and output "my_new_prog"
                      
                        ld np1 np2 -t -m -o my_new_prog


                 The Primos loader also pays no attention to i/o redirection.
            If you want to catch its terminal output, you must use the Primos
            'como'  commands.   For  details, see the reference manual or use
            the 'help' command.


            EEExxxeeecccuuutttiiinnnggg

                 Executing a Subsystem program is the easiest  step  of  all.
            All  you  have  to  do  to  execute  it is to type its name.  For
            instance, if your object program was named "prog.o", all you need
            type is

                      prog.o

            to make it go.  Because the shell  also  looks  in  your  current
            directory for executable programs, "prog.o" is now a full-fledged
            Subsystem  command.   You  may  give  it arguments on its command
            line, redirect its standard inputs and  outputs,  include  it  in
            pipelines,  or  use it as a function.  Of course to be able to do
            all of these things properly, it must observe the Subsystem  con-
            ventions and use the Subsystem I/O routines.


            SSShhhooorrrtttcccuuutttsss

                 There  are  several  shortcuts that speed things up and save
            typing when developing programs.

                 _S_h_e_l_l _P_r_o_g_r_a_m_s.  Shell programs can be  a  great  help  when
            performing  repetitive  tasks.  Quite often one of these tasks is
            preprocessing,  compiling,  and  linking  a  program  during  its
            development.   A  simple  shell  program can save a great deal of


                                         - 48 -                              




            Ratfor User's Guide                                              


            typing in this situation.  For instance, let's say we are writing
            a Ratfor program that is in the  file  "np.r".   We  are  in  the
            process  of adding new features to "np" and will probably compile
            and test it several times.  We  can  make  a  very  simple  shell
            program  that  will  keep  us from having to type 'rp,' 'fc,' and
            'ld' commands every time we want to make a test run.  All we have
            to do make a file containing these three commands with 'cat':

                      ] cccaaattt >>>cccnnnppp
                      rrrppp nnnppp...rrr
                      fffccc nnnppp...fff
                      lllddd ---uuu nnnppp...bbb ---ooo nnnppp
                      <<<cccooonnntttrrrooolll---ccc>>>
                      ]

            Now the file "cnp" contains the following text:

                      rp np.r
                      fc np.f
                      ld -u np.b -o np

            All we need do now to preprocess, compile, and link  our  program
            is just type the name of the shell program as a command:

                      cnp

            and the shell will execute all of the commands contained in it.

                 _T_h_e   _'_R_f_l_'   _C_o_m_m_a_n_d.   Of  course,  it  is  so  common  to
            preprocess, compile, and link a program,  there  is  an  already-
            built  shell  program  that  works  nicely  in most cases.  'Rfl'
            contains the necessary commands to preprocess, compile and link a
            Ratfor program contained in a file whose  name  ends  with  ".r".
            All you have to do is type

                      rfl np.r

            and  'rfl'  will  execute  the  necessary  commands to produce an
            executable file named "np".  (note that the  executable  file  is
            named  "np"  and not "np.o"!)  'Rfl' can also do some other handy
            things that you can find out about  in  the  Subsystem  reference
            manual.

                 _S_t_o_r_i_n_g  _S_o_u_r_c_e  _P_r_o_g_r_a_m_s _S_e_p_a_r_a_t_e_l_y.  When you write fairly
            large programs or test modules independently, it  is  often  con-
            venient  to store the programs in separate files.  If this is the
            case, creating an executable program is just a  little  bit  more
            complicated.   The  easiest  solution  is to just name all of the
            programs on the 'rp' command line, like this:

                      rp p1.r p2.r p3.r

            'Rp' will preprocess all of the files together and produce output
            on the file "p1.f".  The dddeeefffiiinnneee statements in "p1.r"  will  still
            be  in  effect  when  "p2.r"  is  preprocessed,  etc.  so "p1.r",
            "p2.r", and "p3.r" might just as well be together in one file.


                                         - 49 -                              




            Ratfor User's Guide                                              


                 _C_o_m_p_i_l_i_n_g _P_r_o_g_r_a_m_s _S_e_p_a_r_a_t_e_l_y.  A  little  bit  harder,  but
            sometimes  much  faster, is to preprocess and compile the modules
            separately and then combine them during linking.  There  are  two
            things  that  you have to watch.  The first problem with separate
            compilation is that dddeeefffiiinnneee statements in one file  cannot  affect
            subprograms  in  the other files.  For a large program that would
            benefit from separate compilation, this nastiness can be  avoided
            by placing all of the dddeeefffiiinnneeesss together in one file and placing an
            iiinnncccllluuudddeee  for  that  file  at  the  beginning of each of the files
            containing  the  program.   The  dddeeefffiiinnneeesss  will  then  be  applied
            uniformly to all parts of the program.

                 The second thing is that since Ratfor chooses unique Fortran
            names  in  the order it is presented with "long" Ratfor names, it
            cannot guarantee that a long name in one file will be transformed
            into exactly the same Fortran name as the same  long  name  in  a
            second  file  (although the probability is quite high).  To avoid
            problems, either subprogram names that  are  cross-referenced  in
            the  separate  binary  files  should  be  given  six-character or
            shorter names, or a llliiinnnkkkaaagggeee declaration containing the  names  of
            all  subroutines,  function, and common blocks should be inserted
            at the beginning of each module.  It is usually easiest to handle
            the llliiinnnkkkaaagggeee declaration just like the dddeeefffiiinnneee statements:  put  it
            in  a  separate  file, and add an iiinnncccllluuudddeee statement for it at the
            beginning of each module.

                 Then, the program units in each file may be preprocessed and
            compiled separately.  The binary files  from  the  separate  com-
            pilations are linked together by just listing the names of all of
            the files on the 'ld' command:

                      ld p1.b p2.b p3.b

            The  only restriction is that the main program _m_u_s_t appear first.
            The object file from this example would be named "p1.o", but this
            could have been overridden by including the  "-o  <output  file>"
            option.

                 When  compiling parts of a program separately, you should be
            aware that incorrect use of the  llliiinnnkkkaaagggeee  declaration  can  cause
            totally  irrational behavior of the program with no other indica-
            tion of  error.   Since  no  checking  is  done  on  the  llliiinnnkkkaaagggeee
            declaration, you must be certain that every external name appears
            in  the  statement.  More importantly, when you add a subroutine,
            function, or common block, you must remember to change  the  llliiinnn-
            kkkaaagggeee declaration.  In addition, if you do not add the name to the
            very  end  of the declaration, you must immediately recompile all
            modules!  If you compile separately, and are  confronted  with  a
            situation  in  which  your program is misbehaving for no apparent
            reason, re-check the llliiinnnkkkaaagggeee declaration and  recompile  all  the
            modules.







                                         - 50 -                              




            Ratfor User's Guide                                              


            DDDeeebbbuuuggggggiiinnnggg

                 Debugging unruly programs under Primos is at best a grueling
            task, as currently there is almost no run-time debugging support.
            Except  for  a couple of machine-language level debuggers, you'll
            get very little help from Primos (except  for  some  nasty  error
            messages)  while  debugging programs.  This means that such tech-
            niques as top-down design, reading other programmers'  code,  and
            reasonably  careful  desk  checking will pay off in the long run.
            But even with all the care in the world,  some  bugs  will  creep
            through  (especially  on  an  unfamiliar  system).   The next few
            paragraphs will be devoted to techniques for exterminating  these
            stubborn bugs.

                 For  an  experienced user, a load map, the Primos DMSTK com-
            mand, and VPSD (the V-mode symbolic debugger)  can  very  quickly
            isolate the location, if not the cause, of a bug.  With more com-
            plicated programs that are dependent on the internal structure of
            the  machine  and  operating system, such machine level debugging
            cannot always be avoided.   If  you  find  yourself  in  such  as
            position,  you can begin to learn some of these things by examin-
            ing the following reference manuals:

            MAN 1671  System Reference Manual, Prime 100-200-300

            MAN 2798  System Reference Manual, Prime 400

            FDR 3059  The PMA Programmer's Guide

            FDR 3057  User Guide for the Fortran Programmer


                 Most often, the bug can be found by one or more of the  fol-
            lowing techniques:

            (1)  Inserting  'print' calls to display the intermediate results
                 within the program.

            (2)  Using the Ratfor subroutine trace.

            (3)  Using the Fortran statement number and assignment trace.

            It is usually quickest to use the  Ratfor  subroutine  trace  (by
            including  the  "-t"  option on the 'rp' command line).  Although
            this trace lists only subroutine nesting,  it  will  narrow  down
            where  a  program  is  blowing up to a single subprogram.  If the
            program is very modular and contains  mostly  small  subprograms,
            quite often, the error can be spotted.

                 If  the  Ratfor  trace  fails  to  pinpoint the problem, the
            Fortran statement and assignment trace will  give  a  great  deal
            more information (possibly hundreds of pages).  The Fortran trace
            can  be  produced  by specifying the "-t" option on the 'fc' com-
            mand.  The Fortran code produced by  'rp'  must  be  examined  to
            locate  the  statement  numbers,  but  given  the large number of
            statement labels generated by  'rp,'  study  of  this  trace  can


                                         - 51 -                              




            Ratfor User's Guide                                              


            isolate the problem practically to within one statement.

                 The  above  debugging methods are quick and easy to use when
            the program contains a catastrophic error that  causes  an  error
            termination  or  an  infinite  loop.  While this is sometimes the
            case, more often a subtle error is the problem.  In finding these
            errors, there is no substitute for carefully  inserted  debugging
            code  (such  as  calls  to  'print')  at  critical  points in the
            program.

                 The rest of this section is devoted to a  brief  description
            of  many  of  the  terminal errors that may do away with programs
            (and the Subsystem).  Most terminal errors  cause  the  Subsystem
            command interpreter to be terminated along with the user's delin-
            quent  program.  You can tell that you've been booted into Primos
            by the appearance of the "OK," or "ER!"  prompt.  All error  mes-
            sages  that  cause  an  exit  to  Primos are briefly explained in
            appendix A-4 of the Prime Fortran Programmer's  Guide  (FDR3057).
            Some  very common programming errors can cause cryptic error mes-
            sages  with  explanations  that  are  close  to   unintelligible.
            Hopefully, most of these messages are described below.

                 Many  Primos  error  messages  are dead giveaways of program
            errors.  Messages that begin with four  asterisks  are  from  the
            Fortran  runtime packages -- they usually indicate such things as
            division by zero or extraction of the square root of  a  negative
            number.  For example,

                      **** SQRT -- ARGUMENT < 0
                      OK,

            results  from  extracting  the  square root of a number less than
            zero.

                 Other, more mysterious, error messages can also be caused by
            simple program errors.

                      Error: condition "POINTER_FAULT$" raised at <addr>

            can be caused by referencing a  subprogram  which  has  not  been
            included  in the object file.  An obvious indication of a missing
            subprogram is the failure to get the

                      LOAD COMPLETE

            message from  'ld'.   (Note  that  the  Fortran  compiler  treats
            references  to  undimensioned  arrays as function calls!)  A more
            insidious cause of the "POINTER FAULT" message is a reference  to
            an  unspecified  argument  in  a  subprogram;  i.e.   the calling
            routine specifies three arguments and the called routine  expects
            four.    The  error  occurs  when  the  unspecified  argument  is
            _r_e_f_e_r_e_n_c_e_d _i_n _t_h_e _s_u_b_p_r_o_g_r_a_m, not during the subprogram call.

                 Error: condition "ACCESS_VIOLATION$" raised at <addr>
                 Error: condition "RESTRICTED_INST$" raised at <addr>
                 Error: condition "ILLEGAL_SEGNO$" raised at <addr>


                                         - 52 -                              




            Ratfor User's Guide                                              


                 Error: condition "ARITH$" raised at <addr>
                 Program halt at <addr>

            all can result from a subscript exceeding  its  bounds.   Because
            the  program  may  have  destroyed  parts of its code, the memory
            addresses sometimes given may well be meaningless.  Even so,  you
            may  locate the routine in which the program blew up by using the
            Primos DMSTK command and a load map.   For  instance,  given  the
            following scenario (ellipsis indicate irrelevant information),

                 Error: condition "POINTER_FAULT$" raised at 3.4000.001000.
                 Abort (a), Continue (c) or Call Primos (p)? ppp
                 OK, dddmmmssstttkkk
                 ...
                 Stack Segment is 6002.
                 
                    6) 001464: Condition Frame for "POINTER_FAULT$"; ...
                       Raised at 3.4000.017202; LB= 0.4000.017402, ...
                 
                    7) 001374: Fault Frame; fault type= 000064
                       Returns to 3.4000.017202; _L_B_= _0._4_0_0_0._0_1_7_4_0_2, ...
                       Fault code= 100000, Fault addr= 3.4000.017204
                       Registers at time of fault:
                 ...

            The  numbers  following  "LB="  on  the underlined portion of the
            stack dump show the address of the data  area  of  the  procedure
            executing when the fault occurred.  The segment number portion of
            this  address (the four-digit part) tells who the routine belongs
            to:

                      _S_e_g_m_e_n_t      _U_s_e
                      
                      0000 - 0033  Operating System
                      2030         Software Tools Shell
                      2031         Software Tools Screen Editor
                      2035         Software Tools Library
                      2050         Fortran Library
                      4000 - 4037  User Program
                      4040         Software Tools Common
                      4041         Software Tools Stack
                      6001         Fortran Library
                      6002         Primos Ring 3 Stack

            If the executing routine is not part of  your  program,  you  can
            trace  back  the  stack  (see below) until you find which of your
            subprograms made the call.  If the  segment  number  begins  with
            "4",  you  need  only look down the right-most two columns of the
            load map (see the 'ld' command) for the two numbers  (4000  17402
            in  this  case).   If you get an exact match, just look across to
            the name  on  the  left  --  this  is  the  subprogram  that  was
            executing.   Otherwise,  if none of the numbers match then either
            the program has clobbered itself and  jumped  into  nowhere,  you
            left  off  an  argument  to  a  library subprogram, or one of the
            library routines has caused an exception trap with no fault  vec-
            tor.


                                         - 53 -                              




            Ratfor User's Guide                                              


                 Subsequent entries in the stack dump (following the informa-
            tion  in  the  last  scenario) can be used to find what procedure
            calls were in process when the error occurred.  The  entries  are
            of the following form:

                 Stack Segment is 4041.
                 
                    8) 002222: Owner=  (LB= 0.4000.017402).
                       Called from 3.4000.017700; returns to 3.2035.017702.
                 
                    9) 002156: Owner=  (LB= 0.4000.013026).
                       Called from 3.4000.013442; returns to 3.2030.013450.
                 ...

            Each  entry  on  the  Subsystem stack (segment 4041) represents a
            procedure call in process.  You can use the numbers following the
            "LB=" and the load map to  trace  back  through  the  "stack"  of
            procedure calls, just as with the "fault frame" mentioned above.

                 If you find yourself at a complete and total loss at finding
            why  your  program  is  blowing up, here is a list of some of the
            errors that have caused us great anguish:

            -    Subscript out of range.  This error can cause any number  of
                 strange results.

            -    Undefined  subprogram.   This  error  can be detected by the
                 lack of a "LOAD COMPLETE" message from the 'ld' command.

            -    Too few arguments passed.  This error almost always causes a
                 "POINTER_FAULT$" when the missing argument is referenced.

            -    Code and initialized local data requires more that one  seg-
                 ment  (64K  words).   The  load  map shows how much space is
                 allocated.  No linkage or procedure frame should  appear  in
                 any segment other than 4000.

            -    Delimiter  character  is  missing  in a packed string.  This
                 includes periods in packed strings  passed  to  'print'  and
                 'input'.  This error causes the program to run wild, writing
                 all over the place.

            -    Type  declaration is missing for a function.  This error can
                 causes failure of routines such as 'open'  which  return  an
                 integer  result.   The Primos Fortran compiler does not flag
                 undeclared functions.  This error may also cause an  erratic
                 real-to-integer  conversion  error  or  cause the program to
                 take an exception trap.

            -    A subprogram is changing the value of a  constant.   If  you
                 pass a single constant as a function or subroutine argument,
                 and  the subprogram changes the corresponding parameter, the
                 values of all occurrences of that constant  in  the  calling
                 program  will be changed.  With this error, it is quite pos-
                 sible for the constant 12 to have the value -37 at some time
                 during execution.


                                         - 54 -                              




            Ratfor User's Guide                                              


            PPPeeerrrfffooorrrmmmaaannnccceee MMMooonnniiitttooorrriiinnnggg

                 In most cases, it is very difficult to  determine  how  much
            processing  time  is  required  by  different parts of a program.
            Since it is nearly impossible  to  determine  which  parts  of  a
            program are "inefficient", especially before the program is writ-
            ten,  it often more effective to write a program in the most sim-
            ple and straightforward manner, and then use performance monitor-
            ing tools to find where the program is spending its time.  It has
            many times been our experience to find even  though  parts  of  a
            program are coded inefficiently, only a very small amount of time
            is wasted.

                 There  are  two available methods for obtaining an execution
            time "profile" of a Ratfor program.  The  first  method  provides
            statistics on the number of calls to and the amount of time spent
            in  each  subprogram.   The second method provides a count of the
            number of times each statement in the program is executed.

                 To invoke the subroutine profile, just  preprocess  (in  one
            run)  all the subprograms to be profiled.  Add the "-p" option to
            the 'rp' command line when the programs are  preprocessed.   Then
            compile, link and execute the program normally.  When the program
            terminates  (it  must  execute  a  ssstttoooppp  statement,  and not call
            "error"), type the command

                      profile

            'Profile' accesses the files "timer_dictionary" (output by  'rp')
            and "_profile" (output by your program) and prints the subroutine
            profile to standard output.

                 To  invoke  the  statement  count  profile, put all the sub-
            programs to be profiled (you must also include the main  program)
            in  a  single  file.   Then preprocess the file with 'rp' and the
            "-c" option.  Compile, link, and execute the program.   When  the
            program terminates normally, type the command

                      st_profile myprog.r

            (Of  course,  assuming  your  source file name is "myprog.r".)  A
            listing of the program with execution count for each line will be
            printed.

                 When running a profile, there are several things to keep  in
            mind.   First,  the  program  with the profiling code can be more
            than twice as large as the original program.  Second, the program
            can run an order of magnitude more slowly.  Third, there can be a
            considerable delay between the execution of  the  ssstttoooppp  statement
            and  the actual end of the program.  Finally, you should remember
            that the main program and all subprograms to be profiled must  be
            preprocessed at the same time.






                                         - 55 -                              




            Ratfor User's Guide                                              


            CCCooonnndddiiitttiiiooonnnaaalll CCCooommmpppiiilllaaatttiiiooonnn

                 Conditional  compilation  is  a  handy  trick  for inserting
            debugging code or  setting  compile-time  options  for  programs.
            Conditional compilation can be approximated in Ratfor by defining
            an  identifier,  such as "DEBUG" to a sharp sign or null (for off
            and on respectively).  Lines in the Ratfor program beginning with
            the identifier "DEBUG" (i.e.  debugging code) are not compiled if
            "DEBUG" is defined to  be  "#",  but  are  compiled  normally  if
            "DEBUG" is defined as a null string.

                 For  instance,  the  following example shows how conditional
            compilation can be used to "turn off" print statements at compile
            time:

                      define (DEBUG, #)
                      
                         fd = open (fn, READ)
                      DEBUG  call print (ERROUT, "fd returned:*i*n"s, fd)
                      ...
                         len = getlin (str, fd)
                      DEBUG  call print (ERROUT, "str read: *s"s, str)

            In this example, all lines beginning with  "DEBUG"  are  ignored,
            unless the dddeeefffiiinnneee statement is replaced with

                      define (DEBUG, )

            Then, all lines beginning with "DEBUG" will be compiled normally.


            PPPooorrrtttaaabbbiiillliiitttyyy

                 If your intent is to produce portable Fortran code, the Rat-
            for  preprocessor,  'rp'  can  be invoked with the following four
            options:


                 ---hhh   Produce Hollerith-format string constants  rather  than
                      quoted string constants.  This option useful in produc-
                      ing  character  strings  in the proper format needed by
                      your Fortran compiler.

                 ---vvv   Output "standard" Fortran.  This option causes 'rp'  to
                      generate only standard Fortran constructs (as far as we
                      know).    This  option  does  not  detect  non-standard
                      Fortran usage in Ratfor source code; it  only  prevents
                      'rp'   from   generating   non-standard  constructs  in
                      implementing its data and control structures.

                 ---xxx   Translate character codes.   'Rp'  uses  the  character
                      correspondences   in  a  translation  file  to  convert
                      characters into integers when it builds Fortran  "data"
                      statements  containing  EOS-terminated or PL/I strings.
                      If the option  is  not  specified,  'rp'  converts  the
                      characters using the native Prime character set.


                                         - 56 -                              




            Ratfor User's Guide                                              


                 ---yyy   Do  not output "call swt".  This option keeps 'rp' from
                      generating  a  "call  swt"  in  place  of  all   "stop"
                      statements,  which are required for Fortran programs to
                      run under the Subsystem.

            The following option for 'fc' may also help:


                 ---iii   Consider all integers to be "long" (32-bit) rather than
                      short.




                            SSSooouuurrrccceee PPPrrrooogggrrraaammm FFFooorrrmmmaaattt CCCooonnnvvveeennntttiiiooonnnsss


                 After considering many program formatting  styles,  we  have
            concluded  that  the  convention used by Kernighan and Plauger in
            _S_o_f_t_w_a_r_e _T_o_o_l_s is the most expedient in terms of clarity and ease
            of  modification.   As  a  consequence,  we  have  tried  to   be
            consistent in the use of this convention throughout the Subsystem
            to  provide  uniformly  readable and modifiable code.  We present
            the convention here in the hope that you can use it to  the  same
            advantage.


            SSStttaaattteeemmmeeennnttt PPPlllaaaccceeemmmeeennnttt

                 The  placement of statements in program units is perhaps the
            most  important  part  of  the  formatting  convention.   Through
            uniform  placement  of statements, many documents can be produced
            directly directly  from  the  source  code.   For  instance,  the
            skeleton  for  Section  2  of  the Subsystem Reference Manual was
            produced originally from the subprogram headers of the  Subsystem
            library  subprograms.   Then  the  detail was filled in using the
            text editor.

                 The order of a  program  unit  (including  a  main  program)
            should be as follows:

            1.   A comment line of the following format:

                 # <program name> --- <one-line description>

            2.   The  sssuuubbbrrrooouuutttiiinnneee or fffuuunnnccctttiiiooonnn statement (or nothing if it
                 is a main program).

            3.   The declarations of all arguments passed  to  the  sub-
                 program, if any.

            4.   A blank line

            5.   Declarations  for  all  local  variables in the program
                 unit.



                                         - 57 -                              




            Ratfor User's Guide                                              


            6.   A blank line.

            7.   Executable program statements.

            8.   The eeennnddd statement.

            9.   Three blank lines.

            Of course, extra blank lines should be used  freely  to  separate
            different  logical  groups  of declarations and different logical
            blocks of executable statements.

                 As an example, here is the source code  for  the  subroutine
            "cant" taken directly from the Subsystem library:

          |           # cant --- print cant open file message
                         subroutine cant (str)
                         character str (ARB)
                      
                         call putlin (str, ERROUT)
          |              call error (": can't open.")
          |           
                         return
                         end



            IIInnndddeeennntttaaatttiiiooonnn

                 The  indentation  convention is very simple.  It is based on
            the idea that a statement should be indented three spaces to  the
            right  of  the  innermost  statement  controlling it.  Braces are
            placed as unobtrusively as possible, without affecting  the  ease
            of adding or deleting statements.

                 Statements,  with  the exception of the program heading com-
            ment, are placed three spaces to the right of  the  left  margin.
            All  statements  are  placed  in  this  position, unless they are
            subordinate to a control  statement.   In  this  case,  they  are
            placed three spaces to the right of the beginning of the control-
            ling statement.

                 Braces  do not affect the placement of statements.  An open-
            ing brace is placed on the line with the  controlling  statement.
            A  closing brace is placed on a separate line three spaces to the
            right of the beginning of the controlling statement.

                 Multiple statements per line are forbidden,  except  when  a
            chain  of iiifff --- eeelllssseee iiifff ... ... ... eeelllssseee statements is used to implement
            a case structure.  In this event, the eeelllssseee  iiifff  is  considered  a
            single  statement,  appearing  on  the  same line, and subsequent
            lines are indented only three spaces to the right.

                 If all of this seems terribly confusing, here are some exam-
            ples that show the indentation convention in action (the bars are
            just to show you the matching of braces):


                                         - 58 -                              




            Ratfor User's Guide                                              


                      for (i = 1; str (i) ~= EOS; i += 1) {
                      |  if (str (i) == 'a'c) {
                      |  |  j = ctoi (str (2), i)
                      |  |  select (j)
                      |  |  |  when (1)
                      |  |  |  |  call alt1
                      |  |  |  when (2)
                      |  |  |  |  call alt2
                      |  |  |  when (3) {
                      |  |  |  |  call alt1
                      |  |  |  |  call alt2
                      |  |  |  |  }
                      |  |  else
                      |  |     call error ("number must be >= 1 and <= 3"s)
                      |  ---}
                      |  else if (str (i) == 's'c)
                      |     repeat {
                      |     |  j = ctoi (str (2), i)
                      |     |  status = getnext (j)
                      |     ---} until (status == EOF)
                      |  else {
                      |  |  call clean_up
                      |  |  stop
                      |  ---}
                      ---}



            SSSuuubbbsssyyysssttteeemmm DDDeeefffiiinnniiitttiiiooonnnsss

                 The use of the  dddeeefffiiinnneee  statement  plays  a  large  part  in
            producing readable, maintainable programs.  Hiding implementation
            details  with  dddeeefffiiinnneee  statements not only produces more readable
            code, but allows changes in the implementation details to be made
            without necessitating  changes  in  applications  programs.   The
            development  of  a  large  part  of the Subsystem would have been
            greatly hindered if it had not  been  possible  to  redefine  the
            constant  "STDIN"  from  "1"  to  "-11", with no more than recom-
            pilation.

                 The Subsystem definitions file, "=incl=/swt_def.r.i"  exists
            primarily  to  hide  the  dirty  details of the Subsystem support
            routines from Ratfor programmers.  We sincerely believe that  the
            character  string  "EOF"  is  inherently more meaningful than the
            string "-1".  (Would you believe that after three years of  using
            the  Subsystem,  the  author  of  this section had to look up the
            value  assigned  to  "EOF"  in  order  to  write  the   preceding
            sentence?)

                 Of  course,  the use of the Subsystem definitions also allow
            the developers to change these values when necessary.  Of course,
            these changes force recompilation of all existing  programs,  but
            we feel that this is a small price to pay for the availability of
            more  advanced  features.   All  users  of  the Subsystem support
            routines are therefore warned that the values  of  the  Subsystem
            definitions  may  change  between versions of the Subsystem.  (At


                                         - 59 -                              




            Ratfor User's Guide                                              


            Georgia Tech, this may be daily.)  Programs that  depend  on  the
            specific values of the symbolic constants may well cease to func-
            tion when a new version of the Subsystem is installed.

                 Appendix  D  contains  specific  information  about (but not
            specific specific values for) the standard  Subsystem  definition
            file.   As  a  general  rule, all symbolic constants mentioned in
            Section 2 of the Subsystem  Reference  Manual  can  be  found  in
            "=incl=/swt_def.r.i".



                          UUUsssiiinnnggg ttthhheee SSSuuubbbsssyyysssttteeemmm SSSuuuppppppooorrrttt RRRooouuutttiiinnneeesss


                 Many of the capabilities available to a Subsystem programmer
            are  provided  through  the Subsystem support routines.  The Sub-
            system support routines consist of well over one  hundred  Ratfor
            and  PMA  subprograms  that either perform common tasks, insulate
            the user  from  Primos  and  Fortran,  or  conceal  the  internal
            mechanisms  of the Subsystem.  By default, the library containing
            all of these routines ("=lib=/vswtlb") is included in the linking
            of all Subsystem programs.  Therefore, no special actions need be
            taken to call these routines.

                 If you notice that there  are  some  "holes"  in  the  func-
            tionality  of  the  Subsystem  library,  you  are  probably quite
            correct.  The Subsystem library has grown  to  its  present  size
            through  the  effort  of  many  of its users.  The instance often
            arises that a routine is required to fill  a  specific  function.
            In  keeping with the _S_o_f_t_w_a_r_e _T_o_o_l_s methodology, instead of writ-
            ing a very specific routine, we  ask  that  the  author  write  a
            slightly  more  general  routine that can be used in a variety of
            instances.  The routine can then be documented and placed in  the
            Subsystem library for the benefit of all users.  Many of the sup-
            port routines, including the dynamic storage management routines,
            have come from just such instances.  The "holes" in the Subsystem
            library  are just waiting for someone to fill them; if you need a
            routine that isn't there, please write it for us.


            TTTeeerrrmmmiiinnnaaatttiiiooonnn

                 The subprogram 'swt' terminates the  program  and  causes  a
            return to the Subsystem command interpreter.  Any Subsystem files
            left  open  by  the  program  are  closed.   Ratfor automatically
            inserts a "call swt"  any  time  it  encounters  a  Fortran  ssstttoooppp
            statement.   All  Ratfor  programs  should ssstttoooppp rather than "call
            exit".   Fortran  and  PMA  programs  should  invoke   'swt'   to
            terminate.


            CCChhhaaarrraaacccttteeerrr SSStttrrriiinnngggsss

                 Most  of the support routines use characters that are unpac-
            ked, one per word (i.e.  integer variable), right-justified  with


                                         - 60 -                              




            Ratfor User's Guide                                              


            zero  fill,  rather  than the Fortran default, two characters per
            word, left-justified, with blank fill (for an  odd  last  charac-
            ter).   In  addition  to  the simplicity of manipulating unpacked
            strings, the unpacked  format  represents  characters  as  small,
            positive  integers.   Thus,  character values can be used in com-
            parisons and as indexes without conversion.

                 Most of  the  support  routines  that  manipulate  character
            strings expect them to be stored in an integer array, one charac-
            ter  per  word,  right-justified  and zero-filled, and terminated
            with a word containing the symbolic constant 'EOS'.   Strings  of
            this format are usually called EOS-terminated strings.

                 Support  for  the  use of unpacked characters is provided in
            several ways:  (1) the Subsystem I/O routines perform  conversion
            to and from unpacked format, (2) single-character constants 'a'c,
            'b'c,  ','c,  etc.   are  provided  for  use  in place of single-
            character Hollerith literals, and (3) the Ratfor ssstttrrriiinnnggg statement
            is provided to initialize EOS-terminated strings.

                 In a few cases, it is more convenient  to  use  a  Hollerith
            literal  instead of an EOS-terminated string.  Since it is impos-
            sible to tell the length of a Hollerith literal at run time, Hol-
            lerith literals used with the Subsystem are required to contain a
            delimiter character (usually a period)  as  the  last  character.
            Hollerith  literals  or  integer  arrays  that contain Hollerith-
            format characters and end with a delimiter character are referred
            to as packed strings.

                 Following are brief  descriptions  for  the  most  generally
            useful    character    manipulation   routines.    For   specific
            information, see the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l.

                 _E_q_u_a_l.  'Equal' is an integer function that takes  two  EOS-
            terminated   strings  as  arguments.   If  the  two  strings  are
            identical, 'equal' returns YES; otherwise  it  returns  NO.   For
            example,

                      string dash_x "-x"
                      integer equal
                      ...
                      if (equal (argument, dash_x) == YES)
                         call cross_ref


                 _I_n_d_e_x.   'Index' is used to find the position of a character
            in an EOS-terminated string.  If the character is in the  string,
            its position is returned, otherwise zero is returned.  'Index' is
            very  similar  to the built-in function of the same name in PL/I.
            Example:








                                         - 61 -                              




            Ratfor User's Guide                                              


                      string options "acx"
                      integer ndx
                      integer index
                      ...
                      ndx = index (options, opt_character)
                      select (ndx)
                         when (1)
                            call list_all
                         when (2)
                            call list_common
                         when (3)
                            call cross_reference
                      else
                         call remark ("illegal option"s)

            This example selects  one  of  a  number  of  subroutines  to  be
            executed  depending  on  a single-character option specifier.  Of
            course, this particular example could be done  with  just  ssseeellleeecccttt
            alone.   'Index'  is also useful in character transliteration and
            conversion from character to binary integer.

                 _L_e_n_g_t_h.  'Length' is an integer function  that  returns  the
            length  of  an  EOS-terminated string.  The length of a string is
            zero if and only if its first character is an EOS; it is the num-
            ber of characters before the EOS in all other cases.  'Length' is
            often useful in deciding  where  to  start  appending  additional
            text, as in the following example:

                      integer len
                      integer length
                      ...
                      len = length (str)
                      call scopy (new_str, 1, str, len + 1)


                 _M_a_p_d_n  _a_n_d _M_a_p_u_p.  These functions accept a single character
            as an argument and if the character is alphabetic,  force  it  to
            lower  or  upper  case,  respectively.  'Mapdn' and 'mapup' quite
            often find use in mapping option letters to a single case  before
            comparison.   Since  non-alphabetic  characters are not modified,
            these routines may be used safely even if non-alphabetic  charac-
            ters  appear.   In  addition,  these routines provide a very good
            place to isolate character set dependencies.  For example,

                      character c
                      character mapdn
                      ...
                      if (mapdn (c) == 'a'c) {
                         # handle 'a' option
                      ...
                      else if (mapdn (c) == '1'c) {
                         # handle '1' option


                 _M_a_p_s_t_r.   'Mapstr'  provides  case  mapping  for  alphabetic
            characters  in  EOS-terminated  strings.   As  arguments 'mapstr'


                                         - 62 -                              




            Ratfor User's Guide                                              


            takes a string and the  symbolic  constant  'LOWER'  or  'UPPER'.
            Alphabetic  characters  in the string are then forced to lower or
            upper case, depending on the constant specified.

                 _S_c_o_p_y.  The subroutine 'scopy'  is  used  for  copying  EOS-
            terminated  strings.   It  requires  four  arguments:  the source
            string, the position from which to start copying, the destination
            string, and the position at which filling begins in the  destina-
            tion string.  Since Ratfor provides no string assignment, 'scopy'
            is  normally used to provide the capability.  The simple movement
            of a string from one place to another is coded as

                      character str1 (MAXLINE), str2 (MAXLINE)
                      ...
                      call scopy (str1, 1, str2, 1)

            'Scopy' is also capable of appending one string to another, as in
            the following example:

                      character str1 (MAXLINE), str2 (MAXLINE)
                      ...
                      call scopy (str1, 1, str2, length (str2) + 1)

            Note that 'scopy' makes no attempt to avoid writing past the  end
            of 'str2'!

                 _T_y_p_e.  'Type' is another of the routines that is intended to
            isolate  character dependencies.  Type is a function that takes a
            single character as an argument.  If that character is a  letter,
            'type'  returns  the  constant  'LETTER';  if  the character is a
            digit, 'type' returns the  constant  'DIGIT';  otherwise,  'type'
            returns  the  character.   'Type'  often  finds  use in a lexical
            analyzer:

                      character c
                      character type
                      
                      if (type (c) == LETTER) {
                         # collect identifier
                      ...
                      else if (type (c) == DIGIT) {
                         # collect integer
                      ...
                      else {
                         # handle special character



            FFFiiillleee AAAcccccceeessssss

                 File access is one of the more important aspects of the Sub-
            system.  It is through the Subsystem  i/o  routines  that  device
            independence  and i/o redirection are accomplished; moreover, the
            Subsystem routines provide a much less complicated interface than
            comparable Primos routines.



                                         - 63 -                              




            Ratfor User's Guide                                              


                 The basic method of access to a Subsystem  file  is  through
            the  contents  of  an  integer variable called a fffiiillleee dddeeessscccrrriiippptttooorrr...
            File descriptors can be set by one of several  routines  or  they
            can  be  set  to one of the six standard descriptors representing
            the six standard ports provided to all Subsystem programs.

                 Quite often, the standard ports  provide  all  of  the  file
            access  required  by  a  program.   Values  for the standard port
            descriptors  can  be   accessed   from   dddeeefffiiinnneeesss   contained   in
            "=incl=/swt_def.r.i"  ('Rp'  automatically  includes this file in
            each run).  The following table gives the symbolic names for  the
            three standard input and three standard output ports available:

                         _I_n_p_u_t _P_o_r_t_s                   _O_u_t_p_u_t _P_o_r_t_s
                      
                      STDIN1 (or STDIN)             STDOUT1 (or STDOUT)
                      STDIN2                        STDOUT2
                      STDIN3 (or ERRIN)             STDOUT3 (or ERROUT)

            These  constants  may  be  used  wherever  a  file  descriptor is
            required by a Subsystem i/o routine.

                 Other files may be accessed or created through the  routines
            'open',  'create', and 'mktemp' that are described later.  At the
            moment, it is sufficient to say that these routines are functions
            that return a file descriptor that may be used in other Subsystem
            i/o calls.

                 Once a file  descriptor  has  been  obtained,  the  file  it
            references  may  be  read with the routines 'getlin', 'getch', or
            'input'; written with the routines 'putlin', 'putch', or 'print';
            positioned with the routines 'wind' or 'rewind'; or  closed  with
            the routines 'close' or 'rmtemp'.

                 _O_p_e_n  _a_n_d  _C_l_o_s_e.   'Open' takes an EOS-terminated path name
            and a mode (one of the constants READ, WRITE,  or  READWRITE)  as
            arguments  and returns the value of a file descriptor or the sym-
            bolic constant ERR as a function value.  'Open' is normally  used
            to  make  a  file available for processing in the specified mode.
            If the mode is READ, 'open' will open the file  for  reading;  if
            the  file  doesn't exist or cannot be read (i.e.  no read permis-
            sion), 'open' will return ERR.  If the mode  is  WRITE  or  READ-
            WRITE, 'open' will open an existing file or create a new file for
            writing  or  reading  and writing, if possible; otherwise it will
            return ERR.  If 'open' opens an  existing  file,  it  will  never
            destroy  the contents, even if mode is WRITE.  To be certain that
            a "new" file is empty, use 'create' instead of 'open'.

                 'Close' takes a file descriptor as its argument;  it  closes
            and  releases the file attached to the descriptor.  If 'close' is
            called with a standard port, it takes no action.

                 Opening and closing a file is really very easy.  This  exam-
            ple  opens a file named "=extra=/news/index" and returns the file
            descriptor in 'fd'.  If the file can't  be  opened,  the  program
            will terminate with a call to 'cant'.


                                         - 64 -                              




            Ratfor User's Guide                                              


                      file_des fd
                      integer open
                      string fn "=extra=/news/index"
                      
                      fd = open (fn, READ) # open "=extra=/news/index"
                      if (fd == ERR)
                         call cant (fn)
                      
                      <process the contents of =extra=/news/index>
                      
                      call close (fd)      # release the file
                      stop

            If the file can't be opened, 'cant' will print the message

                      =extra=/news/index: can't open

            and terminate the program.

                 _C_r_e_a_t_e.   'Create'  takes  the same arguments as 'open', but
            also truncates the file (makes it empty) to be  sure  that  there
            are no remnants of its previous contents.

                 _M_k_t_e_m_p  _a_n_d  _R_m_t_e_m_p.   Quite  often, programs need temporary
            files for their internal use only.  'Mktemp' and  'rmtemp'  allow
            the  creation  of  unique  temporaries in the directory "=temp=".
            'Mktemp' requires only a mode (READ, WRITE, or READWRITE)  as  an
            argument  and  returns  a  file descriptor as its function value.
            'Rmtemp' takes a file descriptor as its argument and destroys and
            closes the temporary file.  (One should use  caution,  for  if  a
            descriptor  for a permanent file is passed to 'rmtemp', that file
            will also be destroyed.)

                 Typical use of 'mktemp' and 'rmtemp'  usually  involves  the
            writing and reading of an intermediate file:

                      file_des fd
                      integer mktemp
                      
                      fd = mktemp (READWRITE) # create a temporary file
                      
                      <code to write the intermediate file>
                      
                      call rewind (fd)        # reposition the temporary
                      
                      <code to read the intermediate file>
                      
                      call rmtemp (fd)        # close and destroy the temporary


                 _W_i_n_d  _a_n_d _R_e_w_i_n_d.  The subroutines 'wind' and 'rewind' allow
            the positioning of an open file to its end and beginning, respec-
            tively.  Both take a file descriptor as  an  argument.   Usually,
            'rewind' is used when a program creates a file and then wishes to
            read it back; 'wind' is often used when a program wants to add to
            the end of an existing file.


                                         - 65 -                              




            Ratfor User's Guide                                              


                 A  program  wishing  to  extend  a file would make a call to
            'wind' just after successfully opening the file to be extended:

                      file_des fd
                      integer open
                      string fn "myfile"
                      
                      fd = open (fn, READWRITE)
                      if (fd == ERR)
                         call cant (fn)
                      call wind (fd)    # file is now positioned at the
                                        #    end, ready for appending.


                 _T_r_u_n_c.  'Trunc' truncates an open file.  Truncating  a  file
            means releasing all of its disk space, hence making it empty, but
            retaining its name and attributes.  'Trunc' takes a file descrip-
            tor as its argument.

                 _R_e_m_o_v_e.   'Remove'  removes a file by name, deleting it from
            the disk directory.  It takes an  EOS-terminated  string  as  its
            argument,  and  returns  the  constant  OK  or  ERR, depending on
            whether or not it could remove the  file.   ('Remove'  will  also
            delete a Primos segment directory without complaining.)

                 _C_a_n_t.   'Cant'  is  a  handy routine for handling exceptions
            when opening files.  For  its  argument,  'cant'  takes  an  EOS-
            terminated string containing a file name.  It prints the message

                      <file name>: can't open

            and then terminates the program.

                 _G_e_t_l_i_n.  All Subsystem character input is done through 'get-
            lin'.   'Getlin'  takes a character array (at least MAXLINE long)
            and a file descriptor and returns a line of input in the array as
            an EOS-terminated string.  Although the  last  character  in  the
            string  is  normally  a  NEWLINE character, if the line is longer
            than MAXLINE, no NEWLINE will be present and the rest of the line
            will be obtained on the next call to 'getlin'.  For its  function
            value,  'getlin'  returns  the  length  of  the  line  delivered,
            (including the NEWLINE, if any) or the constant  EOF  if  end-of-
            file was encountered.

                 Most line-oriented i/o is done with 'getlin'.  For instance,
            using 'getlin' with its analog 'putlin', a program to select only
            those  lines  beginning  with  the letter "a" can be written very
            quickly:

                      character buf (MAXLINE)
                      integer getlin
                      
                      while (getlin (buf, STDIN) ~= EOF)
                         if (buf (1) == 'a'c)
                            call putlin (buf, STDOUT)



                                         - 66 -                              




            Ratfor User's Guide                                              


            'Getlin' is guaranteed to never return a  line  longer  than  the
            symbolic constant MAXLINE (including the terminating EOS).

                 If  needed, there are a number of routines that you can call
            to convert the character string returned by 'getlin'  into  other
            formats,  such  as  integer and real.  Most of these routines are
            described later in the section on "Type Conversion".

                 _G_e_t_c_h.  'Getch' returns one character at a time from a file;
            it requires  a  character  variable  and  a  file  descriptor  as
            arguments;  it  returns  the  character obtained, or the constant
            EOF, in the supplied argument and as the function  value.   Calls
            to 'getch' and 'getlin' may be interleaved; 'getlin' will pick up
            the rest of a line not read by 'getch'.

                 'Getch'  is  very  useful  in lexical analyzers or just when
            counting characters.  For instance, the following routine  counts
            both characters and lines at the same time:

                      character c
                      integer c_count, l_count
                      integer getch
                      
                      c_count = 0
                      l_count = 0
                      while (getch (c, STDIN) ~= EOF) {
                         c_count = c_count + 1
                         if (c == NEWLINE)
                            l_count = l_count + 1
                         }

            This  example  assumes  that  since each line ends with a NEWLINE
            character, lines can be counted by counting the NEWLINEs.

                 _I_n_p_u_t.  'Input' is  a  rather  general  routine  created  to
            provide  easy  access  to  both  interactive and file input.  For
            interactive input, 'input' will prompt at  the  terminal,  accept
            input,  and  call  the  proper conversion routines to produce the
            desired data formats.  In case of unexpected input (like  letters
            in  an  integer), it will ask for a line to be retyped.  For file
            input, 'input' recognizes that its input is  not  coming  from  a
            terminal (even if from a standard port) by turning off all promp-
            ting.   It  will then accept fixed or variable-length fields from
            the file under control of the format string.

                 'Input' requires a variable number  of  arguments:   a  file
            descriptor,  a  format  string, and as many destination fields as
            required by the format string.  It returns the  constant  EOF  as
            its  function  value  if it encountered end-of-file; otherwise it
            returns OK.

                 The file descriptor passed to 'input' describes the file  to
            be  read.   All  prompting  output (if any) always appears on the
            terminal.  The format string passed  to  'input'  indicates  what
            prompting  information  is  to  be output and what data format to
            expect as input.  Prompts to be output are specified  as  literal


                                         - 67 -                              




            Ratfor User's Guide                                              


            characters; i.e.  to output "Input X:", the characters "Input X:"
            would appear in the format string.  Prompting characters may only
            appear  at  the  beginning  of  the  string and immediately after
            "skip-newline" ("*n") format codes.  Data items to be  input  are
            described  by  an asterisk followed by optionally one or two num-
            bers and a letter.  For instance the  code  to  input  a  decimal
            integer  would  be  "*i" and the code to input a double precision
            floating point number would be "*d".

                 When a call to 'input' is executed,  the  format  string  is
            interpreted  from left to right.  When leading literal characters
            are encountered, they are output as a  prompt.   When  the  first
            format  code  is  encountered,  a line is read from the file, the
            corresponding item is obtained from the input line, and the  item
            is  placed in the next item in the argument list.  More items are
            removed from the input line until the end of the format string is
            reached or a newline appears in the input.  If  the  end  of  the
            format  string  is  encountered,  the  rest  of the input line is
            discarded, and 'input' returns OK.  Otherwise, if  a  newline  is
            encountered  in  the  input,  fields designated by the format are
            filled with empty strings, blanks, or zeroes,  until  the  format
            string  is  exhausted,  or  a code ("*n") to skip the NEWLINE and
            read a new line is encountered.

                 The  format  string  must  contain  exactly  as  many  input
            indicators as there are receiving data items in the call.  In any
            case, the maximum number of input items per call is 10.

                 Before  we  go any further, here is an example of an 'input'
            call to obtain three integers:

                      call input (STDIN, "Type i:  *i*nType j:  *i*nType k:  *i"s,
                         i, j, k)

            If this statement were executed the following might appear at the
            terminal (user input is boldfaced):

                      Type i:  222222 <<<nnneeewwwllliiinnneee>>>
                      Type j:  444777666 <<<nnneeewwwllliiinnneee>>>
                      Type k:  111 <<<nnneeewwwllliiinnneee>>>

            We could also type all three  integers  on  the  same  line,  and
            'input'  would  omit  the prompting for the second and third num-
            bers:

                      Type i:  222222 444777666 111 <<<nnneeewwwllliiinnneee>>>


                 There are a number of input indicators available for use  in
            the  format  string.  Since there are a large number of them with
            many available options, only a few are mentioned in the following
            table.  For further  information,  see  the  Subsystem  reference
            manual.

            _I_t_e_m _D_a_t_a _T_y_p_e               _I_n_p_u_t _R_e_p_r_e_s_e_n_t_a_t_i_o_n



                                         - 68 -                              




            Ratfor User's Guide                                              


            *n   skip newline       If  there  is  a  NEWLINE  at the current
                                    position, skip over it and  read  another
                                    line.   Otherwise  do  nothing.  ('Input'
                                    will never read more than  one  line  per
                                    call, unless this format code is present.

            *i   16 bit integer     Input  an  integer  with optional plus or
                                    minus  sign,  followed  by  a  string  of
                                    digits,  delimited by a blank or newline.
                                    Leading blanks are  ignored.   The  input
                                    radix  can  be  changed  by preceding the
                                    number  with  "<radix>r"   (e.g.    octal
                                    should be expressed by "8r").

            *l   32 bit integer     Same as "*i".

            *r   32 bit real        Input a real number with optional plus or
                                    minus  sign, followed by a possible empty
                                    string of digits, optionally followed  by
                                    a  decimal  point  and  a  possibly empty
                                    string of digits.  Scaling by a power  of
                                    10 may be indicated by an "e" followed by
                                    an  optional plus or minus sign, followed
                                    by a string of  digits.   The  number  is
                                    delimited  by a blank; leading blanks are
                                    ignored.

            *d   64 bit real        Same as "*r".

            *s   string             Input a string of characters delimited by
                                    a blank or newline.  No more than MAXLINE
                                    characters will be delivered,  regardless
          |                         of  input  size.   Use "*1s" to read in a
          |                         single character.  (Admittedly,  this  is
          |                         an  inconsistency; there really should be
          |                         a "*c" format.)

                 Fixed size input fields can  be  requested  by  placing  the
            desired  field  size  immediately  following  the asterisk in the
            format code.  For instance, to read three integers requiring five
            spaces each, you can use the following format string:

                      "*5i*5i*5i"

            You can also change the delimiting character of a field from  its
            default  value of a blank.  Just place two commas followed by the
            new delimiter immediately after the asterisk.  For instance,  two
            strings  delimited  by  slashes  can  be input with the following
            format string:

                      *,,/s*,,/s

            Regardless of the delimiter setting, a newline is always  treated
            as  a  delimiter.  One caution:  if the delimiter is not a blank,
            leading blanks in strings are not ignored.



                                         - 69 -                              




            Ratfor User's Guide                                              


                 _R_e_a_d_f.  You can use 'readf' to  read  binary  (memory-image)
            files  that  were  created with 'writef'.  'Readf' is the fastest
            way to  read  files,  since  no  data  conversion  is  performed.
            However,  use  of  'readf'  and  'writef'  tend to make a program
            dependent on machine word size, and hence, non-portable.

                 'Readf' takes three arguments:  a receiving data array,  the
            maximum number of words to be read, and a Subsystem file descrip-
            tor.   When  called, 'readf' attempts to read the number of words
            requested; if there are not that many in the file, it returns all
            that are left.  If there are no words left in the  file  at  all,
            'readf'  returns EOF as its function value; otherwise, it returns
            the number of words actually read as its function value.

                 _P_u_t_l_i_n.  'Putlin' is the primary output routine of the  Sub-
            system.   It takes an EOS-terminated string and a file descriptor
            as arguments, and writes the characters in the string on the file
            specified by the descriptor.  There  is  no  restriction  on  the
            length  of the input string; 'putlin' will write characters until
            it sees an EOS.  'Putlin' dddoooeeesss nnnooottt supply a newline character  at
            the  end  of the line; if one is to be written, it must appear in
            the string.  For a simple example, see the description  of  'get-
            lin'.

                 _P_u_t_c_h.   A  single  character  can  be output to a file with
            'putch'; it takes a character and a file descriptor as  arguments
            and writes the character on the file specified by the descriptor.
            Calls to 'putch' and 'putlin' can be interleaved as desired.

                 _P_r_i_n_t.   'Print'  is a general output routine that accepts a
            format string and up to ten output data items.  Interpreting  the
            format  string,  'print'  calls  the  appropriate type conversion
            routines to produce character data, and outputs the characters as
            directed  by  the  format  string.   'Print'   requires   several
            arguments:   a  file descriptor; an EOS-terminated format string;
            and zero to ten output data arguments, depending on how many  are
            required by the format string.

                 The  format  string  contains  two  kinds of items:  literal
            items which are output when  they  are  encountered,  and  output
            items,  which  cause  the  next  data argument to be converted to
            character format and output.  Literal items are  just  characters
            in  the  string;  i.e.   to output "X =", the format string would
            contain "X =".  Output items consist of an asterisk, followed  by
            two optional numbers, followed by a letter.  For instance an out-
            put  item  for  an  integer is "*i" and an output item for single
            precision floating point is "*r".  The  next  example  shows  the
            output of three integers:

                      call print (STDOUT, "i = *i, j = *i, k = *i*n"s,
                         i, j, k)

            If this call were executed, the following might be the result:

                      i = 342, j = 1, k = -3382



                                         - 70 -                              




            Ratfor User's Guide                                              


            Some of the more useful output items are described in the follow-
            ing table:

            _I_t_e_m     _D_a_t_a _R_e_p_r_e_s_e_n_t_a_t_i_o_n

            *i       short (16 bit) integer
            *l       long (32 bit) integer
            *r       single precision (32 bit) real
            *d       double precision (64 bit) real
            *p       packed, period-terminated string
            *s       EOS-terminated string
            *c       single character
            *n       newline

            It is possible to exert much more control over the format of out-
            put  using  'print';  for  more  information,  see  the Subsystem
            reference manual.

                 _W_r_i_t_e_f.  'Writef' is the companion routine  to  'readf';  it
            writes  words to a binary (memory-image) file.  It is the fastest
            of the output routines, since it performs no data conversion.  It
            is called with three arguments:   a  data  array  containing  the
            words  to  be  written,  the number of words to write, and a Sub-
            system file descriptor.  Here is  an  example  fast  file-to-file
            copy using 'readf' and 'writef' together.

                      integer l, buf (1024)
                      integer readf
                      file_des in_fd, out_fd
                      
                      repeat {
                         l = readf (buf, 1024, in_fd)
                         if (l == EOF)
                            break
                         call writef (buf, l, out_fd)
                         }


                 _F_c_o_p_y.   'Fcopy' is a very simple routine that copies files.
            You open and position the input and output files and call 'fcopy'
            with the input and output file descriptors.  It then copies lines
            from the input file to the output file.   'Fcopy'  uses  a  great
            deal  of  "secret  knowledge"  of  the  workings of the Subsystem
            input-output routines, and as a consequence, it copies  disk-file
            to disk-file very quickly (even when the descriptors are of stan-
            dard ports).

                 _M_a_r_k_f _a_n_d _S_e_e_k_f.  'Markf' and 'seekf' are companion routines
            that implement random access on disk files.  'Markf' takes a file
            descriptor as argument and returns a "file_mark" (currently a 32-
            bit  integer).   'Seekf'  takes  the  file mark along with a file
            descriptor and  sets  the  file  pointer  so  that  the  file  is
            positioned at the same place as when the "mark" was taken.

                 To  be  used  portably, 'markf' and 'seekf' may only be used
            between calls to 'readf' and 'writef', or immediately after input


                                         - 71 -                              




            Ratfor User's Guide                                              


            or output of a newline character (i.e.  at the  ends  of  lines).
            In  addition, a call to 'putlin' or 'putch' on a file effectively
            (although  not  actually)  destroys  information  following   the
            current  position of the file.  For example, if you want to write
            a line in a file, go off and do other operations on the file, and
            then be able to re-read the line later, you can use  'markf'  and
            'seekf':

                      file_mark fm
                      file_mark markf
                      file_des fd
                      character line (MAXLINE)
                      
                      fm = markf (fd)
                      call putlin (line, fd)
                      
                      ### perform other operations on 'fd'
                      
                      call seekf (fm, fd)
                      call getlin (line, fd)  # get 'line' back


                 Non-portably,  you  can assume that a "file mark" is a zero-
            relative word number within the file -- to get word number 12  in
            the file, just execute

                      call seekf (intl (12), fd)
                      call readf (word, 1, fd)

            (Remember:   file  marks are 32 bits, not 16!  We use 'intl' here
            to make "12" into a 32 bit integer.)   Keep  in  mind  that  this
            "secret  knowledge" is useful only with "readf" and "writef", not
            with any other input or output  routine.   Blank  compression  is
            used  in line oriented files, so the position of a line is depen-
            dent not only on length of previous  lines,  but  also  on  their
            content.   This  usually  makes  the position of a line in a file
            quite unpredictable.

                 _G_e_t_t_o.  'Getto'  exists  primarily  to  interface  with  the
            Primos  file system calls.  'Getto' takes a path name (in an EOS-
            terminated string) as its first argument.  It  follows  the  path
            and  sets the current directory to that specified for the file in
            the path name.  It then packs  the  file  name  into  its  second
            argument,  a 16 word array (with blank padding), ready for a call
            to the Primos file system.  It fills its  3-word  third  argument
            with  the  password  of  the  last node of the path (if there was
            one).  Its fourth argument, an integer, is set to YES if  'getto'
            changed the attach point, and NO otherwise.

                 'Getto' often finds use when functions other than those sup-
            ported  by  Subsystem routines need to be performed, such as set-
            ting the passwords on a directory:






                                         - 72 -                              




            Ratfor User's Guide                                              


                      integer pfn (16), opw (3), npw (3), pw (3), att
                      integer getto
                      string fn "=vars=/system"
                      
                      if (getto (fn, pfn, pw, att) == ERR)
                         call print (ERROUT, "can't get to *s*n"s, fn)
                      call spas$$ (pfn, 32, opw, npw) # set passwords
                      if (att == YES)
                         call follow (EOS, 0)    # attach back to home



            TTTyyypppeee CCCooonnnvvveeerrrsssiiiooonnn

                 There are a very large number of  type  conversion  routines
            available  to  convert most data types into character strings and
            back.  Because keeping up with all the conversion  routine  names
            and calling sequences can be quite a chore, two routines 'decode'
            and  'encode'  exist to handle conversion details in a consistent
            format.  These two routines are described at the end of this sec-
            tion.

                 Most of the  "character-to-something"  routines  require  at
            least two arguments.  The first argument is usually the character
            string,  and  the  second  is  an integer variable indicating the
            first of the characters to be converted.  The result  of  conver-
            sion  is  then  returned  as the function value, and the position
            variable is updated to  indicate  the  first  position  past  the
            characters used in the conversion.

                 For  example,  the  simplest "character-to-integer" routine,
            'ctoi' requires the two  arguments  mentioned  above.   Since  it
            skips leading blanks, but stops at the first non-digit character,
            it  can  be  called  several  times in succession to grab several
            blank-separated integers on a line:

                      character str (MAXLINE)
                      integer i, k (4), pos
                      integer ctoi
                      ...
                      pos = 1
                      do i = 1, 4
                         k (i) = ctoi (str, pos)
                      if (str (pos) ~= EOS)
                         call remark ("illegal character in input"s)

            This routine will assume unspecified values to be zero, but  com-
            plain if non-numeric, non-blank characters are specified.

                 Here is a list of all of the currently supported "character-
            to-something" routines.

                 ctoc     Character-to-character;    copies    character
                          strings and  pays  attention  to  the  maximum
                          length parameter.



                                         - 73 -                              




            Ratfor User's Guide                                              


                 ctod     Character-to-double  precision  real;  handles
                          general floating point input.

                 ctoi     Character-to-integer (16 bit); does not handle
                          plus and minus signs; decimal only.

                 ctop     Character-to-packed-string; converts to packed
                          format with no delimiter character.

                 ctor     Character-to-single  precision  real;  handles
                          general floating point input.

                 ctov     Character-to-PL/I-character-varying;  converts
                          to PL/I character varying format.

                 gctoi    Generalized-character-to-integer   (16   bit);
                          handles  plus  and minus signs; in addition to
                          program-specified radix, accepts  an  optional
                          user-specified radix from 2-16.

                 gctol    Generalized-character-to-long-integer      (32
                          bit); handles plus and minus signs;  in  addi-
                          tion  to  program-specified  radix, accepts an
                          optional user-specified radix from 2-16.


                 In addition to the "character-to-something" routines,  there
            are   the   "something-to-character"  routines.   Most  of  these
            routines require three arguments:  the value to be converted, the
            destination string, and the maximum size allowable.  They  return
            the  length of the string produced as the function value.  An EOS
            is always placed in the position following the last character  in
            the destination string, but the EOS is not included when the size
            of the returned string is calculated.

                 Since  the  functions  will accept a sub-array reference for
            the output string, you may place  several  objects  in  the  same
            string.  For example, using the "integer-to-character" conversion
            routine  'itoc', you can place the four integers in the array 'k'
            into 'str' in character format:

                      character str (MAXLINE)
                      integer i, k(4), pos
                      integer itoc
                      ...
                      pos = 1
                      do i = 1, 4; {
                         pos = pos + itoc (k (i), str (pos), MAXLINE - pos)
                         if (pos >= MAXLINE - 1) # there's no room for any more
                            break
                         str (pos) = BLANK
                         pos = pos + 1
                         }
                      str (pos) = EOS   # cover up the last blank

            This code will place the four integers in 'str', separated  by  a


                                         - 74 -                              




            Ratfor User's Guide                                              


            single  blank.   Although all conversion routines leave an EOS in
            the string, we have to replace it here because we clobber it with
            the blank.

                 It's worth noting that the  maximum  size  parameter  always
            includes  the  EOS -- the conversion routine will never touch any
            more characters than are specified by this parameter.

                 Here is a list  of  all  available  "something-to-character"
            conversion routines:

                 ctoc     Character-to-character;    copies    character
                          strings and  pays  attention  to  the  maximum
                          length parameter.

                 dtoc     Double-precision-real-to-character;    handles
                          general floating point conversions in Basic or
                          Fortran formats.

                 gitoc    Generalized-integer-to-character   (16   bit);
                          handles integer conversions; program-specified
                          radix.

                 gltoc    Generalized-long-integer-to-character      (32
                          bit); handles long integer conversion; program
                          specified radix.

                 itoc     Integer-to-character (16 bit); handles integer
                          conversion; decimal only.

                 ltoc     Long-integer-to-character  (32  bit);  handles
                          long integer conversion; decimal only.

                 ptoc     Packed-string-to-character;  accepts arbitrary
                          delimiter character; will unpack fixed  length
                          strings if delimiter is set to EOS and maximum
                          is set to (length + 1).

                 rtoc     Single-precision-real-to-character;    handles
                          general real conversion in  Basic  or  Fortran
                          formats.

                 vtoc     PL/I-character-varying-to-character;  converts
                          PL/I character varying format to character.

                 _D_e_c_o_d_e.  'Decode' handles conversion from character  strings
            to  all  other formats.  It is written to be used in concert with
            'getlin' and other such routines, and as such, has a  rather  odd
            calling  sequence.  It requires a minimum of five arguments:  the
            usual string, and string index; a format string; a format  string
            index  and  an  argument  string  index.  Following are receiving
            arguments, depending on the data types specified  in  the  format
            string.   In  almost  all cases, you should just supply variables
            with a values of 1 for the format index and the  argument  index.
            The  string index behaves just as it does in all other character-
            to-something routine -- on successful conversion,  it  points  to


                                         - 75 -                              




            Ratfor User's Guide                                              


            the  EOS  in  the string.  The specifics of the format string and
            receiving fields are identical to 'input'.  The only  differences
            are  that  'decode'  returns  with  OK in the situations in which
            'input' would read another line of input, and EOF otherwise,  and
            that  all  characters  in  the  format string that are not format
            codes are ignored.

                 _E_n_c_o_d_e.  'Encode' is a companion routine  to  'decode':   it
            can  access all of the something-to-character conversion routines
            in a consistent way.  For arguments it takes a character  string,
            maximum length of the string, a format string, and a varying num-
            ber   of  source  arguments,  depending  on  the  format  string.
            'Encode' behaves exactly like 'print', except that  it  puts  the
            converted  characters  into  the string, rather than putting them
            onto a file.


            AAArrrggguuummmeeennnttt AAAcccccceeessssss

                 Programs  often  find  it  necessary  to  access   arguments
            specified  on  the command line.  These arguments can be obtained
            as EOS-terminated strings, ready for processing or passing  to  a
            routine such as 'open'.

                 _G_e_t_a_r_g.    'Getarg'  is  the  only  routine  that  retrieves
            arguments from the shell's argument buffer.  It  is  called  with
            three  arguments:   an  integer  describing  the  position of the
            argument desired, a character array to receive the argument,  and
            an  integer  describing  the maximum size of the receiving array.
            'Getarg'  tries  to  retrieve  the  argument  in  the   specified
            position;  if  it can, it returns the length of the string placed
            in the array; if it can't, it returns the constant EOF.  'Getarg'
            will never write farther in the character  array  than  the  size
            specified in the third argument.

                 Arguments  are  numbered  0 through the maximum specified on
            the command line.   Argument  0  is  the  name  of  the  command,
            argument  1 is the first argument specified, and so on.  The num-
            ber of arguments present on the command line can be determined by
            the point at which 'getarg' returns EOF.

                 As a short example, here is a program fragment that attempts
            to delete all files specified as arguments on its command line:

                      character file (MAXLINE)
                      integer i
                      integer remove, getarg
                      
                      i = 1
                      while (getarg (i, file, MAXLINE ~= EOF)) {
                         if (remove (file) == ERR)
                            call print (ERROUT, "*s: cannot remove*n"s,
                               file)
                         i = i + 1
                         }



                                         - 76 -                              




            Ratfor User's Guide                                              


                 _P_a_r_s_c_l.  In many programs, argument syntax is quite complex.
            'Parscl' exists for the benefit of both  programmers  and  users:
            it  makes  coding  argument  parsing  simple  and  it  helps keep
            argument conventions uniform.  Of course, to  do  this,  it  must
            automatically enforce certain argument conventions.  'Parscl' and
            its accompanying macros expect to recognize arguments of a single
            letter   without   regard   to   case.   Rather  than  a  lengthy
            explanation, let's look at an  example:   For  its  arguments,  a
            program requires a page length (which should default to 66 if not
            present), a title (which may also not be present), a flag to tell
            whether  to format for for a printer or a terminal, and a list of
            file names to process.  In this case, a reasonable option  syntax
            is

                      prog [-l <page length>] [-t [<title>]] [-p] {<file name>}

            We  have  used  single  letter flags to avoid the need for always
            specifying arguments.  Now, in terms of 'parscl', what we have is
            an "required integer", an "optional string", and a "flag".   This
            means  that "-l" cannot be specified without a <page length>, but
            "-t" can be specified without a <title> (in this case, of course,
            we would use an empty title).  Be sure to note that a  "required"
            argument  means  that if the letter is specified, it must be fol-
            lowed by a value.  It does nnnooottt mean that the letter argument must
            always be present.  In other  circumstances,  we  can  also  have
            "optional integer" and "required string" arguments.

                 To  use  'parscl'  in our program, we must first include the
            argument macros and declare the argument data area:

                         include ARGUMENT_DEFS
                         ARG_DECL

            Then, near the beginning of the main program, we use a macro call
            to call 'parscl' that contains the syntax of the command line and
            a "usage"  message  to  be  displayed  if  the  command  line  is
            incorrect.  For our example, we can use

                         PARSE_COMMAND_LINE ("l<req int> t<opt str> p<flag>"s,
                            "prog [-l <page len>] [-t [<title]] [-p] {<file}>"s)

            For  "optional  integer"  and  "required  string"  arguments, the
            argument types are "<opt int>" and "<req str>", respectively.

                 If the command line is parsed successfully, 'parscl' returns
            and the program continues; otherwise, 'parscl' prints the "usage"
            message with a call to 'error'.  Once 'parscl' has  returned,  we
            can  set  the default values, test for the presence or absence of
            arguments, and obtain values of arguments.  First we usually  set
            default values:

                         ARG_DEFAULT_INT (l, 66)
                         if (ARG_PRESENT (t))
                            ARG_DEFAULT_STR (t, ""s)
                         else
                            ARG_DEFAULT_STR (t, "Listing from prog"s)


                                         - 77 -                              




            Ratfor User's Guide                                              


            Remember, default values are set aaafffttteeerrr the call to 'parscl'!

          |      In  the  preceding example, we set the value of the argument
            for "l" to 66.  This is simple enough.  But for the "t" argument,
            we really have three different cases:  the argument was specified
            with a string, the argument was specified without a string (mean-
            ing that we must use an empty title), or  the  argument  was  not
            specified  at  all  (meaning that we use some other default).  In
            the first case, neither call to ARG_DEFAULT_STR will do anything,
            since the string was specified by the user; in the  second  case,
            ARG_PRESENT  (t)  will  be  ".true."   setting the default to the
            empty string (since the "t" argument was specified,  even  though
            it  was  without a string); and in the third case ARG_PRESENT (t)
            will be ".false.", setting the default to "Listing from prog".

                 Now that we have finished setting defaults,  we  can  obtain
            the values of arguments with more macros:  the call ARG_VALUE (l)
            will return the page length value:  either the value specified by
            the  user  or  the value 66 that we set as the default.  ARG_TEXT
            (t) references an EOS-terminated  string  containing  the  title:
            either the value specified the user, an empty string, or "Listing
            from  prog".   Use  of  the values in our example might look like
            this:

                         page_len = ARG_VALUE (l)
                         call ctoc (ARG_TEXT (t), title, MAXTITLE)
                         if (ARG_PRESENT (p))
                            ### do printer formatting
                         else
                            ### do terminal formatting

            And now, here's how all of the argument parsing will look:

                         include ARGUMENT_DEFS
                         ARG_DECL
                      
                         PARSE_COMMAND_LINE ("l<req int> t<opt str> p<flag>"s,
                            "prog [-l <page len>] [-t [<title]] [-p] {<file}>"s)
                      
                         ARG_DEFAULT_INT (l, 66)
                         if (ARG_PRESENT (t))
                            ARG_DEFAULT_STR (t, ""s)
                         else
                            ARG_DEFAULT_STR (t, "Listing from prog"s)
                      
                         page_len = ARG_VALUE (l)
                         call ctoc (ARG_TEXT (t), title, MAXTITLE)
                         if (ARG_PRESENT (p))
                            ### do printer formatting
                         else
                            ### do terminal formatting


                 Now, what about the file name arguments we were supposed  to
            parse.   Where  did  they go?  'Parscl' deletes arguments that it
            processes; it also ignores any  arguments  not  starting  with  a


                                         - 78 -                              




            Ratfor User's Guide                                              


            hyphen (that do not appear after an letter-argument looking for a
            string).  So the file name arguments are still there, ready to be
            fetched  by 'getarg', with none of the "-t <title>" stuff left to
            confuse the logic of the rest of the program.

                 Now, how about some example commands to call this program:

                         prog -p
                               (page_len = 66, title = "Listing from prog",
                                  formatted for printer)
                      
                         prog -l34 -t new title
                               (page_len = 34, title = "new",
                                  file name = "title",
                                  formatted for terminal)
                      
                         prog file1 file2 -p -t -l70
                               (page_len = 70, title = "",
                                  file names = file1 file2,
                                  formatted for printer)
                      
                         prog filea -t"my new title" -l 60
                               (page_len = 60, title = "my new title",
                                  file name = filea, formatted for printer)
                      
                         prog -x filea
                               (the "usage" message is printed)
                      
                         prog fileb -l
                               (the "usage" message is printed)

            As you can see, 'parscl' allows you to specify arguments in  many
            different  ways.  For more information on 'parscl', see its entry
            in the Reference Manual.


            DDDyyynnnaaammmiiiccc SSStttooorrraaagggeee MMMaaannnaaagggeeemmmeeennnttt

                 Dynamic storage subroutines reserve and free  variable  size
            blocks  from an area of memory.  In this implementation, the area
            of memory is a one-dimensional array.   Each  block  consists  of
            consecutive words of that array.

                 The  dynamic  storage routines assume that you have included
            the following declaration in your main program and  in  any  sub-
            programs that reference dynamic storage:

                      DS_DECL (mem, MEMSIZE)

            where  'mem'  is  an array name that can be used to reference the
            dynamic storage area.  You must also define MEMSIZE to an integer
            value between 6 and 32767 inclusive.  This number is the  maximum
            amount  of  space  available  for  use  by  the  dynamic  storage
            routines.  In  estimating  for  the  amount  of  dynamic  storage
            required,  you must allow for two extra 'overhead' words for each
            block allocated.  Three other overhead words are required  for  a


                                         - 79 -                              




            Ratfor User's Guide                                              


            pointer  to  the first available block of memory and to store the
            value of MEMSIZE.

                 _D_s_i_n_i_t.  The call

                      call dsinit (MEMSIZE)

            initializes the storage structure's pointers and sets up the list
            of free  blocks.   This  call  must  be  made  before  any  other
            references to the dynamic storage area are made.

                 _D_s_g_e_t.   'Dsget'  allocates  a block of words in the storage
            area and returns a pointer (array index)  to  the  first  useable
            word  of  the  block.   It  takes one argument -- the size of the
            block to be allocated (in words).

                 After a call to 'dsget', you may then fill consecutive words
            in the 'mem' array beginning at the pointer returned  by  'dsget'
            (up  to  the  number  of  words  you requested in the block) with
            whatever information called for  by  your  application.   If  you
            should write more words to the block than you allocated, the next
            block  will be overwritten.  Needless to say, if this happens you
            may as well give up and start over.

                 If 'dsget' finds that there is not enough contiguous storage
            space to satisfy your request, it prints an error message, and if
            you desire, calls 'dsdump' to give you a dump of the contents  of
            the dynamic storage array.

                 _D_s_f_r_e_e.   A  call  to  'dsfree' with a pointer to a block of
            storage (obtained from a call to 'dsget') deallocates  the  block
            and  makes  it available for later use by 'dsget'.  'Dsfree' will
            warn you if it detects an attempt to free  an  unallocated  block
            and give you the option of terminating or continuing the program.

                 _D_s_d_u_m_p.   The  dynamic  storage  routines  cannot  check for
            correct usage  of  dynamic  storage.   Because  block  sizes  and
            pointers  are  also stored in 'mem' it is very easy for a mistake
            in your program to  destroy  this  information.   'Dsdump'  is  a
            subroutine  that  can  print  the dynamic storage area in a semi-
            readable format to assist in debugging.  It takes  one  argument:
            the  constant  LETTER  for  an alphanumeric dump, or the constant
            DIGIT for a numeric dump.

                 The following example shows the use of the  dynamic  storage
            routines  and  uses  'dsdump' to show the changes in storage that
            result from each call.











                                         - 80 -                              




            Ratfor User's Guide                                              


                      define (MEMSIZE, 35)
                      
                      pointer pos1, pos2   # pointer is a subsystem defined type
                      pointer dsget
                      DS_DECL (mem, MEMSIZE)
                      
                      call dsinit (MEMSIZE)
                      call dsdump (LETTER) # first call
                      
                      pos1 = dsget (4)
                      call scopy ("aaa"s, 1, mem, pos1)
                      call dsdump (LETTER) # second call
                      
                      pos2 = dsget (3)
                      call scopy ("bb"s, 1, mem, pos2)
                      call dsdump (LETTER) # third call
                      
                      call dsfree (pos2)
                      call dsdump (LETTER) # fourth call
                      
                      stop
                      end

            The first call to 'dsdump' (after 'init') produces the  following
            dump:

                      * DYNAMIC STORAGE DUMP *
                          1   3 words in use
                          4   32 words available
                      * END DUMP *

            The first three words are used for overhead, and 32 (MEMSIZE - 3)
            words are available starting at word four in 'mem'.

                 The  second  call  to  'dsdump'  (after  the  first write to
            dynamic storage) produces the following:

                      * DYNAMIC STORAGE DUMP *
                          1   3 words in use
                          4   26 words available
                         30   6 words in use
                                aaa
                      * END DUMP *

            Note that only four characters were written, three a's and an EOS
            (an EOS is a nonprinting character), but two extra control  words
            are required for each block.  That block is comprised of words 30
            - 35 in the array 'mem'.

                 The  third  call  to  'dsdump'  (after  the  second 'scopy')
            produces the following:







                                         - 81 -                              




            Ratfor User's Guide                                              


                      * DYNAMIC STORAGE DUMP *
                          1   3 words in use
                          4   21 words available
                         25   5 words in use
                                bb
                         30   6 words in use
                                aaa
                      * END DUMP *

            The final call to 'dsdump' produces:

                      * DYNAMIC STORAGE DUMP *
                          1   3 words in use
                          4   26 words available
                         30   6 words in use
                                aaa
                      * END DUMP *

            As you can see, the second block of storage that began at word 25
            has been returned to the list of available space.


            SSSyyymmmbbbooolll TTTaaabbbllleee MMMaaannniiipppuuulllaaatttiiiooonnn

                 Symbol table routines allow you to index tabular data with a
            character string rather than an integer subscript.  For instance,
            in the following table, the information  contained  in  "field1",
            "field2",  and  "field3" can obtained by specifying a certain key
            value (e.g.  "firstentry").

                      ----------------------------------------
                      |key         |field1 | field2   |field3|
                      ----------------------------------------
                      |firstentry  | 10268 | data     |  u   |
                      |            |       |          |      |
                      |secondentry | 27043 | moredata |  a   |
                      ----------------------------------------


                 All Subsystem symbol table  routines  use  dynamic  storage.
            Therefore,  the  declarations  and  initialization  required  for
            dynamic storage are also required for the symbol table  routines;
            namely:

                      DS_DECL (mem, MEMSIZE)
                      ...
                      call dsinit (MEMSIZE)

            where  'mem'  is  an array name that can be used to reference the
            dynamic storage area, and MEMSIZE is  a  user-defined  identifier
            describing how many words are to be reserved for items in dynamic
            storage.   MEMSIZE  must  be  a integer value between 6 and 32767
            inclusive.  For a discussion on how to  estimate  the  amount  of
            dynamic  storage space needed in a program, you can refer back to
            the section on the dynamic storage routines.



                                         - 82 -                              




            Ratfor User's Guide                                              


                 A symbol table entry consists of two parts:   an  identifier
            and  its  associated  data.   The identifier is a variable length
            character string; it is dynamically created when  the  symbol  is
            entered into a symbol table.  The data associated with the symbol
            is  treated  as  a  fixed-length  array  of words to be stored or
            modified when the associated symbol is entered in the  table  and
            returned  when  the symbol is looked up.  The size of the data is
            fixed for each symbol table -- each entry in a  table  must  have
            associated data of the same size, but different symbol tables may
            have different lengths of data.

                 _M_k_t_a_b_l.   A symbol table is created by a call to the pointer
            function 'mktabl' with a single integer argument giving the  size
            of  the  associated  data  array  or  the  "node size".  'Mktabl'
            returns a pointer to the symbol table in dynamic  storage.   This
            returned  pointer identifies the symbol table -- you must pass it
            to the other symbol table routines to identify  which  table  you
            want  to  reference.   A  symbol  table is relatively small (each
            table requires about 50 words, not counting the symbols stored in
            it), so you may create as many of them as you like  (as  long  as
            you have room for them).

                 In  the  table  above,  if "field1" and "field3" require one
            word each, and "field2" requires no more than 9 words,  then  you
            can create the symbol table with the following call:

                      pointer extable
                      ...
                      extable = mktabl (11)

            The argument to 'mktabl' is 11 -- the total length of the data to
            be associated with each symbol.

                 _E_n_t_e_r.   To  enter  a  symbol  in  a  symbol table, you must
            provide two  items:   an  EOS-terminated  string  containing  the
            identifier to be placed in the table, and an array containing the
            data to be associated with the symbol.  Of course this array must
            be  at  least  as  large  as  the  "nodesize"  declared  when the
            particular symbol table was created.  A call  to  the  subroutine
            'enter' with the identifier, the data array, and the symbol table
            pointer  will make an entry in the symbol table.  However, if the
            identifier is already in the table, its associated data  will  be
            overwritten  by that you've just supplied.  It is not possible to
            have the same identifier in the same symbol table twice.

                 Now, continuing our example,  to  enter  the  first  row  of
            information in the table, you can use the following statements:

                      info (1) = 10268
                      call scopy ("data"s, 1, info, 2)
                      info (11) = 'u'c
                      call enter ("firstentry"s, info, extable)


                 _L_o_o_k_u_p.   Once you've made an entry in the symbol table, you
            can retrieve it by supplying the identifier in an  EOS-terminated


                                         - 83 -                              




            Ratfor User's Guide                                              


            string,  an empty data array, and the symbol table pointer to the
            function 'lookup'.  If 'lookup' can find the  identifier  in  the
            table,  it  will  fill  in  your  data array with the data it has
            stored with the symbol and  return  with  YES  for  its  function
            value.   Otherwise,  it  will just return with NO as its function
            value.

                 In our example, to access the data associated with the "fir-
            stentry" we can make the following call:

                      foundit = lookup ("firstentry"s, info, extable)

            After this call (assuming that "firstentry" was  in  the  table),
            "foundit"  would  have  the  value YES, "info (1)" would have the
            value for "field1", "info (2)" through "info (10)" would have the
            value for "field2", and "info (11)"  would  have  the  value  for
            "field3".

                 _D_e_l_e_t_e.  If you should want to get rid of an entry in a sym-
            bol  table,  you  can make a call to the subroutine 'delete' with
            identifier you want to delete in an EOS-terminated string and the
            symbol table pointer.  If the  identifier  you  pass  is  in  the
            table,  'delete' will delete it and free its space for later use.
            If the identifier is not in the table,  then  'delete'  won't  do
            anything.

                 Using  our example again, if you want to delete 'firstentry'
            from the table, you can just make the call

                      call delete ("firstentry"s, extable)

            and "firstentry" will be removed from the table.

                 _R_m_t_a_b_l.  When you are through  with  a  table  and  want  to
            reclaim  all  of its storage space, you pass the table pointer to
            'rmtabl'.  'Rmtabl' will delete all of the symbols in  the  table
            and  release  the storage space for the table itself.  Of course,
            after you remove a table, you can never reference it again.

                 To complete our example, we can get rid of our symbol  table
            by just calling 'rmtabl':

                      call rmtabl (extable)


                 _S_c_t_a_b_l.   So  far, the routines we've talked about have been
            sufficient for dealing with symbol tables.   It  turns  out  that
            there  is  one missing operation:  getting entries from the table
            without knowing the identifiers.  The  need  for  this  operation
            arises under many circumstances.  Perhaps the most common is when
            we  want  to  print out the contents of a symbol table for debug-
            ging.

                 To use 'sctabl' to return the contents of  a  symbol  table,
            you  first  need  to  initialize  a  pointer with the value zero.
            We'll call this the position pointer from now on.  Then you  call


                                         - 84 -                              




            Ratfor User's Guide                                              


            'sctable'  repeatedly,  passing  it  the  symbol table pointer, a
            character array for the name, a data  array  for  the  associated
            data,  and the position pointer.  Each time you call it, 'sctabl'
            will return another entry in the table:   it  will  fill  in  the
            character  string  with the entry's identifier, fill in your data
            array with the entry's data, and update position in the  position
            pointer.   When there are no more entries to return in the table,
            'sctabl' returns EOF as its function value.

                 There are two things you have to watch when using  'sctabl'.
            First,  if  you don't keep calling 'sctabl' until it returns EOF,
            you must call 'dsfree' with the position pointer to  release  the
            space.   Second,  you  may  call 'enter' to _m_o_d_i_f_y the value of a
            symbol while scanning a table, but you cannot use 'enter' to  add
            a  new  symbol  or  use  'delete' to remove a symbol.  If you do,
            'sctabl' may lose its place and return garbage,  or  it  may  not
            return at all!

                 Here  is  a  subroutine  that  will dump the contents of our
            example symbol table:

                      # stdump --- print the contents of a symbol table
                         subroutine stdump (table)
                         pointer table
                      
                         integer posn
                         integer sctabl
                         character symbol (MAXSTR)
                         untyped info (11)
                      
                         call print (ERROUT, "*4xSymbol*12xInfo*n"s)
                      
                         posn = 0
                         while (sctabl (table, symbol, info, posn) ~= EOF)
                            call print (ERROUT, "*15s|*6i|*9s|*c*n"s,
                                    symbol, info (1), info (2), info (9))
                      
                         return
                         end

            If make a call to 'stdump' after made the entry for "firstentry",
            it would print the following:

                          Symbol            Info
                      firstentry     | 10268|data     |u



            OOOttthhheeerrr RRRooouuutttiiinnneeesss

                 There are a number of miscellaneous  routines  that  provide
            often  needed  assistance.  The following table gives their names
            and a brief description.  For full information on their use,  see
            the Subsystem reference manual:

                 date     Obtain date, time, process id, login name


                                         - 85 -                              




            Ratfor User's Guide                                              


                 error    Print an error message and terminate

                 follow   Follow  a path and set the current and/or home
                          directories

                 remark   Print a string followed by a newline

                 tquit$   Check if the break key was hit

                 wkday    Determine the day of the week of any date
















































                                         - 86 -                              




            Ratfor User's Guide                                              


                                       ___AAA___ppp___ppp___eee___nnn___ddd___iii___xxx___eee___sss




                   AAAppppppeeennndddiiixxx AAA ------ IIImmmpppllleeemmmeeennntttaaatttiiiooonnn ooofff CCCooonnntttrrrooolll SSStttaaattteeemmmeeennntttsss


                 This appendix contains flowcharts of the  code  produced  by
            the  Ratfor  control statements along with actual examples of the
            code Ratfor produces.

                 In different contexts, a given sequence  of  Ratfor  control
            statements  can  generate  slightly different code.  First, where
            possible, statement labels are not produced  when  they  are  not
            referenced.   For  instance,  a  rrreeepppeeeaaattt  loop containing no bbbrrreeeaaakkk
            statements will have no "exit" label generated, since one is  not
            needed.   Second, cccooonnntttiiinnnuuueee statements are generated only when two
            statement numbers must reference the  same  statement.   Finally,
            internally generated gggoootttooo statements are omitted when control can
            never  pass  to  them;  e.g.   a wwwhhheeennn clause ending with a rrreeetttuuurrrnnn
            statement.

                 These  code  generation  techniques  make   no   fundamental
            difference  in  the  control-flow  of a program, but can make the
            code generated by very similar instances of a  control  statement
            appear quite different.  Please keep in mind that the examples of
            Fortran code generated by 'rp' are included for completeness, and
            are  not  necessarily character-for-character descriptions of the
            code that would be obtained from preprocessing.  Rather, they are
            intended to illustrate the manner in which the Ratfor  statements
            are implemented in Fortran.


























                                         - 87 -                              




            Ratfor User's Guide                                              


                                          BBBrrreeeaaakkk



            _S_y_n_t_a_x:

                      break [<levels>]

            _F_u_n_c_t_i_o_n:

                 Causes an immediate exit from the referenced loop.

            _E_x_a_m_p_l_e:

                      for (i = length (str); i > 0; i = i - 1)
                         if (str (i) ~= ' 'c)
                            break
                      
                      
                            i=length(str)
                            goto 10002
                      10000 i=i-1
                      10002 if((i.le.0))goto 10001
                              if((str(i).eq.160))goto 10003
                                goto 10001
                      10003 goto 10000
                      10001 continue































                                         - 88 -                              




            Ratfor User's Guide                                              


                                           DDDooo



            _S_y_n_t_a_x:

                      do <limits>
                         <statement>

            _F_u_n_c_t_i_o_n:

                             |
                             V
                   ---------------------
                   |                   |
                   |  initialize do    |
                   |                   |
                   ---------------------
                             |<-----------------------------------------
                             V                                         |
                   ---------------------                               |
                   |                   |                               |
                   |    <statement>    |                               |
                   |                   |                               |
                   ---------------------                               |
                             |                                         |
                             V                                         |
                             *                                         |
                          *     *           ---------------------      |
                       *           *  false |                   |      |
                    *  do satisfied?  * --->|  reinitialize do  |----->|
                       *           *        |                   |
                          *     *           ---------------------
                             *
                             | true
                             V

            _E_x_a_m_p_l_e:

                      do i = 1, 10
                         array (i) = 0
                      
                      
                            do 10000 i=1,10
                      10000 array(i)=0













                                         - 89 -                              




            Ratfor User's Guide                                              


                                           FFFooorrr



            _S_y_n_t_a_x:

                      for ([<initialize>]; [<condition>]; [<reinitialize>])
                         <statement>

            _F_u_n_c_t_i_o_n:

                                   |
                                   V
                         ---------------------
                         |                   |
                         |   <initialize>    |
                         |                   |
                         ---------------------
                    -------------->|
                    |              V
                    |              *
                    |           *     *
                    |        *           *    false
                    |     *   <condition>   * ------>|
                    |        *           *           |
                    |           *     *              |
                    |              *                 |
                    |              | true            |
                    |              V                 |
                    |    ---------------------       |
                    |    |                   |       |
                    |    |    <statement>    |       |
                    |    |                   |       |
                    |    ---------------------       |
                    |              |                 |
                    |              V                 |
                    |    ---------------------       |
                    |    |                   |       |
                    |    |  <reinitialize>   |       |
                    |    |                   |       |
                    |    ---------------------       |
                    |              |                 |
                    |              V                 |
                    |---------------                 |
                                                     |
                                   |------------------
                                   V











                                         - 90 -                              




            Ratfor User's Guide                                              


            _E_x_a_m_p_l_e:

                      for (i = limit - 1; i > 0; i = i - 1) {
                         array_1 (i) = array_1 (i + 1)
                         array_2 (i) = array_2 (i + 1)
                         }
                      
                      
                            i=limit-1
                            goto 10002
                      10000 i=i-1
                      10002 if((i.le.0))goto 10001
                              array1(i)=array1(i+1)
                              array2(i)=array2(i+1)
                            goto 10000
                      10001 continue










































                                         - 91 -                              




            Ratfor User's Guide                                              


                                           IIIfff



            _S_y_n_t_a_x:

                      if (<condition>)
                         <statement>

            _F_u_n_c_t_i_o_n:

                             |
                             V
                             *
                          *     *           ---------------------
                       *           *   true |                   |
                    *   <condition>   * --->|    <statement>    |----->|
                       *           *        |                   |      |
                          *     *           ---------------------      |
                             *                                         |
                             | false                                   |
                             |<-----------------------------------------
                             V

            _E_x_a_m_p_l_e:

                      if (a == b) {
                         c = 1
                         d = 1
                         }
                      
                      
                            if((a.ne.b))goto 10000
                              c=1
                              d=1
                      10000 continue






















                                         - 92 -                              




            Ratfor User's Guide                                              


                                        IIIfff --- EEElllssseee



            _S_y_n_t_a_x:

                      if (<condition>)
                         <statement_1>
                      else
                         <statement_2>

            _F_u_n_c_t_i_o_n:

                                             |
                                             V
                                             *
                                          *     *
                              true     *           *    false
                            |<----- *   <condition>   * ----->|
                            |          *           *          |
                            |             *     *             |
                            V                *                V
                   ---------------------           ---------------------
                   |                   |           |                   |
                   |   <statement_1>   |           |   <statement_2>   |
                   |                   |           |                   |
                   ---------------------           ---------------------
                             |                                |
                             V                                V
                             ----------------------------------
                                             |
                                             V

            _E_x_a_m_p_l_e:

                      if (i >= MAXLINE)
                         i = 1
                      else
                         i = i + 1
                      
                      
                            if((i.lt.102))goto 10000
                              i=1
                              goto 10001
                      10000   i=i+1
                      10001 continue












                                         - 93 -                              




            Ratfor User's Guide                                              


                                          NNNeeexxxttt



            _S_y_n_t_a_x:

                      next [<levels>]

            _F_u_n_c_t_i_o_n:

                 All  loops  nested within the loop specified by <levels> are
                 terminated.  Execution resumes with the  next  iteration  of
                 the loop specified by <levels>.

            _E_x_a_m_p_l_e:

                        # output only strings containing no blanks
                      for (i = 1; i <= LIMIT; i = i + 1) {
                         for (j = 1; str (j, i) ~= EOS; j = j + 1)
                            if (str (j, i) == ' 'c)
                               next 2
                         call putlin (str (1, i), STDOUT)
                         }
                      
                      
                            i=1
                            goto 10002
                      10000 i=i+1
                      10002 if((i.gt.50))goto 10001
                              j=1
                              goto 10005
                      10003   j=j+1
                      10005   if((str(j,i).eq.-2))goto 10004
                                if((str(j,i).ne.160))goto 10006
                                  goto 10000
                      10006   goto 10003
                      10004   call putlin(str(1,i),-11)
                            goto 10000
                      10001 continue



















                                         - 94 -                              




            Ratfor User's Guide                                              


                                         RRReeepppeeeaaattt



            _S_y_n_t_a_x:

                      repeat
                         <statement>
                         [until (<condition>)]

            _F_u_n_c_t_i_o_n:

                                   |
                                   |<-----------------
                                   V                 |
                         ---------------------       |
                         |                   |       |
                         |    <statement>    |       |
                         |                   |       |
                         ---------------------       |
                                   |                 |
                                   V                 |
                                   *                 |
                                *     *              |
                             *           *    false  |
                          *   <condition>   * ------>|
                             *           *
                                *     *
                                   *
                                   | true
                                   V

            _E_x_a_m_p_l_e:

                      repeat {
                         i = i + 1
                         j = j + 1
                         } until (str (i) ~= ' 'c)
                      
                      
                      10000   i=i+1
                              j=j+1
                            if((str(i).eq.160))goto 10000















                                         - 95 -                              




            Ratfor User's Guide                                              


                                         RRReeetttuuurrrnnn



            _S_y_n_t_a_x:

                      return [ '(' <expression ')' ]

            _F_u_n_c_t_i_o_n:

                 Causes  <expression>  (if  specified)  to be assigned to the
                 function name, and then causes a return from the subprogram.

            _E_x_a_m_p_l_e:

                      integer function fcn (x)
                      ...
                      return (a + 12)
                      
                            integer function fcn (x)
                            ...
                            fcn=a+12
                            return



































                                         - 96 -                              




            Ratfor User's Guide                                              


                                         SSSeeellleeecccttt



            _S_y_n_t_a_x:

                      select
                         when (<condition_1>)
                            <statement_1>
                         when (<condition_2>)
                            <statement_2>
                         when (<condition_3>)
                            <statement_3>
                              .
                              .
                              .
                         when (<condition_n>)
                            <statement_n>
          *           [ifany
                         <statement_i>]
                      [else
                         <statement_e>]




































                                         - 97 -                              




            Ratfor User's Guide                                              


            _F_u_n_c_t_i_o_n:

                            |
                            V
                            *
                         *     *           ---------------------
                      *           *   true |                   |
                   *  <condition_1>  * --->|   <statement_1>   |->|
                      *           *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     |
                            *                                     |
                         *     *           ---------------------  |
                      *           *   true |                   |  |
                   *  <condition_2>  * --->|   <statement_2>   |->|
                      *           *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     |
                            *                                     |
                         *     *           ---------------------  |
                      *           *   true |                   |  |
                   *  <condition_3>  * --->|   <statement_3>   |->|
                      *           *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     |
                            .                                     .
                            .                                     .
                            .                                     .
                            | false                               |
                            V                                     |
                            *                                     |
                         *     *           ---------------------  |
                      *           *   true |                   |  |
                   *  <condition_n>  * --->|   <statement_n>   |->|
                      *           *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     V
                  ---------------------                 ---------------------
                  |                   |                 |                   |
                  |   <statement_e>   |                 |   <statement_i>   |
                  |                   |                 |                   |
                  ---------------------                 ---------------------
                            |                                     |
                            |                                     V
                            |<-------------------------------------
                            V




                                         - 98 -                              




            Ratfor User's Guide                                              


            _E_x_a_m_p_l_e:

                      select
                         when (i == 1)
                            call add_record
                         when (i == 2)
                            call delete_record
                      else
                         call code_error
                      
                      
                            goto 10001
                      10002   call addre0
                            goto 10000
                      10003   call delet0
                            goto 10000
                      10001 if((i.eq.1))goto 10002
                            if((i.eq.2))goto 10003
                              call codee0
                      10000 continue






































                                         - 99 -                              




            Ratfor User's Guide                                              


                              SSSeeellleeecccttt (((<<<iiinnnttteeegggeeerrr eeexxxppprrreeessssssiiiooonnn>>>)))



            _S_y_n_t_a_x:

                      select (<i0>)
                         when (<i1.1>, <i1.2>, ...)
                            <statement_1>
                         when (<i2.1>, <i2.2>, ...)
                            <statement_2>
                         when (<i3.1>, <i3.2>, ...)
                            <statement_3>
                              .
                              .
                              .
                         when (<in.1>, <in.2>, ...)
                            <statement_n>
          *           [ifany
                         <statement_i>]
                      [else
                         <statement_e>]




































                                         - 100 -                             




            Ratfor User's Guide                                              


            _F_u_n_c_t_i_o_n:

                            |
                            V
                            *
                         *     *           ---------------------
                      *   i0 ==   *   true |                   |
                   *  i1.1 or i1.2   * --->|   <statement_1>   |->|
                      *  or ...   *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     |
                            *                                     |
                         *     *           ---------------------  |
                      *   i0 ==   *   true |                   |  |
                   *  i2.1 or i2.2   * --->|   <statement_2>   |->|
                      *  or ...   *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     |
                            *                                     |
                         *     *           ---------------------  |
                      *   i0 ==   *   true |                   |  |
                   *  i3.1 or i3.2   * --->|   <statement_3>   |->|
                      *  or ...   *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     |
                            .                                     .
                            .                                     .
                            .                                     .
                            | false                               |
                            V                                     |
                            *                                     |
                         *     *           ---------------------  |
                      *   i0 ==   *   true |                   |  |
                   *  in.1 or in.2   * --->|   <statement_n>   |->|
                      *  or ...   *        |                   |  |
                         *     *           ---------------------  |
                            *                                     |
                            | false                               |
                            V                                     V
                  ---------------------                 ---------------------
                  |                   |                 |                   |
                  |   <statement_e>   |                 |   <statement_i>   |
                  |                   |                 |                   |
                  ---------------------                 ---------------------
                            |                                     |
                            |                                     V
                            |<-------------------------------------
                            V




                                         - 101 -                             




            Ratfor User's Guide                                              


            _E_x_a_m_p_l_e:

                      select (i)
                         when (4, 6, 3003)
                            call add_record
                         when (2, 12, 5000)
                            call delete_record
                      else
                         call code_error
                      
                      
                            integer aaaaa0,aaaab0
                            ...
                            aaaaa0=i
                            goto 10001
                      10002   call addre0
                            goto 10000
                      10003   call delet0
                            goto 10000
                      10001 aaaab0=aaaaa0-1
                            goto(10003,10004,10002,10004,10002,
                           *     10004,10004,10004,10004,10004,
                           *     10003),aaaab0
                            if(aaaaa0.eq.3003)goto 10002
                            if(aaaaa0.eq.5000)goto 10003
                      10004 continue
                      10000 continue































                                         - 102 -                             




            Ratfor User's Guide                                              


                                          WWWhhhiiillleee



            _S_y_n_t_a_x:

                      while (<condition>)
                         <statement>

            _F_u_n_c_t_i_o_n:

                                   |
                    -------------->|
                    |              V
                    |              *
                    |           *     *
                    |        *           *    false
                    |     *   <condition>   * ------>|
                    |        *           *           |
                    |           *     *              |
                    |              *                 |
                    |              | true            |
                    |              V                 |
                    |    ---------------------       |
                    |    |                   |       |
                    |    |    <statement>    |       |
                    |    |                   |       |
                    |    ---------------------       |
                    |              |                 |
                    |              V                 |
                    |---------------                 |
                                                     |
                                   |------------------
                                   V

            _E_x_a_m_p_l_e:

                      while (str (i) ~= EOS)
                         i = i + 1
                      
                      
                      10000 if((str(i).eq.-2))goto 10001
                              i=i+1
                            goto 10000
                      10001 continue













                                         - 103 -                             




            Ratfor User's Guide                                              


                 AAAppppppeeennndddiiixxx BBB ------ LLLiiinnnkkkiiinnnggg PPPrrrooogggrrraaammmsss WWWiiittthhh IIInnniiitttiiiaaallliiizzzeeeddd CCCooommmmmmooonnn


                 The Subsystem link procedure makes the assumption  that  all
            common  areas are uninitialized to allow programs to access up to
            27 64K word  segments  of  data  space.   A  program  which  uses
            initialized  common areas must be linked with one of two slightly
            different procedures:  If the object file can be a segment direc-
            tory (this is usually not a problem), you  can  have  the  object
            file  placed in a segment directory.  Just add the "-d" option to
            the 'ld' command  line.   Assuming  your  binary  file  is  named
            "prog.b", you can use the command

                      ld -d prog.b


                 If  you  would  rather  the  object  program  be stored in a
            regular file, you can use a slightly different  procedure.   With
            this  procedure,  the  program  is restricted to _o_n_e _s_e_g_m_e_n_t (_6_4_K
            _w_o_r_d_s) for both code and data space.  If this limit is  exceeded,
            no  warning  will  be given, and unpredictable results will occur
            during execution.  If more than 64K words of space  is  required,
            the  common areas must be initialized at run time, or the program
            must be placed in a segment directory.

                 This modification to the link procedure is as follows:   the
            option  string  "-s 'co ab 4000'" must appear on the 'ld' command
            line before the first binary file.  For  instance,  if  the  file
            "prog.b"  contained a program with bbbllloooccckkk dddaaatttaaa statements, an 'ld'
            command to link it might appear as follows:

                      ld -s 'co ab 4000' prog.b

            The executable program would be placed in the file "prog.o".
























                                         - 104 -                             




            Ratfor User's Guide                                              


                    AAAppppppeeennndddiiixxx CCC ------ RRReeeqqquuuiiirrreeemmmeeennntttsss fffooorrr SSSuuubbbsssyyysssttteeemmm PPPrrrooogggrrraaammmsss


                 This  appendix  gives  the   technical   specifications   of
            requirements  for  programs  that run under the Subsystem.  It is
            included to allow non-Ratfor programs to run under the Subsystem.

            _3_2_S _a_n_d _1_6_S _a_d_d_r_e_s_s_i_n_g _m_o_d_e_s

                -  There is no support for the execution of these  addressing
                   modes.


            _6_4_R _& _3_2_R _a_d_d_r_e_s_s_i_n_g _m_o_d_e_s

                -  The  64R mode library routines cannot access the Subsystem
                   common areas, so 32R and 64R mode programs cannot  execute
          |        under the Subsystem.


            _6_4_V _a_d_d_r_e_s_s_i_n_g _m_o_d_e

                -  Segments '4040 and '4041 may not be disturbed.

                -  When a Subsystem program is executed, the stack is already
                   constructed  in  segment  '4041.   However,  the executing
                   program may rebuild it if desired.

                -  Programs that use native i/o routines  must  inform  their
                   native i/o routines of the Subsystem (if they wish to take
                   advantage   of   Subsystem  i/o)  by  calling  the  proper
                   initialization routines, i.e.  'init$f' for Fortran 66 and
                   Fortran 77, 'init$p' for Pascal and 'init$plg' for PL/I G.

                -  The program must terminate with a call  to  the  Subsystem
                   routine  'swt'  at  the  end  of its execution or its main
                   program must return to its caller.  A  ssstttoooppp  statement  in
                   Ratfor will be transformed into a call to 'swt'.

                -  The  program  must  not tamper with any file units already
                   open by the Subsystem.  It should always use  a  Subsystem
                   or Primos call to obtain an unused file unit.

                -  The  program  must  be  in a P300 format runfile or a SEG-
                   compatible segment directory.

                -  If the program is in a P300 format runfile, it  must  have
                   been  loaded  by  the  modified  version  of the segmented
                   loader, 'swtseg', or the entry control block for the  main
                   program must be at location '1000 in segment '4000.

                -  The  runfile  must not expect any segment other than '4000
                   to be initialized before execution, unless  it  is  loaded
                   from a SEG-compatible segment directory.

                -  The  default load sequence produced by 'ld' will correctly


                                         - 105 -                             




            Ratfor User's Guide                                              


                   link programs requiring  up  to  64K  words  of  procedure
                   (code) and linkage (initialized local data) frames.  Up to
                   27  64K word segments may be used for uninitialized common
                   blocks.  Up to 64K words of local data may be allocated on
                   the stack.  Programs loaded  from  SEG-compatible  segment
                   directories  may  be  as  large  as  the  operating system
                   permits, as long as they do not modify segments '4040  and
                   '4041.


            _3_2_I _a_d_d_r_e_s_s_i_n_g _m_o_d_e

                -  Programs  in  32I mode may be executed under the Subsystem
                   subject to the same constraints as 64V mode programs.












































                                         - 106 -                             




            Ratfor User's Guide                                              


                         AAAppppppeeennndddiiixxx DDD ------ TTThhheee SSSuuubbbsssyyysssttteeemmm DDDeeefffiiinnniiitttiiiooonnnsss


                 The  file  "=incl=/swt_def.r.i"   contains   Ratfor   dddeeefffiiinnneee
            statements  for  all  the  symbolic constants required to use the
            routines  in  the  Subsystem  support  library.   This   appendix
            describes  the more frequently used constants and the constraints
            placed on them.


            CCChhhaaarrraaacccttteeerrrsss

                 ASCII Mnemonics.  Character  definitions   for   the   ASCII
                           control characters NUL, SOH, STX, ..., GS, RS, US,
                           as well as SP and DEL.
                 Control characters.  Character  definitions  for  the  ASCII
                           control characters CTRL_AT, CTRL_A,  CTRL_B,  ...,
                           CTRL_LBRACK,      CTRL_BACKSLASH,     CTRL_RBRACK,
                           CTRL_CARET, and CTRL_UNDERLINE.
                 BACKSPACE Synonym for ASCII BS.
                 TAB       Synonym for ASCII HT.
                 BELL      Synonym for ASCII BEL.
                 RHT       Relative horizontal tab character (used for  blank
                           compression in Primos text files).
                 RUBOUT    Synonym for ASCII DEL.


            DDDaaatttaaa TTTyyypppeeesss

                 bits      Bit strings (16 bit items).
                 bool      Boolean  (logical)  values: .true. and .false. (16
                           bit items).
                 character Single   right-justified   zero-filled   character
                           (scalar),   or   a   string  of  these  characters
                           terminated by an EOS (array).
                 file_des  File descriptor returned 'open', 'create', etc.
                 file_mark File position returned by 'seekf'.
                 longint   Double precision (32 bit) integer.
                 longreal  Double precision (64 bit) floating point.
                 pointer   Pointer for use with dynamic  storage  and  symbol
                           table routines.


            MMMaaacccrrrooo SSSuuubbbrrrooouuutttiiinnneeesss

                 fpchar (<packed array>, <index>, <character>) Fetches
                           <character> from <packed array> at character posi-
                           tion  <index>  and  increments <index>.  The first
                           character in the array is position zero.
                 spchar (<packed array>, <index>, <character>) Stores
                           <character> in <packed array> at  character  posi-
                           tion  <index>  and  increments <index>.  The first
                           character in the array is position zero.
                 getc (<char>) Behaves  exactly  like  'getch',  except   the
                           character is always obtained from STDIN.
                 putc (<char)) Behaves   exactly  like  'putch',  except  the


                                         - 107 -                             




            Ratfor User's Guide                                              


                           character is always placed on STDOUT.
                 SKIPBL (<character array>, <index>) Increments <index> until
                           the corresponding position in the character  array
                           is non-blank.
                 DS_DECL (<ds array name>, <ds array size>) Declares      the
                           dynamic storage array  with  the  name  <ds  array
                           name> with size <ds array size>.


            LLLaaannnggguuuaaagggeee EEExxxttteeennnsssiiiooonnnsss

                 ARB       Used  when  dimensioning  array parameters in sub-
                           programs (since their length is determined by  the
                           calling program, not the subprogram).
                 FALSE     Represents the Fortran logical constant .false.
                 IS_DIGIT (<char>) Logical expression yielding TRUE if <char>
                           is a digit.
                 IS_LETTER (<char>) Logical   expression   yielding  TRUE  if
                           <char> is an upper or lower case letter.
                 IS_UPPER (<char>) Logical expression yielding TRUE if <char>
                           is an upper case letter.
                 IS_LOWER (<char>) Logical expression yielding TRUE if <char>
                           is a lower case letter.
                 SET_OF_UPPER_CASE Sequence   of   26   character   constants
                           representing the upper case letters for use in the
                           wwwhhheeennn parts of ssseeellleeecccttt statements.
                 SET_OF_LOWER_CASE Sequence   of   26   character   constants
                           representing the lower case  letters  for  use  in
                           wwwhhheeennn parts of ssseeellleeecccttt statements.
                 SET_OF_LETTERS Sequence of 52 character constants represent-
                           ing  the  upper  and lower case letters for use in
                           wwwhhheeennn parts of ssseeellleeecccttt statements.
                 SET_OF_DIGITS Sequence of 10 character constants  represent-
                           ing  the  digits  for  use in wwwhhheeennn parts of ssseeellleeecccttt
                           statements.
                 SET_OF_CONTROL_CHAR Sequence  of  32   character   constants
                           representing the first 32 ASCII control characters
                           for use in wwwhhheeennn parts of ssseeellleeecccttt statements.
                 TRUE      Represents the Fortran logical constant .true.


            LLLiiimmmiiitttsss

                 CHARS_PER_WORD Maximum   number  of  packed  characters  per
                           machine word.
                 MAXINT    Largest 16-bit integer.
                 MAXARG    Maximum length of a command  line  argument  (EOS-
                           terminated character string).
                 MAXCARD   Maximum input line length (excluding the EOS).
                 MAXDECODE Maximum size of string processed by 'decode'.
                 MAXLINE   Maximum input line length.
                 MAXPAT    Maximum size of a pattern array.
                 MAXPATH   Maximum size of a Subsystem pathname.
                 MAXPRINT  Maximum  number of character that can be output by
                           a single call to 'print'.
                 MAXTREE   Maximum number of  characters  in  a  Primos  tree


                                         - 108 -                             




            Ratfor User's Guide                                              


                           name.
                 MAXFNAME  Maximum  number  of  characters  in  a simple file
                           name.


            SSStttaaannndddaaarrrddd PPPooorrrtttsss

                 STDIN     Standard input 1.
                 STDIN1    Standard input 1.
                 STDIN2    Standard input 2.
                 ERRIN     Standard input 3.
                 STDIN3    Standard input 3.
                 STDOUT    Standard output 1.
                 STDOUT1   Standard output 1.
                 STDOUT2   Standard output 2.
                 ERROUT    Standard output 3.
                 STDOUT3   Standard output 3.


            AAArrrggguuummmeeennnttt aaannnddd RRReeetttuuurrrnnn VVVaaallluuueeesss

                 ABS       Request absolute positioning ('seekf').
                 REL       Request relative positioning ('seekf').
                 DIGIT     Character is a digit ('type').
                 LETTER    Character is a letter ('type').
                 UPPER     Map to upper case ('mapstr').
                 LOWER     Map to lower case ('mapstr').
                 READ      Open file for reading.
                 WRITE     Open file for writing.
                 READWRITE Open file for reading and writing.
                 EOF       End of file (guaranteed distinct from all  charac-
                           ters and from OK and ERR).
                 OK        No  error (guaranteed distinct from all characters
                           and from EOF and ERR).
                 ERR       Error  occurred  (guaranteed  distinct  from   all
                           characters and from EOF and OK).
                 EOS       End   of  string  (guaranteed  distinct  from  all
                           characters).
                 LAMBDA    Null pointer (guaranteed distinct from all pointer
                           values).
          |      PG_END    Make 'page' return after the last page of input.
          |      PG_VTH    Make 'page' use the VTH routines when  writing  to
          |                the terminal.
                 YES       Affirmative  response  (guaranteed  distinct  from
                           NO).
                 NO        Negative response (guaranteed distinct from YES).












                                         - 109 -                             




            Ratfor User's Guide                                              


                            AAAppppppeeennndddiiixxx EEE ------ '''RRRppp''' RRReeessseeerrrvvveeeddd WWWooorrrdddsss


                 The following identifiers are reserved  keywords  in  Ratfor
            and  cannot  be  used as identifiers.  'Rp' will not diagnose the
            use of reserved keywords as identifiers; results of  misuse  will
            be  unreasonable  behavior  such as misleading error messages and
            mis-ordered Fortran code.

                      blockdata                    linkage
                      break                        local
                      call                         logical
                      case                         next
                      common                       parameter
                      complex                      procedure
                      continue                     real
                      data                         recursive
                      define                       repeat
                      dimension                    return
                      do                           save
                      doubleprecision              select
                      else                         shortcall
                      end                          stackheader
                      equivalence                  stmtfunc
                      external                     stop
                      for                          string
                      forward                      stringtable
                      function                     subroutine
                      goto                         trace
                      if                           undefine
                      ifany                        until
                      implicit                     when
                      include                      while
                      integer
























                                         - 110 -                             




            Ratfor User's Guide                                              


                            AAAppppppeeennndddiiixxx FFF ------ CCCooommmmmmaaannnddd LLLiiinnneee SSSyyynnntttaaaxxx


                 'Rp' provides a rich set of processing options to allow  the
            user  much  flexibility  and  control  over  the  code  which  is
            produced.  The command line syntax is as follows:

                 rp [-{a | b | c | d | f | g | h | l | m | p | s | t | v | y}]
                    [-o <output_file>] {<input_file>} [-x <translation file>]

                 The following is a full description of each option:

                 a    Abort all active shell  programs  if  any  errors  were
                      encountered   during  preprocessing.   This  option  is
                      useful in  shell  programs  like  'rfl'  that  wish  to
                      inhibit   compilation   and  loading  if  preprocessing
                      failed.  By default, this option is not selected;  that
                      is,  errors  in  preprocessing  do not terminate active
                      shell programs.

                 b    Do not map long indentifiers or identifiers  containing
                      upper  case  letters  into unique six character Fortran
                      identifiers.  This option is  useful  if  your  Fortran
                      compiler will accept names longer than six characters.

                 c    Include statement-count profiling code in the generated
                      Fortran.   When  this  option is selected, calls to the
                      library routines 'c$init', 'c$incr', and  'c$end'  will
                      be placed (unobtrusively) in the output code.  When the
                      preprocessed  program  is  run, it will generate a file
                      named "_st_count" containing execution frequencies  for
                      each   line   of  source  code.   The  utility  program
                      'st_profile' may then be used to  combine  source  code
                      and statement counts to form a readable report.

                 d    Inhibit   generation   of   the  long-name  dictionary.
                      Normally, a dictionary listing all long names  used  in
                      the  Ratfor  program  along with their equivalent short
                      forms is placed at the end of the generated Fortran  as
                      a  series  of comment statements.  This option prevents
                      its generation.

                 f    Suppress automatic inclusion  of  standard  definitions
                      file.   Macro  definitions  for  the manifest constants
                      used  throughout  the  Subsystem  reside  in  the  file
                      "=incl=/swt_def.r.i".     'Rp'   will   process   these
                      definitions automatically, unless the  "-f"  option  is
                      specified.

                 g    Make  a  second  pass over the code and remove GOTOs to
                      GOTOs generated in Ratfor control structures.   Use  of
                      this option lengthens preprocessing time significantly,
                      but  can  result  (sometimes)  in a 2-5% speedup of the
                      object program.

                 h    Produce Hollerith-format string constants  rather  than


                                         - 111 -                             




            Ratfor User's Guide                                              


                      quoted string constants.  This option useful in produc-
                      ing  character  strings  in the proper format needed by
                      your Fortran compiler.

                 l    Include Ratfor line  numbers  in  the  sequence  number
                      field  of  the  Fortran  output.  This may be useful in
                      tracking  down  the  Ratfor  statement  that  caused  a
                      Fortran syntax error.  By default, no sequence field is
                      generated.

                 m    Map all identifiers to lower case.  When this option is
                      selected,   'rp'   considers  the  upper  case  letters
                      equivalent to the  corresponding  lower  case  letters,
                      except inside quoted strings.

                 p    Emit  subroutine  profiling  code.  When this option is
                      selected, 'rp' places calls  to  the  library  routines
                      't$entr', 't$exit', and 't$clup' in the Fortran output,
                      and   creates  a  text  file  named  "timer_dictionary"
                      containing the names of all  subprograms  seen  by  the
                      preprocessor.  When the profiled program is run, a file
                      named   "_profile"  is  created  that  contains  timing
                      measurements for each subprogram.  The utility  program
                      'profile'  may then be used to print a report summariz-
                      ing the number of times each subprogram was called  and
                      the total time spent in each.

                 s    Short-circuit  all  logical  conditions.   The order of
                      evaluation  of   logical   operands   in   Fortran   is
                      unspecified;  that is, in the expression "a&b" there is
                      no guarantee that "a" will  be  evaluated  before  "b".
                      Occasionally  this  creates  inconveniences;  one would
                      like to say  something  like  "if(i>1&array(i)~=0)...".
                      'Rp'  supplies the short-circuit logical operators "&&"
                      and "||" (read "andif" and "orif") for these occasions.
                      Both operators evaluate their  left  operands;  if  the
                      value  of  the logical expression is predictable solely
                      on the basis of the value of the left operand, then the
                      right  operand  remains  unevaluated  and  the  correct
                      expression  value  is  yielded.   Otherwise  the  right
                      operand is evaluated and the proper expression value is
                      determined.   The  "-s"   option   may   be   used   to
                      automatically  convert all "logical and" operators in a
                      program to "andifs," and all "logical or" operators  to
                      "orifs."  In addition to improving program portability,
                      this   option  may  also  reduce  execution  time.   By
                      default, however, this option is not in effect.

                 t    Trace subprograms.  When a  program  preprocessed  with
                      the  "-t"  option is run, an indented trace of the sub-
                      programs encountered will be printed on  ERROUT.   This
                      trace  output  is  generated  by  calls  to the library
                      routine 't$trac' that  are  inserted  automatically  by
                      'rp'.

                 v    Output  "standard" Fortran.  This option causes 'rp' to


                                         - 112 -                             




            Ratfor User's Guide                                              


                      generate only standard Fortran constructs (as far as we
                      know).   This  option  does  not  detect   non-standard
                      Fortran  usage  in Ratfor source code; it only prevents
                      'rp'  from  generating   non-standard   constructs   in
                      implementing its data and control structures.  Programs
                      preprocessed  with  this option are slightly larger and
                      slower; the intermediate Fortran and binary  files  are
                      approximately 10% larger.

                 x    Translate  character  codes.   'Rp'  uses the character
                      correspondences in the  <translation file>  to  convert
                      characters  into  integers  when it builds Fortran DATA
                      statements containing EOS-terminated or  PL/I  strings.
                      If  the  option  is  not  specified,  'rp' converts the
                      characters using the native Prime character  set.   The
                      format of the translation file is documented below.

                 y    Do  not output "call swt".  This option keeps 'rp' from
                      generating  "call  swt"  in   place   of   all   "stop"
                      statements.

                 The  remainder  of  the  command line is used to specify the
            names of the Ratfor input file(s) and the  Fortran  output  file.
            If the "-o" option, followed by a filename, is selected, then the
            named  file  is used for Fortran output.  Any remaining filenames
            are considered Ratfor source files.  If no other file  names  are
            specified,  standard  input  is  read.  If the "-o" option is not
            specified, then the output filename is constructed from the first
            input filename by changing a ".r" suffix (if  present)  to  ".f".
            If  the  ".r"  suffix  is not present, the output filename is the
            input filename followed by the suffix ".f".

                 The format of the translation file used with the "-x" option
            is as follows.  Each line contains descriptions  of  two  charac-
            ters:  the Prime native character to be replaced, and the charac-
            ter  value  to  replace it.  These descriptions may be any one of
            the following:  a single non-blank Prime ASCII character, a  num-
            ber  in  a  format  acceptable  to 'gctoi' (must be more than one
            digit), or an ASCII mnemonic acceptable to 'mntoc'.  In addition,
            the character to be replaced may also be the  mnemonic  "EOS"  to
            indicate  that  the value of the end-of-string indicator is to be
            changed.  For example, here is a portion of the  table  for  con-
            verting the EBCDIC character set:

                 A 16rc1
                 B 16rc2
                 ...
                 Z 16re9
                 0 16rf0
                 ...
                 9 16rf9
                 SP 16r40






                                         - 113 -                             




            


          |                         ___TTT___AAA___BBB___LLL___EEE___ ___OOO___FFF___ ___CCC___OOO___NNN___TTT___EEE___NNN___TTT___SSS




                                  ___RRR___aaa___ttt___fff___ooo___rrr___ ___LLL___aaa___nnn___ggg___uuu___aaa___ggg___eee___ ___GGG___uuu___iii___ddd___eee



            WWWhhhaaattt iiisss RRRaaatttfffooorrr??? ..........................................   1

            DDDiiiffffffeeerrreeennnccceeesss BBBeeetttwwweeeeeennn RRRaaatttfffooorrr aaannnddd FFFooorrrtttrrraaannn ...................   1
               Source Program Format .................................   1
                  Case Sensitivity ...................................   1
                  Blank Sensitivity ..................................   2
                  Card Columns .......................................   2
                  Multiple Statements per Line .......................   2
                  Statement Labels and Continuation ..................   3
                  Comments ...........................................   4
               Identifiers ...........................................   5
               Integer Constants .....................................   6
               String Constants ......................................   7
               Logical and Relational Operators ......................   9
               Assignment Operators ..................................  10
               Fortran Statements in Ratfor Programs .................  11
               Incompatibilities .....................................  12

            RRRaaatttfffooorrr TTTeeexxxttt SSSuuubbbssstttiiitttuuutttiiiooonnn SSStttaaattteeemmmeeennntttsss ......................  13
               Define ................................................  13
               Undefine ..............................................  16
               Include ...............................................  17

            RRRaaatttfffooorrr DDDeeeccclllaaarrraaatttiiiooonnnsss ......................................  18
               String ................................................  18
               Stringtable ...........................................  18
               Linkage ...............................................  20
               Local .................................................  20

            RRRaaatttfffooorrr CCCooonnntttrrrooolll SSStttaaattteeemmmeeennntttsss ................................  22
               Compound Statements ...................................  22
               If - Else .............................................  22
               While .................................................  23
               Repeat ................................................  23
               Do ....................................................  24
               For ...................................................  25
               Break .................................................  26
               Next ..................................................  26
               Return ................................................  27
               Select ................................................  28
               Procedure .............................................  30








                                         - iii -                             




            


                                ___RRR___aaa___ttt___fff___ooo___rrr___ ___LLL___aaa___nnn___ggg___uuu___aaa___ggg___eee___ ___RRR___eee___fff___eee___rrr___eee___nnn___ccc___eee



            DDDiiiffffffeeerrreeennnccceeesss BBBeeetttwwweeeeeennn RRRaaatttfffooorrr aaannnddd FFFooorrrtttrrraaannn ...................  33
               Source Program Format .................................  33
               Identifiers ...........................................  33
               Integer Constants .....................................  34
               String Constants ......................................  34
               Logical and Relational Operators ......................  34
               Assignment Operators ..................................  35
               Escape Statements .....................................  35
               Incompatibilities .....................................  36

            RRRaaatttfffooorrr TTTeeexxxttt SSSuuubbbssstttiiitttuuutttiiiooonnn SSStttaaattteeemmmeeennntttsss ......................  37
               Define ................................................  37
               Undefine ..............................................  37
               Include ...............................................  37

            RRRaaatttfffooorrr DDDeeeccclllaaarrraaatttiiiooonnnsss ......................................  38
               Linkage ...............................................  38
               Local .................................................  38
               String ................................................  38
               Stringtable ...........................................  38

            RRRaaatttfffooorrr CCCooonnntttrrrooolll SSStttaaattteeemmmeeennntttsss ................................  39
               Break .................................................  39
               Do ....................................................  39
               For ...................................................  39
               If ....................................................  39
               Next ..................................................  39
               Procedure .............................................  40
               Repeat ................................................  40
               Return ................................................  40
               Select ................................................  40
               While .................................................  41




                         ___RRR___aaa___ttt___fff___ooo___rrr___ ___PPP___rrr___ooo___ggg___rrr___aaa___mmm___mmm___iii___nnn___ggg___ ___UUU___nnn___ddd___eee___rrr___ ___ttt___hhh___eee___ ___SSS___uuu___bbb___sss___yyy___sss___ttt___eee___mmm



            RRReeeqqquuuiiirrreeemmmeeennntttsss fffooorrr RRRaaatttfffooorrr PPPrrrooogggrrraaammmsss .........................  42

            RRRuuunnnnnniiinnnggg RRRaaatttfffooorrr PPPrrrooogggrrraaammmsss UUUnnndddeeerrr ttthhheee SSSuuubbbsssyyysssttteeemmm ..............  43
               Preprocessing .........................................  43
               Compiling .............................................  44
               Linking ...............................................  46
               Executing .............................................  48
               Shortcuts .............................................  48
                  Shell Programs .....................................  48
                  The 'Rfl' Command ..................................  49
                  Storing Source Programs Separately .................  49
                  Compiling Programs Separately ......................  49


                                         - iv -                              




            


               Debugging .............................................  51
               Performance Monitoring ................................  55
               Conditional Compilation ...............................  56
               Portability ...........................................  56

            SSSooouuurrrccceee PPPrrrooogggrrraaammm FFFooorrrmmmaaattt CCCooonnnvvveeennntttiiiooonnnsss ........................  57
               Statement Placement ...................................  57
               Indentation ...........................................  58
               Subsystem Definitions .................................  59

            UUUsssiiinnnggg ttthhheee SSSuuubbbsssyyysssttteeemmm SSSuuuppppppooorrrttt RRRooouuutttiiinnneeesss .....................  60
               Termination ...........................................  60
               Character Strings .....................................  60
                  Equal ..............................................  61
                  Index ..............................................  61
                  Length .............................................  62
                  Mapdn and Mapup ....................................  62
                  Mapstr .............................................  62
                  Scopy ..............................................  63
                  Type ...............................................  63
               File Access ...........................................  63
                  Open and Close .....................................  64
                  Create .............................................  65
                  Mktemp and Rmtemp ..................................  65
                  Wind and Rewind ....................................  65
                  Trunc ..............................................  66
                  Remove .............................................  66
                  Cant ...............................................  66
                  Getlin .............................................  66
                  Getch ..............................................  67
                  Input ..............................................  67
                  Readf ..............................................  69
                  Putlin .............................................  70
                  Putch ..............................................  70
                  Print ..............................................  70
                  Writef .............................................  71
                  Fcopy ..............................................  71
                  Markf and Seekf ....................................  71
                  Getto ..............................................  72
               Type Conversion .......................................  73
                  Decode .............................................  75
                  Encode .............................................  76
               Argument Access .......................................  76
                  Getarg .............................................  76
                  Parscl .............................................  76
               Dynamic Storage Management ............................  79
                  Dsinit .............................................  80
                  Dsget ..............................................  80
                  Dsfree .............................................  80
                  Dsdump .............................................  80
               Symbol Table Manipulation .............................  82
                  Mktabl .............................................  83
                  Enter ..............................................  83
                  Lookup .............................................  83
                  Delete .............................................  84
                  Rmtabl .............................................  84


                                          - v -                              




            


                  Sctabl .............................................  84
               Other Routines ........................................  85




                                       ___AAA___ppp___ppp___eee___nnn___ddd___iii___xxx___eee___sss



            AAAppppppeeennndddiiixxx AAA ------ IIImmmpppllleeemmmeeennntttaaatttiiiooonnn ooofff CCCooonnntttrrrooolll SSStttaaattteeemmmeeennntttsss .......  87
               Break .................................................  88
               Do ....................................................  89
               For ...................................................  90
               If ....................................................  92
               If - Else .............................................  93
               Next ..................................................  94
               Repeat ................................................  95
               Return ................................................  96
               Select ................................................  97
               Select (<integer expression>) ......................... 100
               While ................................................. 103

            AAAppppppeeennndddiiixxx BBB ------ LLLiiinnnkkkiiinnnggg PPPrrrooogggrrraaammmsss WWWiiittthhh IIInnniiitttiiiaaallliiizzzeeeddd CCCooommmmmmooonnn ... 104

            AAAppppppeeennndddiiixxx CCC ------ RRReeeqqquuuiiirrreeemmmeeennntttsss fffooorrr SSSuuubbbsssyyysssttteeemmm PPPrrrooogggrrraaammmsss ........ 105

            AAAppppppeeennndddiiixxx DDD ------ TTThhheee SSSuuubbbsssyyysssttteeemmm DDDeeefffiiinnniiitttiiiooonnnsss .................. 107
               Characters ............................................ 107
               Data Types ............................................ 107
               Macro Subroutines ..................................... 107
               Language Extensions ................................... 108
               Limits ................................................ 108
               Standard Ports ........................................ 109
               Argument and Return Values ............................ 109

            AAAppppppeeennndddiiixxx EEE ------ '''RRRppp''' RRReeessseeerrrvvveeeddd WWWooorrrdddsss ........................ 110

            AAAppppppeeennndddiiixxx FFF ------ CCCooommmmmmaaannnddd LLLiiinnneee SSSyyynnntttaaaxxx ........................ 111



















                                         - vi -                              


