#-h- ed             43879  asc  22-jul-83 12:29:00  sventek (joseph sventek)


Ed (4)                        28-Oct-80                         Ed (4)


NAME
     Ed - text editor


         A Tutorial Introduction to the Software Tools TEXT EDITOR


                               B. Kernighan
                             Bell Laboratories

                                    and

                                M.J. Gralia
           Johns Hopkins University - Applied Physics Laboratory



     
INTRODUCTION
     EEEddd  is  a  "text  editor",  that  is,  an interactive program for
     creating and modifying "text", using  directions  provided  by  a
     user  at a terminal.  The text is often a document like this one,
     or a program or perhaps data for a program. 

     This  introduction  is  meant  to  simplify  learning  eeeddd...    The
     recommended   way   to   learn  eeeddd  is  to  read  this  document,
     simultaneously using eeeddd to follow the examples, then to read  the
     description  in  section  I of the Software Tools manual, all the
     while  experimenting  with  eeeddd...   (Solicitation  of  advice  from
     experienced users is also useful.)

     Do  the  exercises!  They cover material not completely discussed
     in the actual text.  An appendix summarizes the commands. 
     
DISCLAIMER
     This is an introduction and a  tutorial.   For  this  reason,  no
     attempt  is made to cover more than a part of the facilities that
     eeeddd offers (although this fraction includes the  most  useful  and
     frequently  used  parts).   Also,  there  is  not enough space to
     explain basic Software Tools procedures.   We  will  assume  that
     you  know  how  to log on and access the Software Tools, and that
     you have at least a vague understanding of what a file is. 

     You must also know what character to type as the  end-of-line  on
     your  particular  terminal.   It  is  almost  always  a "return".
     Throughout, we will refer to this character, whatever it  is,  as
     "newline". 
     
CASES
     And  about  case:   it is traditional to use both upper and lower


                                 -1-


Ed (4)                        28-Oct-80                         Ed (4)


     case characters when using the Software  Tools,  but  it  is  not
     required.   In describing eeeddd,,, we will follow that convention, but
     eeeddd will work with either. 

     But a caution: eeeddd differentiates cases.  If  your  files  contain
     both  and  your  terminal  is  in  upper case, you can get into a
     "deadly embrace" situation in which you can see a  character  but
     can't  delete it.  The solution is simple - always use both upper
     and lower case with Software Tools. 
     
GETTING STARTED
     We'll assume that you have logged in.  The easiest way to get  eeeddd
     is to type

           ed      (followed by a newline)

     You  are  now ready to go - eeeddd is waiting for you to tell it what
     to do. 
     
CREATING TEXT - the Append command ``a''
     As our first  problem,  suppose  we  want  to  create  some  text
     starting  from  scratch.   Perhaps  we  are typing the very first
     draft of a paper; clearly it will have to  start  somewhere,  and
     undergo  modifications  later.  This section will show how to get
     some text in, just to get started.  Later we'll  talk  about  how
     to change it. 

     When  eeeddd is first started, it is rather like working with a blank
     piece of paper - there is no text or information  present.   This
     must  be  supplied  by the person using eeeddd;;; it is usually done by
     typing in the text, or by reading it into eeeddd  from  a  file.   We
     will  start  by typing in some text, and return shortly to how to
     read files. 

     First a bit of terminology.  In eeeddd jargon, the text being  marked
     on  is  said  to be "kept in a buffer."  Think of the buffer as a
     work space, if you like, or simply as the  information  that  you
     are  going to be editing.  In effect the buffer is like the piece
     of paper on which we will  write  things,  then  change  some  of
     them, and finally file the whole thing away for another day. 

     The  user  tells eeeddd what to do to his text by typing instructions
     called "commands".  Most commands consist  of  a  single  letter.
     Each  command  is  typed  on  a  separate  line.   (Sometimes the
     command is preceded by information about what line  or  lines  of
     text are to be affected - we will discuss these shortly.)

     The first command is aaappppppeeennnddd,,, written as the letter

           a


                                 -2-


Ed (4)                        28-Oct-80                         Ed (4)


     all  by  itself.   It  means  """aaappppppeeennnddd  (or add) text lines to the
     buffer, as I type them in."  Appending  is  rather  like  writing
     fresh material on a piece of paper. 

     So  to  enter  lines of text into the buffer, we just type an "a"
     followed by a newline, followed by the lines  of  text  we  want,
     like this:

           a
           Now is the time
           for all good men
           to come to the aid of their party.
           .

     The  only  way  to stop appending is to type a line that contains
     only a period.  The "." is used to tell eeeddd that we have  finished
     appending.   (Even  experienced users forget that terminating "."
     sometimes.  If eeeddd seems to be ignoring you, type  an  extra  line
     with  just  "."  on  it.   You  may  then  find you've added some
     garbage lines to  your  text,  which  you'll  have  to  take  out
     later.)

     After  the  append command has been done, the buffer will contain
     the three lines

           Now is the time
           for all good men
           to come to the aid of their party.

     The "a" and "." aren't there, because they are not text. 

     To add more text to what we already have, just issue another  "a"
     command,  and  continue  typing.   (Try  it now - it won't always
     work right until we explain about line numbers.)
     
ERROR MESSAGES - ``?''
     If at any time you make an error in the commands you type to  eeeddd,,,
     it will tell you by typing

           ?

     This  is  about  as  cryptic as it can be, but with practice, you
     can usually figure out how you goofed. 
     
WRITING TEXT OUT AS A FILE - the Write command ``w''
     It's likely that we'll want to save our text for later  use.   To
     write  out  the  contents  of  the buffer onto a file, we use the
     wwwrrriiittteee command

           w


                                 -3-


Ed (4)                        28-Oct-80                         Ed (4)


     followed by the filename we want to write  on.   This  will  copy
     the  buffer's  contents  onto  the specified file (destroying any
     previous information on the file).  To save the text  on  a  file
     named "junk", for example, type

           w junk

     Leave  a space between "w" and the file name.  EEEddd will respond by
     printing the number of lines it  wrote  out.   In  our  case,  eeeddd
     would respond with

           3

     Writing  a  file  just  makes  a  copy of the text - the buffer's
     contents are not disturbed, so we can go on adding lines  to  it.
     This  is  an important point.  EEEddd at all times works on a copy of
     a file, not the file itself.  No change  in  the  contents  of  a
     file  takes place until you give a "w" command.  (Writing out the
     text onto a file from time to time as it is being  created  is  a
     good  idea,  since  if  the  system  crashes  or if you make some
     horrible mistake, you will lose all the text in the  buffer,  but
     any text that was written  onto a file is relatively safe.)
     
LEAVING ED - the Quit command ``q''
     To  terminate  a session with eeeddd,,, save the text you're working on
     by writing it onto a file using the "w" command,  and  then  type
     the command

           q

     which  stands for qqquuuiiittt...  At this point your buffer vanishes, with
     all its text, which is why  you  want  to  write  it  out  before
     quitting. 
     
EXERCISE 1:
     Enter eeeddd and create some text using

           a
           ...text...
           .

     Write  it out using "w".  Then leave eeeddd with the "q" command, and
     print the file, to see  that  everything  worked.   (To  print  a
     file, say

           cat filename

     Also try

           crt filename


                                 -4-


Ed (4)                        28-Oct-80                         Ed (4)


     Here,  you  need to enter a newline (to see the next page) or "q"
     (to quit displaying the text). 
     
READING TEXT FROM A FILE - the Edit command ``e''
     A common way to get text into the buffer is to  read  it  from  a
     file  in  the file system.  This is what you do to edit text that
     you saved with the "w" command in a previous session.   The  eeedddiiittt
     command  "e"  fetches  the  entire  contents  of  a file into the
     buffer.  So if we had saved the three lines "Now  is  the  time",
     etc., with a "w" command in an earlier session, the eeeddd command

           e junk

     would  fetch  the  entire  contents  of  the file "junk" into the
     buffer, and respond

           3

     which is the number of lines in "junk".  If anything was  already
     in the buffer, it is deleted first. 

     If  we  use  the "e" command to read a file into the buffer, then
     we need not use a file name after a subsequent  "w"  command;  eeeddd
     remembers  the  last  file  name  used in an "e" command, and "w"
     will write on this file.  Thus a common way to operate is

           ed
           e file
           [editing session]
           w
           q

     You can find out at any time what file named  eeeddd  is  remembering
     by typing the fffiiillleee command "f".  In our case, if we typed

           f

     eeeddd would reply

           junk
     
READING TEXT FROM A FILE - the Read command ``r''
     Sometimes  we  want  to  read  a  file  into  the  buffer without
     destroying anything that is already there.  This is done  by  the
     rrreeeaaaddd command "r".  The command

           r junk

     will  read  the  file  "junk"  into the buffer; it adds it to the
     buffer (after the current line).  So if we do  a  read  after  an


                                 -5-


Ed (4)                        28-Oct-80                         Ed (4)


     edit:

           e junk
           r junk

     the buffer will contain tttwwwooo copies of the text (six lines). 

           Now is the time
           for all good men
           to come to the aid of their party.
           Now is the time
           for all good men
           to come to the aid of their party.

     Like  the "w" and "e" commands, "r" prints the number of newlines
     read in, after the reading operation is complete. 

     Generally speaking, "r" is much less used than "e". 
     
EXERCISE 2:
     Experiment with the  "e"  command  -  try  reading  and  printing
     various  files.  You may get an error "?.", typically because you
     spelled  the  file  name  wrong.   Try  alternately  reading  and
     appending to see that they work similarly.  Verify that

           ed filename

     is exactly equivalent to

           ed
           e filename

     What does

           f filename

     do?
     
PRINTING THE CONTENTS OF THE BUFFER - the Print command ``p''
     To  ppprrriiinnnttt  or list the contents of the buffer (or parts of it) on
     the terminal, we use the print command

           p

     The way this is done is as follows.  We specify the  lines  where
     we  want printing to begin and where we want it to end, separated
     by a comma, and followed by the letter "p".  Thus  to  print  the
     first  two  lines  of  the buffer, for example, (that is, lines 1
     through 2) we say



                                 -6-


Ed (4)                        28-Oct-80                         Ed (4)


           1,2p (starting line=1, ending line=2)

     EEEddd will respond with

           Now is the time
           for all good men

     Suppose we want to print aaallllll the lines in the buffer.   We  could
     use  "1,3p" as above if we knew there were exactly 3 lines in the
     buffer.  But in general, we don't know  how  many  there  are  so
     what  do  we  use  for  the  ending  line  number?  EEEddd provides a
     shorthand symbol for "line number of last line in buffer"  -  the
     dollar sign "$".  Use it this way:

           1,$p

     This  will  print aaallllll the lines in the buffer (line 1 to the last
     line.)

     To print the lllaaasssttt line of the buffer, we could use

           $,$p

     but eeeddd lets us abbreviate this to

           $p

     We can print any single line by typing the line  number  followed
     by a "p".  Thus

           1p

     produces the response

           Now is the time

     which is the first line of the buffer. 

     In  fact,  eeeddd  lets us abbreviate even further:  we can print any
     single line by typing jjjuuusssttt the line number - no need to type  the
     letter "p".  So if we say

           $

     eeeddd will print the last line of the buffer for us. 

     We can also use "$" in combinations like

           $-1,$p



                                 -7-


Ed (4)                        28-Oct-80                         Ed (4)


     which  prints  the last two lines of the buffer.  This helps when
     we want to see how far we got in typing. 
     
EXERCISE 3:
     As  before,  create  some  text  using  the  append  command  and
     experiment  with  the  "p"  command.  You will find, for example,
     that you can't print line 0 or a  line  beyond  the  end  of  the
     buffer,  and  that attempts to print a buffer in reverse order by
     saying

           3,1p

     don't work. 
     
THE CURRENT LINE - 'Dot' or '.'
     Suppose our buffer still contains the six lines  as  above,  that
     we have just typed

           1,3p

     and eeeddd has printed the three lines for us.  Try typing just

           p     (no line numbers).

     This will print

           to come to the aid of their party. 

     which  is  the  third line of the buffer.  In fact it is the last
     (most recent) line that we have done  anything  with.   (We  just
     printed  it!)   We  can  repeat  this  "p"  command  without line
     numbers, and it will continue to print line 3. 

     The reason is that eeeddd maintains a record of the  last  line  that
     we  did anything to (in this case, line 3, which we just printed)
     so that it can be used instead of an explicit line number.   This
     most recent line is referred to by the shorthand symbol

           .     (pronounced "dot"). 

     Dot  is  a  line  number  in  the  same way that "$" is; it means
     exactly "the  current  line",  or  loosely,  "the  line  we  most
     recently  did  something to." We can use it in several ways - one
     possibility is to say

           .,$p

     This will print all the lines from (including) the  current  line
     to  the end of the buffer.  In our case these are lines 3 through
     6. 


                                 -8-


Ed (4)                        28-Oct-80                         Ed (4)


     Some commands change the value of dot, while others do not.   The
     print  command  sets  dot to the number of the last line printed;
     by our last command, we would have "." = "$" = 6. 

     Dot is most useful when used in combinations like this one:

           .+1     (or equivalently, .+1p)

     This means "print the next line" and gives  us  a  handy  way  to
     step slowly through a buffer.  We can also say

           .-1     (or .-1p)

     which  means  "print  the  line  bbbeeefffooorrreee  the  current line." This
     enables us to go backwards if we wish.   Another  useful  one  is
     something like

           .-3,.-1p

     which prints the previous three lines. 

     Don't  forget that all of these change the value of dot.  You can
     find out what dot is at any time by typing

           .=

     EEEddd will respond by printing the value of dot. 

     Let's summarize some  things  about  the  "p"  command  and  dot.
     Essentially  "p"  can be preceded by 0, 1, or 2 line numbers.  If
     there is no line number given, it prints the "current line",  the
     line  that  dot  refers  to.   If  there is one line number given
     (with or without the letter "p"), it prints that  line  (and  dot
     is  set  there); and if there are two line numbers, it prints all
     the lines in that range (and sets dot to the last line  printed.)
     If  two line numbers are specified the first can't be bigger than
     the second (see Exercise 3.)

     Typing a single newline will cause printing of the  next  line  -
     it's equivalent to ".+1p".  Try it. 
     
DELETING LINES: the ``d'' command
     Suppose  we  want  to  get  rid  of  the three extra lines in the
     buffer.  This is done by the dddeeellleeettteee command

           d

     Except that "d" deletes  lines  instead  of  printing  them,  its
     action  is  similar  to that of "p".  The lines to be deleted are
     specified for "d" exactly as they are for "p":


                                 -9-


Ed (4)                        28-Oct-80                         Ed (4)


           starting-line, ending-line d

     Thus the command

           4,$d

     deletes lines 4 through the  end.   There  are  now  three  lines
     left, as we can check by using

           1,$p

     And  notice  that "$" now is line 3!  Dot is set to the next line
     after the last line deleted, unless the last line deleted is  the
     last line in the buffer.  In that case, dot is set to "$". 
     
EXERCISE 4:
     Experiment  with  "a",  "e", "r", "w", "p", and "d" until you are
     sure that you know what they do, and  until  you  understand  how
     dot, "$", and line numbers are used. 

     If  you  are  adventurous,  try using line numbers with "a", "r",
     and "w" as well.  You will find that "a" will append lines  aaafffttteeerrr
     the  line  number  that you specify (rather than after dot); that
     "r" reads a file in  aaafffttteeerrr  the  line  number  you  specify  (not
     necessarily  at  the  end of the buffer); and that "w" will write
     out exactly the lines you  specify,  not  necessarily  the  whole
     buffer.   These variations are sometimes handy.  For instance you
     can insert a file at the beginning of a buffer by saying

           0r filename

     and you can enter lines at the beginning of the buffer by saying

           0a
           ...text...
           .

     Notice that ".w" is vvveeerrryyy different from

           .
           w

     
MODIFYING TEXT: the Substitute command ``s''
     We are now ready  to  try  one  of  the  most  important  of  all
     commands - the substitute command

           s

     This  is  the  command that is used to change individual words or


                                 -10-


Ed (4)                        28-Oct-80                         Ed (4)


     letters within a line or group of lines.  It is what we use,  for
     example, for correcting spelling mistakes and typing errors. 

     Suppose that by a typing error, line 1 says

           Now is th time

     -  the  "e"  has been left off "the".  We can use "s" to fix this
     up as follows:

           1s/th/the/

     This says:  "in line 1, substitute for the  characters  `th'  the
     characters  `the'.   To  verify that it works ( eeeddd will not print
     the result automatically) we say

           p

     and get

           Now is the time

     which is what we wanted.  Notice that dot must have been  set  to
     the  line  where  the  substitution  took  place,  since  the "p"
     command printed that line.  Dot is always set this way  with  the
     "s" command. 

     The general way to use the substitute command is

           starting-line, ending-line s/change this/to this/

     Whatever  string  of  characters  is  between  the  first pair of
     slashes is replaced by whatever is between the  second  pair,  in
     aaallllll  the  lines  between starting line and ending line.  Only the
     first occurrence on each line is changed, however.  If  you  want
     to  change  eeevvveeerrryyy occurrence, see Exercise 5.  The rules for line
     numbers are the same as those for "p", except that dot is set  to
     the  last  line changed. (But there is a trap for the unwary:  if
     no substitution took place, dot is nnnooottt changed.  This  causes  an
     error "?" as a warning.)

     Thus we can say

           1,$s/speling/spelling/

     and  correct  the  first  spelling  mistake  on  each line in the
     text.   (This  is  useful   for   people   who   are   consistent
     misspellers!)

     If  no  line  numbers  are given, the "s" command assumes we mean


                                 -11-


Ed (4)                        28-Oct-80                         Ed (4)


     "make the substitution on line dot", so it  changes  things  only
     on the current line.  This leads to the very common sequence

           s/something/something else/p

     which  makes some correction on the current line, and then prints
     it, to make sure it worked out right.  If it didn't, we  can  try
     again.   (Notice  that we put a print command on the same line as
     the  substitute.   With  few  exceptions,  "p"  can  follow   any
     command; no other multi-command lines are legal.)

     It's also legal to say

           s/something//

     which  means  "change  'something'  to nnnooottthhhiiinnnggg,,,""" i.e., remove it.
     This is useful for deleting extra words in  a  line  or  removing
     extra letters from words.  For instance, if we had

           Nowxx is the time

     we can say

           s/xx//p

     to get

           Now is the time

     Notice  that "//" here means "no characters", not a blank.  There
     iiisss a difference!  (See below for another meaning of "//".)
     
EXERCISE 5:
     Experiment with the substitute command.  See what happens if  you
     substitute  for  some  word on a line with several occurrences of
     that word.  For example, do this:

           a
           the other side of the coin
           .
           s/the/on the/p

     You will get

           on the other side of the coin

     A substitute command changes only the  first  occurrence  of  the
     first  string.   You  can  change all occurrences by adding a "g"
     (for "global") to the "s" command, like this:



                                 -12-


Ed (4)                        28-Oct-80                         Ed (4)


           s/.../.../gp

     Try other characters instead of slashes to delimit the  two  sets
     of  characters  in  the "s" command - anything should work except
     blanks or tabs. 

     (If you get funny results using any of the characters

           %  ?  $  [  *

     read the section on "Special Characters".)
     
CONTEXT SEARCHING - ``/.../''
     With the substitute command mastered, we can move on  to  another
     highly important idea of eeeddd - context searching. 

     Suppose we have our original three line text in the buffer:

           Now is the time
           for all good men
           to come to the aid of their party.

     Suppose  we want to find the line that contains "their" so we can
     change it to "the". Now with only  three  lines  in  the  buffer,
     it's  pretty  easy to keep track of what line the word "their" is
     on.  But if the buffer contained several hundred lines, and  we'd
     been  making  changes, deleting and rearranging lines, and so on,
     we would no longer really know what this line  number  would  be.
     Context  searching  is  simply a method of specifying the desired
     line, regardless of  what  its  number  is,  by  specifying  some
     context on it. 

     The  way  we say "search for a line that contains this particular
     string of characters" is to type

           /string of characters we want to find/

     For example, the eeeddd line

           /their/

     is a context search which is sufficient to find the desired  line
     -  it  will  locate the next occurrence of the characters between
     slashes ("their").  It also sets dot to that line and prints  the
     line for verification:

           to come to the aid of their party. 

     "Next  occurrence" means that eeeddd starts looking for the string at
     line ".+1", searches to the end of the buffer, then continues  at


                                 -13-


Ed (4)                        28-Oct-80                         Ed (4)


     line  1  and  searches  to line dot.  (That is, the search "wraps
     around" from "$" to 1.)  It scans all the  lines  in  the  buffer
     until  it  either  finds  the  desired  line  or gets back to dot
     again.  If the given string of characters can't be found  in  any
     line, eeeddd types the error message

           ?

     Otherwise it prints the line it found. 

     We   can   do  both  the  search  for  the  desired  line  aaannnddd  a
     substitution all at once, like this:

           /their/s/their/the/p

     which will yield

           to come to the aid of the party. 

     There were three parts to that last command:  context search  for
     the desired line, make the substitution, print the line. 

     The  expression  "/their/"  is  a  context search expression.  In
     their simplest form, all  context  search  expressions  are  like
     this  -  a  string  of characters surrounded by slashes.  Context
     searches are interchangeable with line numbers, so  they  can  be
     used  by  themselves to find and print a desired line, or as line
     numbers for some other command, like  "s".   We  used  them  both
     ways in the examples above. 

     Suppose the buffer contains the three familiar lines

           Now is the time
           for all good men
           to come to the aid of their party.

     Then the eeeddd line numbers

           /Now/+1
           /good/
           /party/-1

     are  all  context  search  expressions, and they all refer to the
     same line (line 2).  To make a change in line 2, we could say

           /Now/+1s/good/bad/

     or

           /good/s/good/bad/


                                 -14-


Ed (4)                        28-Oct-80                         Ed (4)


     or

           /party/-1s/good/bad/

     The choice is dictated only by convenience.  We could  print  all
     three lines by, for instance

           /Now/,/party/p

     or

           /Now/,/Now/+2p

     or  by  any  number  of  similar  combinations.  The first one of
     these might be better  if  we  don't  know  how  many  lines  are
     involved.   (Of  course,  if  there  were only three lines in the
     buffer, we could use

           1,$p

     but not if there were several hundred.)

     The basic rule is:  a context search expression is ttthhheee same as  a
     line  number,  so  it  can  be  used  wherever  a  line number is
     needed. 
     
EXERCISE 6:
     Experiment with context searching.   Try  a  body  of  text  with
     several  occurrences  of  the same string of characters, and scan
     through it using the same context search. 

     Try using context searches as line numbers  for  the  substitute,
     print  and  delete  commands.   (They  can also be used with "r",
     "w", and "a".)

     Try context searching using "\text\" instead of  "/text/".   This
     scans  lines  in  the buffer in reverse order rather than normal.
     This is sometimes useful if you go  too  far  while  looking  for
     some string of characters - it's an easy way to back up. 

     (If you get funny results with any of the characters

           %  ?  $  [  *

     read the section on "Special Characters".)

     EEEddd  provides  a  shorthand for repeating a context search for the
     same string.  For example, the eeeddd line number

           /string/


                                 -15-


Ed (4)                        28-Oct-80                         Ed (4)


     will find the next occurrence  of  "string".   It  often  happens
     that  this  is  not  the  desired  line,  so  the  search must be
     repeated.  This can be done by typing merely

           //

     This shorthand stands for "the most recently used context  search
     expression."   It  can  also  be  used as the first string of the
     substitute command, as in

           /string1/s//string2/

     which will find the next occurrence of "string1" and  replace  it
     by "string2".  This can save a lot of typing.  Similarly

           \\

     means "scan backwards for the same expression."
     
CHANGE and INSERT - ``c'' and ``i''
     This section discusses the ccchhhaaannngggeee command

           c

     which  is used to change or replace a group of one or more lines,
     and the iiinnnssseeerrrttt command

           i

     which is used for inserting a group of one or more lines. 

     "Change", written as

           c

     is used to replace a number of lines with different lines,  which
     are  typed  in  at  the  terminal.   For example, to change lines
     ".+1" through "$" to something else, type

           .+1,$c
           ...type the lines of text you want here...
           .

     The lines you type between the "c" command and the "." will  take
     the  place  of  the  original  lines  between  start line and end
     line.  This is most useful in replacing a line or  several  lines
     which have errors in them. 

     If  only one line is specified in the "c" command, then just that
     line is replaced.  (You can type in as many replacement lines  as


                                 -16-


Ed (4)                        28-Oct-80                         Ed (4)


     you  like.)   Notice the use of "." to end the input - this works
     just like the "." in  the  append  command  and  must  appear  by
     itself  on  a  new line.  If no line number is given, line dot is
     replaced.  The value of dot is set to the  last  line  you  typed
     in. 

     "Insert" is similar to append - for instance

           /string/i
           ...type the lines to be inserted here...
           .

     will  insert  the  given  text bbbeeefffooorrreee the next line that contains
     "string".  The text between "i" and "." is  iiinnnssseeerrrttteeeddd  before  the
     specified  line.   If  no  line  number is specified dot is used.
     Dot is set to the last line inserted. 
     
EXERCISE 7:
     "Change" is rather like  a  combination  of  delete  followed  by
     insert.  Experiment to verify that

           start, end d
           i
           ...text...
           .

     is almost the same as

           start, end c
           ...text...
           .

     These  are  not  ppprrreeeccciiissseeelllyyy  the  same  if  line "$" gets deleted.
     Check this out.  What is dot?

     Experiment with "a" and "i", to see that they  are  similar,  but
     not the same.  You will observe that

           line-number a
           ...text..
           .

     appends aaafffttteeerrr the given line, while

           line-number i
           ...text...
           .

     inserts  bbbeeefffooorrreee it.  Observe that if no line number is given, "i"
     inserts before line dot, while "a" appends after line dot. 


                                 -17-


Ed (4)                        28-Oct-80                         Ed (4)


     
BROWSING: the ``b'' command
     Many times you want to look at several  lines  of  a  large  file
     while you're using a video terminal.  If you said

           1,$p

     the  whole  buffer would flash on the screen, usually too fast to
     read.  A better way is the browse command "b".   It  prints  just
     enough  lines  (23)  to  fill  the  CRT screen.  Browse has three
     major forms which control what lines are displayed.  "b" or  "b+"
     prints  the  current  line  and the screen after it.  "b." prints
     the screen centered on the current line and including  it.   "b-"
     prints the screenful before the current line. 
     
MOVING TEXT AROUND: the ``m'' command
     The  move  command  "m" is used for cutting and pasting - it lets
     you move a group of lines  from  one  place  to  another  on  the
     buffer.   Suppose  we  want  to  put the first three lines of the
     buffer at the end instead.  We could do it by saying:

           1,3w temp
           $r temp
           1,3d

     (Do you see why?) but we can do it a  lot  easier  with  the  "m"
     command:

           1,3m$

     The general case is

           start-line, end-line m after-this-line

     Notice  that  there  is  a third line to be specified - the place
     where the moved stuff gets put.  Of course the lines to be  moved
     can be specified by context searches; if we had

           First paragraph
           ...
           end of first paragraph.
           Second paragraph
           ...
           end of second paragraph.

     we could reverse the two paragraphs like this:

           /Second/,/second/m/First/-1

     Notice  the  "-1" - the moved text goes aaafffttteeerrr the line mentioned.


                                 -18-


Ed (4)                        28-Oct-80                         Ed (4)


     Dot gets set to the last line moved. 
     
THE GLOBAL COMMAND ``g''
     The ggglllooobbbaaalll command "g" is used to execute an eeeddd  command  on  all
     those  lines in the buffer that match some specified string.  For
     example

           g/peling/p

     prints all lines that contain "peling".  More usefully,

           g/peling/s//pelling/gp

     makes the substitution everywhere on the line, then  prints  each
     corrected line.  Compare this to

           1,$s/peling/pelling/gp

     which  only  prints  the  last  line substituted.  Another subtle
     difference is that the  "g"  command  does  not  give  a  "?"  if
     "peling" is not found where the "s" command will. 
     
SPECIAL CHARACTERS
     You  may  have noticed that things just don't work right when you
     used some characters like "?", "*", "$", and  others  in  context
     searches  and  the  substitute  command.   The  reason  is rather
     complex, although  the cure  is  simple.   Basically,  eeeddd  treats
     these   characters   as  special,  with  special  meanings.   For
     instance, iiinnn  a  context  search  or  the  first  string  of  the
     substitute command only,

           /x?y/

     means  "a  line  with  an x, aaannnyyy character, and a y," nnnooottt just "a
     line with an x, a question mark, and a y."  A  complete  list  of
     the special characters that can cause trouble is the following:

           %   .   $   [   ]   *   @   #   !   +   {   }

     WWWaaarrrnnniiinnnggg:::  The  character  @ is special to eeeddd...  For safety's sake,
     avoid it where possible.  If you have to use one of  the  special
     characters  in  a  substitute command, you can turn off its magic
     meaning temporarily by preceding it with the "at" sign.  Thus

           s/@@?@*/at quest star/

     will change "@?*" into "at quest star". 

     Here is a hurried  synopsis  of  the  other  special  characters.
     First, the percent "%" signifies the beginning of a line.  Thus


                                 -19-


Ed (4)                        28-Oct-80                         Ed (4)


           /%string/

     finds  "string" only if it is at the beginning of a line: it will
     find

           string

     but not

           the string... 

     The dollar-sign "$" is just the opposite of the percent sign;  it
     means the end of a line:

           /string$/

     will  only  find  an occurrence of "string" that is at the end of
     some line.  This implies, of course, that

           /%string$/

     will find only a line that contains just "string", and

           /%?$/

     finds a line containing exactly one character. 

     The character "?", as we mentioned above, matches anything;

           /x?y/

     matches any of

           xay
           x1y
           x+y
           x-y
           x y
           x.y

     This is useful in conjunction with "*",  which  is  a  repetition
     character;  "a*"  is  shorthand  for "any number of a's", so "?*"
     matches any number of anythings.  This is used like this:

           s/?*/stuff/

     which changes an entire line, or

           s/?*,//



                                 -20-


Ed (4)                        28-Oct-80                         Ed (4)


     which deletes all characters in the line up to and including  the
     last  comma.   (Since "?*" finds the longest possible match, this
     goes up to the last comma.)

     "[" is used with "]" to form "character classes"; for example,

           /[1234567890]/

     matches any single digit - any one of the characters  inside  the
     braces will cause a match. 

     Finally,  the  "&"  is  another  shorthand character - it is used
     only on the right-hand part of  a  substitute  command  where  it
     means  "whatever  was matched on the left-hand side".  It is used
     to save typing.  Suppose the current line contained

           Now is the time

     and we wanted to  put  parentheses  around  it.   We  could  just
     retype the line, but this is tedious.  Or we could say

           s/%/(/
           s/$/)/

     using  our  knowledge  of  "%" and "$".  But the easiest way uses
     the "&":

           s/?*/(&)/

     This says "match  the  whole  line,  and  replace  it  by  itself
     surrounded  by  parens."   The "&" can be used several times in a
     line; consider using

           s/?*/&. &!!/

     to produce

           Now is the time.  Now is the time!!

     We don't have to match the whole line, of course:  if the  buffer
     contains

           the end of the world

     we could type

           /world/s//& is at hand/

     to produce



                                 -21-


Ed (4)                        28-Oct-80                         Ed (4)


           the end of the world is at hand

     Observe  this  expression  carefully,  for  it illustrates how to
     take advantage of eeeddd to save typing.  The string "/world/"  found
     the  desired  line; the shorthand "//" found the same word in the
     line; and the "&" saved us from typing it again. 

     The "&" is a special character only within the  replacement  text
     of  a  substitute  command, and has no special meaning elsewhere.
     We can turn off the special meaning of "&" by preceding  it  with
     a "@":

           s/ampersand/@&/

     will  convert the word "ampersand" into the literal symbol "&" in
     the current line. 
     
ACKNOWLEDGEMENT
     The majority of this document has been taken, with  the  author's
     permission,  from  "A  Tutorial  Introduction  to  the  UNIX Text
     Editor" by B.  W.  Kernighan.   It  has  been  changed   only  to
     reflect   the  differences  between  this  editor  and  the  UNIX
     version. 
     
SUMMARY OF COMMANDS AND LINE NUMBERS
     The general form of eeeddd commands  is  the  command  name,  perhaps
     preceded  by  one  or  two line numbers, and, in the case of eee,,, rrr
     and www,,, followed by a file name.  Only one command is allowed  per
     line,  but  a  ppp command may follow any other command (except for
     eee,,, rrr,,, www and qqq)))... 

     aaa (append) Add lines  to  the  buffer  (at  line  dot,  unless  a
     different  line  is specified).  Appending continues until "." is
     typed on a new line.  Dot is set to the last line appended. 

     bbb (browse) Display 23 lines of text,  beginning  at  the  current
     line.   The  current  line  will  be  centered if you use b.  ("b
     dot").   Using  b-  will  cause  the  previous  23  lines  to  be
     printed. 

     ccc  (change)  Change  the  specified  lines  to the new text which
     follows.  The new lines are terminated by a  ".".   If  no  lines
     are  specified,  replace  line  dot.   Dot  is  set  to last line
     changed. 

     ddd (delete) Delete the lines specified.  If  none  are  specified,
     delete  line dot.  Dot is set to the first undeleted line, unless
     "$" is deleted, in which case dot is set to "$". 

     eee (edit) Edit new file.  Any previous contents of the buffer  are


                                 -22-


Ed (4)                        28-Oct-80                         Ed (4)


     thrown away, so issue a www beforehand if you want to save them. 

     fff  (file)  Print  remembered  filename.   If a name follows fff the
     remembered name will be set to it. 

     ggg (global) g/---/command will execute the command on those  lines
     that contain "---", which can be any context search expression. 

     iii  (insert)  Insert  lines before specified line (or dot) until a
     "." is typed on a new line.  Dot is set to last line inserted. 

     mmm (move) Move lines specified to after the line  named  after  mmm...
     Dot is set to the last line moved. 

     ppp  (print)  Print specified lines.  If none specified, print line
     dot.  A single line number is equivalent to "line-number  p".   A
     single newline prints ".+1", the next line. 

     qqq (quit) Exit from ed.  Wipes out all text in buffer!!

     rrr  (read)  Read  a  file  into  buffer  (at  end unless specified
     elsewhere.)  Dot set to last line read. 

     sss (substitute) s/string1/string2/ will substitute the  characters
     of  `string2'  for  `string1'  in specified lines.  If no line is
     specified, make substitution in line dot.  Dot  is  set  to  last
     line  in  which a substitution took place, which means that if no
     substitution took place, dot is not changed.  sss changes only  the
     first  occurrence  of  string1  on a line; to change all of them,
     type a "g" after the final slash. 

     www (write) Write out buffer onto a file.  Dot is not changed. 

     ...=== (dot value) Print value of dot.  ("="  by  itself  prints  the
     value of "$".)

     ///---------///  Context  search.  Search for next line which contains this
     string of characters.  Print  it.   Dot  is  set  to  line  where
     string  found.   Search starts at ".+1", wraps around from "$" to
     1, and continues to dot, if necessary. 

     \---\ Context search  in  reverse  direction.   Start  search  at
     ".-1", scan to 1, wrap around to "$". 









                                 -23-

#-h- msg            32904  asc  22-jul-83 12:29:19  sventek (joseph sventek)


Msg (4)                       17-Mar-82                        Msg (4)


NAME
    Msg - message editor


                              MSG Primer
                                   
                            Joseph Sventek
              Computer Science & Mathematics Department
                     Lawrence Berkeley Laboratory
                         Berkeley, CA  94720


msg  is basically a message editor.  It may be used to read, write and
modify files which have  the  message  file  format.   There  are  two
default files of this type in your home directory:

 mymail - messages sent to you by others are deposited here. 
   mbox - the messages in mymail are saved here, by default. 

msg  gives  the  user  the  power to create and manage other files for
conveniently sorting and categorizing messages received. 

All commands to msg consist of a single  character.   msg  then  types
out  the  rest  of  the  command  name  and, if necessary, prompts for
additional information needed to complete the request. 

msg  is  entered  via  the  following  command  line  to  the  command
interpreter on your machine:

     msg [-p[n]] [filename]

If  no  filename  is specified, msg defaults to the file mymail in the
home directory.  msg first prints out  a  banner  identifying  itself;
then  it  reads  the  file  specified  (or  mymail).  If there are any
messages in the file, the headers  for  that  file  are  automatically
displayed.   Completing  this, msg then prompts the user for a command
character with the string

     <-

The following symbols are used in the command descriptions below:

<RETURN> the character generated by hitting the RETURN or CR key
 <SPACE> the character generated by hitting the space bar
  <ESC>  the character generated by hitting the ESC key
    ^C   the character generated by holding  down  the  CTRL  key  and
         hitting the key `C'





                                 -1-


Msg (4)                       17-Mar-82                        Msg (4)


There are only five types of input expected by msg:

  1. an msg command character
  2. a message sequence specification
  3. a filename
  4. a confirmation character (<SPACE>)
  5. an output continuation character (<SPACE>)

Whenever  msg  prompts  for  input,  typing  <ESC>  causes the current
command to be aborted, and the user is returned to command level. 

The following conventions are used in the command descriptions below:

<FILE-NAME>
     This stands for any valid file specification on your system.   If
     the   tools   on  your  system  support  pathname  to  local-name
     translation, any valid pathname may also be used. 

<MSG-SEQUENCE>
     This input is prompted for by the  string  "(message  sequence)".
     Valid responses to this prompt are:

       1. Any single message number, as listed in the headers. 
       2. Any  two  message  numbers  separated  by  ":" or "-".  This
          specification describes a range  of  message  numbers  (e.g.
          2-5  means  messages 2 and 3 and 4 and 5 in that order).  If
          the first number is larger than the second, then  the  range
          is  traversed  in  decreasing  order.  If the second message
          number is omitted, then the number of the  last  message  in
          the current file is used. 
       3. Any   sequence  of  the  previous  two  types  separated  by
          commas.   For example,
               1,3,5-7,10
          means  messages  1  and  3  and  5   through   7   and   10.
          <MSG-SEQUENCE>  of  the types described above are terminated
          by <RETURN>. 
       4. Special types of message sequences, which are determined  by
          the  first  character  typed  in  response  to  the (message
          sequence) prompt. 

          character
            typed                       action
          --------- ---------------------------------------------

           <RETURN> The relevant process is performed on  the  current
                    message

               a    The  string  "all  messages"  is displayed and the
                    relevant action is taken on all messages



                                 -2-


Msg (4)                       17-Mar-82                        Msg (4)


               c    Identical to <RETURN>

               d    The string "deleted  messages"  is  displayed  and
                    the  appropriate action is taken on those messages
                    currently marked as deleted

               f    The  string  "from   string:   "   is   displayed,
                    prompting  the  user to supply a string to be used
                    in a pattern match with the  from  fields  of  the
                    headers.   The  characteristics  of  these strings
                    are described below. 

               s    The  string  "subject  string:  "  is   displayed,
                    prompting  the  user to supply a string to be used
                    in a pattern match with the subject fields of  the
                    headers.   See  below  for more information on the
                    characteristics of these strings. 

               u    The string "undeleted messages" is  displayed  and
                    the  relevant  action  is  taken on those messages
                    currently not deleted

The strings required for the from and  subject  search  are  the  same
regular  expressions  used  by  the  editor,  find  and change.  Those
manual entries may be consulted  for  more  information.   The  string
must  be  terminated  by  a  <RETURN>.  If a bare <RETURN> is typed in
response to the string prompt, no searching is done  and  the  command
is terminated. 

Whenever  msg  prompts  for  a  string  which  must be terminated by a
<RETURN> (message sequences, from  or  subject  search  strings  or  a
filename), character editing may be performed as follows:

  1. DEL(RUB) or BACKSPACE(^H) will delete the last character. 
  2. ^U will delete the entire string typed so far. 
  3. ^R  will  cause the current string to be retyped on the next line
     of  the  terminal.   This  is  handy  for  users  with   hardcopy
     terminals,  as  character  deletions and replacements will result
     in overprinted paper, and ^R can be used to see exactly what  has
     been typed. 

Since  msg  is a tool, both its standard input and standard output may
be redirected to disk files.  In particular, that is how the  writeups
for  each  individual  command  below was obtained, through the use of
the online help facility, as well as the  example  dialogue  described
below.   It  should be noted that if the standard output is redirected
to a file but standard input is not, none of the prompts or output  of
the commands typed will be seen by the user. 

When  operating in interactive mode, all output to the user's terminal


                                 -3-


Msg (4)                       17-Mar-82                        Msg (4)


is paged - i.e. after a screenful is displayed, the user  is  prompted
to  see  if more output is desired.  Positive responses to this prompt
("[type SPACE  to  continue]")  is  a  <SPACE>.   Any  other  response
results in the following actions:

  1. If  msg  was  typing a large message, it will stop displaying the
     current message.  If there are more messages to be typed  in  the
     current  command,  msg  will  then  ask  if  the  next message is
     desired.  A negative response to this prompt  ("[type  SPACE  for
     next  message]")  results  in  the discontinuation of the current
     command and a return to command level ("<-"). 
  2. If the ? or h[eaders] command generates more than a screenful  of
     lines,  the  user  will  be  prompted.   A negative response will
     result in the discontinuation of the current command. 

The default page size is 22 lines.  This may be modified by using  the
`-p[n]'  switch  in the arguments to msg.  If n is specified, then the
page size is reset to that value.  Simply typing -p with  no  trailing
number  turns  paging  off.   !!!BEWARE!!!   If  you  turn  off paging
altogether, and give a command which generates a lot of  output  (i.e.
t[ype]  a[ll  messages]),  there  is  no  way  to stop msg until it is
done.  A better approach is to set n very large (say 1000 or  so),  so
that  header  listings  and entire messages will not be paged, but msg
will stop after each message when typing multiple message sequences. 




























                                 -4-


Msg (4)                       17-Mar-82                        Msg (4)


The banner that msg greets the user with is:
     
     
         Software Tools MSG System
             type ? for help
             type # for news
             type % for intro
     
     



Typing ? to the prompt results in the following information:

     
     
     <- ? MSG Help
     
     The following commands are recognized by msg:
     a[nswer]        message
     b[ackup]        to previous message and type it
     c[urrent]       message number and file
     d[elete]        message(s)
     e[xit]          and update old file
     f[orward]       message
     g[o to]         message specified and print it
     h[eaders]       print headers of message(s)
     i[nformation]   on command displayed
     j[ump]          into shell - return by typing logout to shell
     k[ey]           encryption-key  *** UNIMPLEMENTED ***
     l[ist]          message(s) in print format on file
     m[ove]          message(s) to another mail file and mark them deleted
     n[ext]          message is typed
     o[verwrite]     current file and re-read
     p[ut]           copies of message(s) in another mail file
     q[uit]          leave MSG without updating current file
     r[ead]          in another mail file
     s[ndmsg]        invoke SNDMSG to send a message (and return to MSG)
     t[ype]          message(s) on standard output
     u[ndelete]      message(s)
     #[news]         print MSG news
     ?[help]         print this list
     %[intro]        type an introduction to MSG (for first-time users)
     For more information, use the i[nformation] command.
     
     
Listed are the valid commands to msg.  Those  which  are  defined  but
unimplemented  are  noted  as  such.   Expanded  information  for each
command may be had through the use of the i[nformation] command. 



                                 -5-


Msg (4)                       17-Mar-82                        Msg (4)


Typing # results in the following display:

     
     
     <- # MSG News
             No news is good news!
     
As modifications are made to the system, entries  will  be  placed  in
msg's  database  such  that  the  news command will inform the user of
recent changes. 



Typing % results in the following display:

     
     
     <- % Introduction to MSG
     If you are a new MSG user, you probably need ONLY the following commands:
     
           t type message(s) on terminal; common options are `a' for all
             messages or `<n>' (where <n> is an integer) for message <n>.
     
           d delete a message after reading it; common options as above.
     
           e exit MSG and move messages which have not been deleted to your
             mail file (`mbox' in your home directory).
     
           q quit MSG without updating your mail file; if there are any
             messages left, you will be notified when you next login (or
             the next time you run `postmn').
     
     NOTE:   These command characters should NOT be followed by a RETURN. When
             you type one of them, MSG will immediately prompt you for more
             input.
     
     To print a copy of the MSG primer on the lineprinter, type
     
                     sh -c "msgprim | lpr"
     
This synopsis is meant for first time users, to  help  them  in  their
efforts to use msg. 










                                 -6-


Msg (4)                       17-Mar-82                        Msg (4)


The  following  is  a  list  of the online documentation available for
each of the supported commands.  The general format of the  output  of
the i[nformation] command is:

  1. A  line  which  shows how the terminal will look when the command
     is used. 
  2. A full description of what  the  command  does,  what  inputs  it
     expects,   and   references   to   other  commands  with  similar
     functionality. 

     
     
     
     
     <- information - type command character: a
     
     Answer message number: <NUMBER>
     
     This command causes sndmsg to be spawned as a sub-process, with the
     To field being the sender of the indicated message, and the subject
     field consisting of the string "Re: <SUBJECT>", where <SUBJECT> is
     replaced by the subject of the indicated message.  In addition, the
     message header of the answering message will contain the line
     
     "In-reply-to: Your message of <DATE>"
     
     where <DATE> is replaced by the date of the indicated message.
     The user will be prompted for Cc addresses and the message to be sent.
     
     
     <- information - type command character: b
     
     Backing up - previous message is:
     
     This command displays the previous message (i.e. current message - 1).
     It is the inverse of the Next command.  The current message number is
     decremented.  If the current message number is 1 when Backup is invoked,
     an error message is displayed.
     
     
     <- information - type command character: c
     
     Current message is nn of mm messages in file <FILE-NAME>
     
     This command displays:
       1. the number of the current message
       2. the total number of messages in the message file
       3. the file name of the currently active message file
     
     


                                      -7-


     Msg (4)                       17-Mar-82                        Msg (4)


     <- information - type command character: d
     
     Delete (message sequence) <MSG-SEQUENCE>
     
     This command marks the messages specified in MSG-SEQUENCE as deleted,
     as indicated by an asterisk following the message number in the headers
     of the affected messages.  The actual messages in the message file are
     not affected unless an Overwrite, Exit or Write command is executed
     before leaving MSG.
     
     
     <- information - type command character: e
     
     Exit and update old file <FILE-NAME> [type SPACE to confirm]
     
     This command overwrites the current message file, but permits the user
     to leave MSG rather than re-reading the message file as Overwrite does.
     
     
     <- information - type command character: f
     
     Forward message number: <NUMBER>
     
     This command causes sndmsg to be spawned as a sub-process, with the
     message consisting of the header and message body of the indicated
     message.  The user will be prompted for To, Cc and Subject fields
     upon entry into sndmsg.
     
     
     <- information - type command character: g
     
     Go to message number: <NUMBER>
     
     This command permits explicit changing of the current message number.
     If <NUMBER> is not in the range of acceptable values (i.e. it is less
     than 1 or greater than the number of messages in the file), an error
     message is displayed and the current message number will remain
     unchanged.  Legal inputs for <NUMBER> are:
       1. a number in the range 1 <= n <= NMSGS
       2. f for the first message (message number 1)
       3. l for the last message
       4. <CARRIAGE-RETURN> for the current message number (a noop)
     
     
     <- information - type command character: h
     
     Headers (message sequence) <MSG-SEQUENCE>
     
     This command displays the headers for the messages defined by the
     specified message sequence.  Headers corresponding to deleted


                                      -8-


     Msg (4)                       17-Mar-82                        Msg (4)


     messages have an asterisk printed after the message number for that
     particular message.  The format for the headers is:
     
     <msg-no>  <size in characters>  <date>  <from>  <subject>
     
     The headers are displayed a screenful at a time.  After a screenful
     has been output, if there are more headers remaining to be displayed,
     the user is prompted with the string "[type SPACE to continue]".
     A response of SPACE will cause the next screenful to be displayed.
     Any other response terminates the listing of the headers.
     
     
     <- information - type command character: i
     
     Information - type command character: <COMMAND-CHARACTER>
     
     This command displays full help information for those commands listed
     by the ? command.
     
     
     <- information - type command character: j
     
     Jump into shell [type SPACE to confirm]
     
     This command drops the user into the Software Tools shell.  All
     normal commands may be executed while in the shell.  Control returns
     to MSG by typing logout to the shell.
     
     
     <- information - type command character: l
     
     List (message sequence) <MSG-SEQUENCE>
     on file name: <FILE-NAME>
     
     This command lists all the specified messages on the file specified
     (overwriting the current contents of <FILE-NAME>.  A preface page,
     consisting of a FORMFEED character and the headers of the selected
     messages is output first, followed by each message preceded by a
     FORMFEED character.  The file output by List can be disposed to a
     printer using the lpr shell command, resulting in a message on each
     page of the output.
     
     
     <- information - type command character: m
     
     Move (message sequence) <MSG-SEQUENCE>
     into file name: <FILE-NAME>
     
     This command is a convenient combination of the Put and Delete commands.
     It will first put the selected messages into the file specified and then


                                      -9-


     Msg (4)                       17-Mar-82                        Msg (4)


     mark the messages as deleted in the header information.
     
     
     <- information - type command character: n
     
     Next message is:
     
     This command displays the next message (current message number + 1)
     and increments the current message number.  If the current message is
     already the last one, an error message is displayed and the current
     message number remains unchanged.
     
     
     <- information - type command character: o
     
     Overwrite old file <FILE-NAME> [type SPACE to confirm]
     
     This command will overwrite the current file (specified by <FILE-NAME>),
     eliminating any deleted messages.  It then re-reads the file, re-numbering
     the messages.
     
     
     <- information - type command character: p
     
     Put (message sequence) <MSG-SEQUENCE>
     into file name: <FILE-NAME>
     
     This command will put the messages specified by <MSG-SEQUENCE> into
     the file specified by <FILE-NAME>.  If the file does not exist, it
     will create the file and write the messages into it.  If the file
     already exists, the messages are appended to those already in the
     file.
     
     
     <- information - type command character: q
     
     Quit [type SPACE to confirm]
     
     This command allows the user to leave MSG without modifying the
     current message file.
     
     
     <- information - type command character: r
     
     Read file name: <FILE-NAME>
     
     This command allows the user to use MSG on files created by previous
     Move or Put invocations.  The current message file is closed with no
     modification, and the file specified is read, displaying the headers
     before prompting for the next command.


                                      -10-


     Msg (4)                       17-Mar-82                        Msg (4)


     
     
     <- information - type command character: s
     
     Sndmsg [type SPACE to confirm]
     
     This command causes SNDMSG to be spawned as a sub-process, allowing the
     user to send a message without leaving MSG; when SNDMSG exits, MSG
     regains control with no changed to files, etc.
     
     
     <- information - type command character: t
     
     Type (message sequence) <MSG-SEQUENCE>
     
     This command displays the messages specified.  If more than one message
     is specified, the user is prompted with "[type SPACE for next message]"
     after each message.  In addition, if a particular message is
     larger than one screenful, the user is prompted after each screenful.
     A negative response to this latter prompt results in the termination of
     the display of the particular message, while a negative response to the
     former results in termination of the Type command.
     
     
     <- information - type command character: u
     
     Undelete (message sequence) <MSG-SEQUENCE>
     
     This command undoes the actions of the Delete command.
     






















                                      -11-


     Msg (4)                       17-Mar-82                        Msg (4)


     The following is a sample dialogue using many of the msg commands.
     The characters typed by the user are underlined, with the token <CR>
     standing for typing <RETURN>.

     % _m_s_g_t_e_s_t _>_t_e_s_t_._m_s_g_; _m_s_g _t_e_s_t_._m_s_g_<_C_R_>
     
     
     
     
         Software Tools MSG System
             type ? for help
             type # for news
     
        1    114 25-MAR-80     Tools               another test of mail
        2    323 27-MAR-80     Tools               still more tests
        3    289 27-MAR-80     Tools               testing
        4    114 01-APR-80     Tools               test of the mail system
        5    330 03-APR-80     System              A TEST OF THE MAIL SYSTEM
        6    116 09-APR-80     Tools               a test of the mail system
        7    308 09-APR-80     Tools               more testing
        8     99 09-APR-80     Tools               another test
        9    145 09-APR-80     Tools               why doesn't mail work?
       10    129 10-APR-80     Tools               more testing
       11    298 10-APR-80     Tools               more testing
       12    326 10-APR-80     Tools               Yet another test
       13    129 10-APR-80     Sventek             sventek's test
       14    314 10-APR-80     Tools               testing again
     
     <- _headers (message sequence) _1_,_2_,_4_-_6_<_C_R_>
        1    114 25-MAR-80     Tools               another test of mail
        2    323 27-MAR-80     Tools               still more tests
        4    114 01-APR-80     Tools               test of the mail system
        5    330 03-APR-80     System              A TEST OF THE MAIL SYSTEM
        6    116 09-APR-80     Tools               a test of the mail system
     
     <- _type (message sequence) _subject string: _s_v_e_n_t_e_k_<_C_R_>
     
     (message 13, 129 characters)
     Date:    10-APR-80 10:43:02 - PST
     From:    Sventek
     Subject: sventek's test
     To:      sventek, tools, system
     
     sure hope this works
     
     <- _put (message sequence) _subject string: _m_a_i_l_<_C_R_>
     into file name: _n_t_e_s_t_._m_s_g_<_C_R_>
     <- _delete (message sequence) _from string: _s_y_s_t_e_m_<_C_R_>
     <- _type (message sequence) _deleted messages
     


                                      -12-


     Msg (4)                       17-Mar-82                        Msg (4)


     (message 5, 330 characters)
     Date: 03-APR-80 11:35:09 - PST
     From: System
     Subject: A TEST OF THE MAIL SYSTEM
     To: allen, austin, bargmeyer, benson, gey, guest, heckman, helena,
         hogan, holmes, kreps, merrill, oracle, robinson, rtsg, scherrer,
         shoshani, sventek, sventekv, system, tabata, tape, tools
     
     THIS IS ANOTHER TEST.  SORRY FOR THE INCONVENIENCE.
     
     
     <- _overwrite old file 'test.msg' [type SPACE to confirm] _<_S_P_A_C_E_>
     updating...
        1    114 25-MAR-80     Tools               another test of mail
        2    323 27-MAR-80     Tools               still more tests
        3    289 27-MAR-80     Tools               testing
        4    114 01-APR-80     Tools               test of the mail system
        5    116 09-APR-80     Tools               a test of the mail system
        6    308 09-APR-80     Tools               more testing
        7     99 09-APR-80     Tools               another test
        8    145 09-APR-80     Tools               why doesn't mail work?
        9    129 10-APR-80     Tools               more testing
       10    298 10-APR-80     Tools               more testing
       11    326 10-APR-80     Tools               Yet another test
       12    129 10-APR-80     Sventek             sventek's test
       13    314 10-APR-80     Tools               testing again
     
     <- _move (message sequence) _1_-_5_<_C_R_>
     into file name: _o_l_d_._m_s_g_<_C_R_> 
     <- _go to message number: _first
     (message 1, 114 characters)
     Date: 25-MAR-80 12:46:23 - PST
     From: Tools
     Subject: another test of mail
     To: tools
     
     sure hope this works again.
     
     
     
     <- _current message is 1 of 13 messages in file 'test.msg'
     <- _next message is:
     (message 2, 323 characters)
     Date:    27-MAR-80 15:08:32 - PST
     From:    Tools
     Subject: still more tests
     To:       allen, austin, bargmeyer, benson, gey, guest, heckman, helena,
               hogan, holmes, kreps, merrill, oracle, robinson, rtsg,
               scherrer, shoshani, sventek, sventekv, system, tabata, tape,
               tools


                                      -13-


     Msg (4)                       17-Mar-82                        Msg (4)


     
     another test message
     
     
     <- _go to message number: _last
     (message 13, 314 characters)
     Date:    10-APR-80 14:53:19 - PST
     From:    Tools
     Subject: testing again
     To:      allen, austin, bargmeyer, benson, gey, guest, heckman, helena,
              hogan, holmes, kreps, merrill, oracle, robinson, rtsg,
              scherrer, shoshani, sventek, sventekv, system, tabata, tape,
              tools
     
     will it never stop?
     
     <- _current message is 13 of 13 messages in file 'test.msg'
     <- _backing up - previous message is:
     (message 12, 129 characters)
     Date:    10-APR-80 10:43:02 - PST
     From:    Sventek
     Subject: sventek's test
     To:      sventek, tools, system
     
     sure hope this works
     
     <- _jump into shell [type SPACE to confirm] _<_S_P_A_C_E_>
     % _l_o_g_o_u_t_<_C_R_>
     
     <- _? MSG Help
     
     The following commands are recognized by msg:
     a[nswer]        message
     b[ackup]        to previous message and type it
     c[urrent]       message number and file
     d[elete]        message(s)
     e[xit]          and update old file
     f[orward]       message
     g[o to]         message specified and print it
     h[eaders]       print headers of message(s)
     i[nformation]   on command displayed
     j[ump]          into shell - return by typing logout to shell
     k[ey]           encryption-key  *** UNIMPLEMENTED ***
     l[ist]          message(s) in print format on file
     m[ove]          message(s) to another mail file and mark them deleted
     n[ext]          message is typed
     o[verwrite]     current file and re-read
     p[ut]           copies of message(s) in another mail file
     q[uit]          leave MSG without updating current file
     r[ead]          in another mail file


                                      -14-


     Msg (4)                       17-Mar-82                        Msg (4)


     s[ndmsg]        invoke SNDMSG to send a message (and return to MSG)
     t[ype]          message(s) on standard output
     u[ndelete]      message(s)
     #[news]         print MSG news
     ?[help]         print this list
     %[intro]        type an introduction to MSG (for first-time users)
     For more information, use the i[nformation] command.
     
     
     <- _# MSG News
             No news is good news!
     
     <- _information - type command character: _r
     
     Read file name: <FILE-NAME>
     
     This command allows the user to use MSG on files created by previous
     Move or Put invocations.  The current message file is closed with no
     modification, and the file specified is read, displaying the headers
     before prompting for the next command.
     
     <- _headers (message sequence) _all messages
        1*   114 25-MAR-80     Tools               another test of mail
        2*   323 27-MAR-80     Tools               still more tests
        3*   289 27-MAR-80     Tools               testing
        4*   114 01-APR-80     Tools               test of the mail system
        5*   116 09-APR-80     Tools               a test of the mail system
        6    308 09-APR-80     Tools               more testing
        7     99 09-APR-80     Tools               another test
        8    145 09-APR-80     Tools               why doesn't mail work?
        9    129 10-APR-80     Tools               more testing
       10    298 10-APR-80     Tools               more testing
       11    326 10-APR-80     Tools               Yet another test
       12    129 10-APR-80     Sventek             sventek's test
       13    314 10-APR-80     Tools               testing again
     
     <- _list (message sequence) _from string: _t_o_o_l_s_<_C_R_>
     on file name: _t_o_o_l_s_._l_s_t_<_C_R_> 
     <- _undelete (message sequence) _deleted messages
     <- _move (message sequence) _from string: _s_v_e_n_t_e_k_<_C_R_>
     into file name: _s_v_e_n_t_e_k_._m_s_g_<_C_R_> 
     <- _current message is 12 of 13 messages in file 'test.msg'
     <- _headers (message sequence) _undeleted messages
        1    114 25-MAR-80     Tools               another test of mail
        2    323 27-MAR-80     Tools               still more tests
        3    289 27-MAR-80     Tools               testing
        4    114 01-APR-80     Tools               test of the mail system
        5    116 09-APR-80     Tools               a test of the mail system
        6    308 09-APR-80     Tools               more testing
        7     99 09-APR-80     Tools               another test


                                      -15-


     Msg (4)                       17-Mar-82                        Msg (4)


        8    145 09-APR-80     Tools               why doesn't mail work?
        9    129 10-APR-80     Tools               more testing
       10    298 10-APR-80     Tools               more testing
       11    326 10-APR-80     Tools               Yet another test
       13    314 10-APR-80     Tools               testing again
     
     <- _overwrite old file 'test.msg' [type SPACE to confirm] _<_S_P_A_C_E_>
     updating...
        1    114 25-MAR-80     Tools               another test of mail
        2    323 27-MAR-80     Tools               still more tests
        3    289 27-MAR-80     Tools               testing
        4    114 01-APR-80     Tools               test of the mail system
        5    116 09-APR-80     Tools               a test of the mail system
        6    308 09-APR-80     Tools               more testing
        7     99 09-APR-80     Tools               another test
        8    145 09-APR-80     Tools               why doesn't mail work?
        9    129 10-APR-80     Tools               more testing
       10    298 10-APR-80     Tools               more testing
       11    326 10-APR-80     Tools               Yet another test
       12    314 10-APR-80     Tools               testing again
     
     <- _read file name: _n_t_e_s_t_._m_s_g_<_C_R_> reading...
        1    114 25-MAR-80     Tools               another test of mail
        2    114 01-APR-80     Tools               test of the mail system
        3    330 03-APR-80     System              A TEST OF THE MAIL SYSTEM
        4    116 09-APR-80     Tools               a test of the mail system
        5    145 09-APR-80     Tools               why doesn't mail work?
     
     <- _quit [type SPACE to confirm] _<_S_P_A_C_E_>























                                      -16-

#-h- ratfor         26657  asc  22-jul-83 12:29:33  sventek (joseph sventek)


Ratfor (4)                  4-Apr-78                   Ratfor (4)


NAME
    Ratfor - rational FORTRAN pre-processor


                          RATFOR PRIMER

Ratfor  is a preprocessor for Fortran.  Its primary purpose is to
encourage  readable  and  well-structured   code   while   taking
advantage  of  the  universality,  portability, and efficiency of
Fortran.  This is done by providing the  control  structures  not
available  in  bare  Fortran, and by improving the "cosmetics" of
the language. 

Ratfor allows for all the features of normal Fortran, plus  makes
available these control structures:
          
          "if"-"else"
          "while", "for", and "repeat"-"until" for looping
          "switch" for multi-way branching
          "break" and "next" for controlling loop exits
          statement grouping with braces
          

The  cosmetic  aspects  of  Ratfor  have been designed to make it
concise and reasonably pleasing to the eye:
          
          free form input
          unobtrusive comment convention
          translation of >, <=, etc. into .GT., .LE., etc.
          string data type
          quoted character strings
          character constants
          "define" statement for symbolic constants
          conditional preprocessing
          "include" statement for including source files


Ratfor is implemented as  a  preprocessor  which  translates  the
above  features  into  Fortran, which can then be fed into almost
any Fortran compiler. 

Each of the  Ratfor  features  will  now  be  discussed  in  more
detail.   In  the following, a "statement" is any legal statement
in Fortran: assignment, declaration, subroutine call, I/O,  etc.,
or  any  of  the  Ratfor  statements  themselves.  Any Fortran or
Ratfor statement or group of these  can  be  enclosed  in  braces
({})  or  brackets ([]) -- to make it a compound statement, which
is then equivalent to a single statement and  usable  anywhere  a
single statement can be used. 



                               -1-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                             IF-ELSE

Ratfor   provides   an   "if-else"   statement   to   handle  the
construction "if a condition is true, do  this  thing,  otherwise
do that thing".  The syntax is
          
          if (legal Fortran condition)
              statement(s)
          else
              statement(s)
          
where  the  else part is optional.  The "legal Fortran condition"
is anything that can legally go into a Fortran logical  IF.   The
Ratfor  statements  may  be  one  or more valid Ratfor or Fortran
statements of any kind.  If more than one statement  is  desired,
the statements must be enclosed by braces.  For example,

          if (a > b)
              {
              k = 1
              call remark (...)
              }
          else if (a < b)
              {
              k = 2
              call remark (...)
              }
          else
              return
          






















                               -2-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                              WHILE

Ratfor  provides  a  while  statement,  which  is  simply a loop:
"while  some  condition   is   true,   repeat   this   group   of
statements".  The syntax is

          while (legal Fortran condition)
              statement(s)
          
As  with  the if, "legal Fortran condition" is something that can
go into a Fortran logical IF.  The  condition  is  tested  before
execution  of  any  of the Ratfor statements, so if the condition
is not met, the loop will be executed zero times.  Also, as  with
the  IF, the Ratfor statements can be any valid Ratfor or Fortran
constructs.   If  more  than  one  statement  is   desired,   the
statements must be enclosed by braces.  For example,

          while (getc(c) != EOF)
              {
              c = cnvt (c)
              call putc (c)
              }
          





























                               -3-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                               FOR

The  "for"  statement  is  similar  to the "while" except that it
allows explicit initialization and increment  steps  as  part  of
the statement.  The syntax is

          for (init; condition; increment)
              statement(s)
          
where  "init"  is  any  single  Fortran statement which gets done
once before the loop begins.  "Increment" is any  single  Fortran
statement  which  gets  done  at the end of each pass through the
loop, before the test.  "Condition" is  again  anything  that  is
legal  in  a  logical  IF.  Any of init, condition, and increment
may  be  omitted,  although  the  semicolons  must   remain.    A
non-existent  condition  is  treated as always true, so "for( ; ;
)" is an indefinite repeat.  The "for" statement is  particularly
useful  for  backward  loops,  chaining  along  lists, loops that
might be done zero times, and similar things which  are  hard  to
express  with  a  DO  statement.   Here are two examples of "for"
loops:

          for (i=1; getarg(i, file, MAXLINE) != EOF; i=i+1)
              {
              int = open (file, READ)
              while (getlin (line, int) != EOF)
                  {
                  for (j=80; j>0; j=j-1)
                      call putc (line(j))
                  }
              call close (int)
              }
          
The above code simply reads cards from a list of files,  reverses
the  order  of  the  characters,  and  writes  the  cards  onto a
standard output file.  (The "!=" means .NE.)

Groups of Fortran statements  may  be  used  in  the  "init"  and
"increment"  clauses  by  separating  the  statements with commas
(,).  For example:

          for (i=1, j=1; buf(i) != EOS; i=i+2, j=j+1)
              out(j) = buf(i)
          
copies every other character in buf  into  consecutive  locations
in out. 






                               -4-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                          REPEAT-UNTIL

The  "repeat-until" statements allow for repetition of a group of
statements until a specified condition is met.  The syntax is:

          repeat
              statement(s)
          until (condition)
          
The "until" is optional.  Once again, if  more  than  one  Ratfor
statement   is  desired,  the  statements  must  be  enclosed  by
brackets.  If the "until" part  is  omitted,  the  result  is  an
infinite  loop  which  must  be  broken  with a "break" or "next"
statement (see below).  An example of a repeat-until loop is:

          repeat
              {
              call putc (' ')
              col = col + 1
              }
          until (tabpos(col,tabs) == YES)
          






























                               -5-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                             SWITCH

The  "switch"  statement  permits  the  execution  of   multi-way
branches.  The syntax is:

          switch (expression)
              {
              case constant[,constant]*: statement(s)
              case constant[,constant]*: statement(s)
                        .
                        .
                        .
              case constant[,constant]*: statement(s)
              default:                   statement(s)
              }
          
`expression'  must result in an integer or character value, which
is  then  compared  with  the  `constant's  enumerated   in   the
statement   block.   Unlike  the  `switch'  statement  in  the  C
programming language,  there  is  an  implied  break  after  each
case.   If  more  than  one  Ratfor statement is desired for each
case, the statements must be enclosed in brackets. 

It is possible to exit from a group of statements  in  the  scope
of  a  case  label  through  the  use  of  a break statement (see
below).  An example of the use of switch is:

          switch (ngetch(c, fd))
              {
              case 'a','q': x = 5
              case 'b','c': x = 10
              case EOF:     {
                            call remark("Error in input.")
                            call putbak(EOF)
                            }
              default:      x = 0
              }















                               -6-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                         BREAK and NEXT

Ratfor provides statements for  leaving  a  loop  early  and  for
beginning the next iteration. 

"Break"  causes  an  immediate  exit  from  whatever  loop  it is
contained  in  (which  may  be  a  "while",  "for",  "repeat"  or
"switch").   Control  resumes  with  the next statement after the
loop.  Only one loop is terminated by  a  "break",  even  if  the
"break" is contained inside several nested loops.  For example:

          repeat
              {
              if (getc(c) == EOF)
                  break
              ...
              }
          
"Next"  is  a  branch to the bottom of the loop, so it causes the
next iteration to be done.  "Next" goes to the condition part  of
a  "while"  or  "until", to the top of an infinite "repeat" loop,
and to the reinitialize part of a "for".  For example:

          for (i=1; i<10; i=i+1)
              {
              if (array(i) == ' ')
                  next
              ...
              }
          

Breaking out of multiple loops can be achieved by specifying  the
number  of  levels  to break out of after the break statement, as
in:

          repeat
              {
              repeat
                  {
                  if (condition)
                      break 2
                  line 2
                  }
              line 1
              }
          line 0

Upon execution of the "break 2" statement, execution  resumes  at
"line  0".   It is probably better to use a "goto" statement when
breaking out of multiple loops, since that  should  be  a  little


                               -7-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


easier to maintain and understand. 



















































                               -8-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


             STATEMENT GROUPING AND NULL STATEMENTS

Ratfor  allows  a  group of statements to be treated as a unit by
enclosing them in braces -- { and }.   This  is  true  throughout
the  language:  wherever  a  single Ratfor statement can be used,
there could also be several enclosed in braces.  For example:

          if (x > 100)
              {
              call error (...)
              err = 1
              return
              }

If braces  are  not  valid  characters  in  the  local  operating
system,  the  characters  "["  and "]" may be used instead of "{"
and "}" respectively. 


Ratfor also allows for null statements, most useful  after  "for"
and  "while"  statements.   A  semicolon  alone  indicates a null
statement.  For instance,

          while (getlin(line, int) != EOF)
              ;
          
would read lines from a file until the  end-of-file  was  reached
and

          for (i=1; line(i) == ' '; i=i+1)
              ;
          
positions after leading blanks in a line. 



















                               -9-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                         FREE-FORM INPUT

Statements  may  be  placed  anywhere  on  a line and several may
appear on one line if  they  are  separated  by  semicolons.   No
semicolon  is  needed  at  the  end  of  each line because Ratfor
assumes there is one statement per line  unless  told  otherwise.
Ratfor  will,  however, continue lines when it seems obvious that
they are not yet done. 

Any statement that begins with an all-numeric  field  is  assumed
to be a Fortran label and is placed in columns 1-5 upon output. 

Statements  may  be  passed through the Ratfor compiler unaltered
by inserting a percent sign (%) as the  first  character  on  the
line.   The percent will be removed, the rest of the line shifted
one position to the left, and  the  line  sent  out  without  any
changes.   This  is  a  convenient way to pass regular Fortran or
assembly code through the ratfor compiler. 

Sequences of characters may be passed through  the  pre-processor
unaltered  by  surrounding  them  with  the tokens %(...%).  This
proves  useful  if  it  is  necessary  to  interact  with   other
system-specific  software  which  uses RATFOR keywords or special
characters.  For example:

          call graph_label(%('X-Axis'%), %('Y-Axis'%))

permits  the  subroutine  graph_label  to  be  called  with   F77
character  strings  as  the  labels.  Using the %(...%) construct
prevents RATFOR from trying  to  interpret  the  F77  strings  as
character constants. 





















                              -10-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                            COMMENTS

A  sharp character "#" in a line marks the beginning of a comment
and the rest of the  line  is  considered  to  be  that  comment.
Comments and code can co-exist on the same line.  For example,

          function dummy (x)
          
          # I made up this function to show some comments
          
          dummy = x         #I am simply returning the parameter
          
          return
          end
          





































                              -11-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                      CHARACTER TRANSLATION

Sometimes  the  characters  >,  <=,  etc.  are  easier to read in
Fortran condition statements  than  the  standard  Fortran  .EQ.,
.LT.,  etc..    Ratfor allows either convention.   If the special
characters  are  used,  they  are  translated  in  the  following
manner:

          ==          .EQ.
          != ^= ~=    .NE.
          <           .LT.
          >           .GT.
          <=          .LE.
          >=          .GE.
          |           .OR.
          &           .AND.
          !           .NOT.
          
For example,

          for (i=1; i<= 5; i=i+1)
              ...
          
          if (j != 100)
              ...
          


























                              -12-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                        STRING DATA TYPE

All   character   arrays   in   Ratfor  are  sequences  of  ASCII
characters, stored right-adjusted, one per  array  element,  with
the  string  terminated  with an EOS marker.  An automatic way to
initialize string characters arrays is provided.  The syntax is:

                    string name "characters"
or
                   string name(n) "characters"

Ratfor will define name to  be  a  character  (or,  more  likely,
integer)  array long enough to accomodate the ASCII codes for the
given character string, one per element.  The last word  of  name
is  initialized  to EOS.  If a size is given, name is declared to
be an integer array of size 'n'.  If  several  string  statements
appear  consecutively,  the  generated declarations for the array
will precede the data statements that initialize them. 

For example, the declarations:

     string errmsg "error"
     string done "bye"

would be converted by ratfor into the Fortran:

     integer error(6)
     integer done(4)
     data error(1), error(2), error(3), error(4),
     error(5), error(6) /'e', 'r', 'r', 'o', 'r', EOS/
     data done(1), done(2), done(3), done(4) /'d', 'o',
     'n', 'e', EOS/

The standard escape characters used in the text processing utilities
(find, ch, ed, etc.) can be used inside of a string.  In particular,
to embed an atsign ('@') or a double quote ('"') into the string,
they must be escaped, as in:

     string escape "Embed quote (@")"













                              -13-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                    QUOTED CHARACTER STRINGS

Text enclosed in  matching  double  quotes  is  converted  to  an
appropriate   declaration   for  a  `character'  array,  and  the
appropriate data statements to load this array are  output.   The
variable  name  will be of the form STNNNZ, where NNN is replaced
by a rotating sequence number.  The array will be  declared  long
enough  to  place  the  value EOS in the last element, as for the
`string'  declaration.   Since  these   declarations   and   data
statements  are  output  immediately,  the resulting FORTRAN code
must be run through the program `ratp2', which will  reorder  the
code to be ANSI-66 compliant. 

String  literals  can  be  continued  across  line  boundaries by
ending  the  line  to  be  continued  with  an  underline.    The
underline  is  not part of the string, nor are any leading blanks
or tabs on the next line. 

The normal escape sequences are permitted in quoted strings.   In
particular,  if  a quote is to be embedded in the string, it must
be escaped, as in

                   "a quote (@") in a string"





























                              -14-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                       CHARACTER LITERALS

Character constants of the form 'c' are converted to the  decimal
integer  representation  of that character in the ASCII character
set.  For example:

          call putc('!')
becomes
          call putc(33)

The standard escape sequences for characters (as  used  in  find,
ch   and   ed)   are  interpreted  within  the  apostrophes.   In
particular, '@n' is NEWLINE, '@t' is  TAB  and  '@@'  is  ATSIGN.
Consult  the  writeup on the find utility for the complete set of
escaped characters. 

Note that this usage pre-empts the use of apostrophes to  delimit
character strings. 


































                              -15-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                             DEFINE

Any  string  of alphanumeric characters can be defined as a name:
thereafter, whenever that name occurs in the input (delimited  by
non-alphanumerics)  it  is replaced by the rest of the definition
line.  The syntax is:

                define(name, replacement string)

which define "name" as  a  macro  which  will  be  replaced  with
"replacement  string" when encountered in the source files.  As a
simple example:

          define(ROW,10)
          define(COLUMN,25)
          
          dimension array (ROW, COLUMN)
and
          
          define(EOF,-1)
          if (getlin(line, fd) == EOF)
              ...
          


Definitions may be included anywhere in  the  code,  as  long  as
they  appear  before the defined name occurs.  The names of macro
may contain letters, digits, and underline characters,  but  must
start  with  a  letter.   Upper  and  lower cases ARE significant
(thus EOF is not the same as eof). 

Any occurrences of the strings  '$n'  in  the  replacement  text,
where  1  <=  n <= 9, will be replaced with the nth argument when
the macro is actually invoked.  For example:

               define(bump, $1 = $1 + 1)

will cause the source line

               bump(i)

to be expanded into

               i = i + 1



In  addition  to  define,  several  other  built-in  macros   are
provided:



                              -16-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


 arith(x,op,y)   performs  the  "integer" arithmetic specified by
                 op (+,-,*,/,**) on the two numeric operands  and
                 returns the result as its replacement. 
 incr(x)         converts  the  string x to a number, adds one to
                 it, and returns the  value  as  its  replacement
                 (as a character string). 
 ifelse(a,b,c,d) compares  a  and b as character strings; if they
                 are the same, c is pushed back onto  the  input,
                 else d is pushed back. 
 substr(s,m,n)   produces  the  substring  of  s  which starts at
                 position m (with origin one), of length  n.   If
                 n  is omitted or too big, the rest of the string
                 is used, while if m is out of range  the  result
                 is a null string. 
lentok(str)      pushes   the   length  of  the  argument  (#  of
                 characters)  onto  the  input  as  a   character
                 string. 
undefine(sym)    removes  the definition for the symbol `sym', if
                 it is defined. 

































                              -17-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                    CONDITIONAL PREPROCESSING

Ratfor source code may be conditionally  preprocessed,  dependent
upon  the  definition  (or lack thereof) of a symbol.  The syntax
is

          ifdef(symbol)                       ifnotdef(symbol)
                .                                   .
                .                                   .
                .                                   .
          elsedef                             elsedef
                .                                   .
                .                                   .
                .                                   .
          enddef                              enddef

Conditionals may be nested to some maximum  level  (usually  10).
An  example  of their use might be an output routine which forces
the output of a characters from a string to uppercase,  depending
upon the definition of a symbol DO_UPPER:

          for (i = 1; buf(i) != EOS; i = i + 1)
              {
              ifdef (DO_UPPER)
                call putc(cupper(buf(i))
              elsedef
                call putc(buf(i))
              enddef
              }























                              -18-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                             INCLUDE

Files  may  be  inserted  into the input stream via the "include"
command.  The statement

          include filename
or
          include "filename"

inserts the file found on input file "filename" into  the  Ratfor
input  in  place  of  the  include  statement.   (Surrounding the
filename  with  quotes  is  required  if  the  filename  contains
characters  other  than letters, digits and underscores.) This is
especially useful in inserting common blocks.  For example,

          function exampl (x)
          
          include comblk
          
          exampl = x + z
          
          return
          end
          
might translate into
          
          function exampl (x)
          
          common /comblk/ q, r, z
          
          exampl = x + z
          
          return
          end
          

















                              -19-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                         IMPLEMENTATION

Ratfor was originally written in C,  a  high-level  language,  on
the  Unix  operating  system.   Our  version is written in Ratfor
itself,  originally  brought  up  by  a  bootstrap   written   in
Fortran. 

Ratfor  generates code by reading input files and translating any
Ratfor keywords into standard Fortran.  Thus, if the first  token
(word)  on  a  source line is not a keyword (like "for", "while",
etc.) the entire statement is simply copied to  the  output  with
appropriate  character  translation and formatting.  Ratfor knows
very little Fortran and thus does not handle  any  Fortran  error
detection.   Errors  in Ratfor keyword syntax are generally noted
by a message to the user's terminal along with an  indication  of
the source line number which caused the problem. 

                           CONCLUSIONS

Ratfor   demonstrates   that  with  modest  effort  Fortran-based
programmers can increase their productivity by using  a  language
that  provides  them  with  the  control  structures and cosmetic
features essential for structured programming design.   Debugging
and   subsequent   revision   times  are  much  faster  than  the
equivalent efforts in Fortran, mainly because  the  code  can  be
easily  read.   Thus  it  becomes  easier  to  write code that is
readable, reliable, and even esthetically pleasing,  as  well  as
being portable to other environments. 
























                              -20-


Ratfor (4)                  4-Apr-78                   Ratfor (4)


                             EXAMPLE

The  following  is  a sample Ratfor tool designed to show some of
the commonly-used Ratfor commands.  The routine reads  through  a
list of files, counting the lines as it goes. 

   # This is an example of a routine written in Ratfor
   # Symbols such as EOF, ERR, MAXLINE, character and filedes are
   # automatically defined (i.e. a file containing them is included)
   # by the preprocessor
   
   ## count - counts lines in files
   DRIVER(count)
   
   include comblk     # this file contains a common block which
                      # contains a variable "linect"
   
   character file(FILENAMESIZE), line(MAXLINE)
   integer i
   filedes fd
   integer getarg, open, getlin
   string total "total lines: "
   
   call query ("usage:  count file.")
   linect = 0
   
   # loop through the list of files
   
   for (i=1; getarg(i, file, FILENAMESIZE) != EOF; i=i+1)
       {
       fd = open (file, READ)          # open (attach) the file
       if (fd == ERR)                  # file could not be located
           call cant (file)
       while (getlin(line, fd) != EOF) # read and count lines
           linect = linect + 1
       call close (fd)                 # close (unattach) the file
       }
   
   call putlin(total, STDOUT)
   call putint (linect, 1, STDOUT)
   call putch ('@n', STDOUT)
   
   DRETURN
   end








                              -21-


Ratfor (4)                  4-Apr-78                   Ratfor (4)



                            SEE ALSO

1)   Kernighan,  Brian W., "Ratfor--a Preprocessor for a Rational
Fortran".   Software  -  Practice  and  Experience,  Vol.  5,   4
(Oct-Dec 75), pp. 395-406. 

2)   Kernighan,  Brian  W.  and  P. J. Plauger, "Software Tools".
Addison-Wesley Publishing Company, Reading, Mass., 1976. 

3)  The ratfor user document

4)  The Unix command "rc" in the Unix Manual (RC(I))







































                              -22-

