                        Chapter 8 - Input/Output


                          A SIMPLE OUTPUT PROGRAM

             Load  and  display the file named SIMPLOUT.MOD  for  an
        example  of  the simple output functions.   This program  is
        limited  to writing only to the monitor but we will  get  to
        files  and printer output shortly.   We must first establish
        some basic principles for use with library procedures.

             The  first line of the declaration part of the  program
        imports   our  two  familiar  procedures  "WriteString"  and
        "WriteLn" in the same manner we are used to.   The next line
        imports every procedure in "InOut" and makes them  available
        for  use in the program without specifically naming each one
        in the IMPORT list.   The third line imports every procedure
        from "Terminal" so that they too are available for our  use.
        The  procedures that are imported explicitly can be used  in
        exactly  the  same manner that we have been using  them  all
        along,  simply  name  the procedure with any arguments  they
        use.   The  others can only be used with a "qualifier"  that
        tells which library module they come from.

             An  example is the easiest way to describe their use so
        refer  to  the  program  before  you.    Line  11  uses  the
        explicitly defined procedure from "InOut",  line 12 uses the
        same procedure from "InOut",  and line 15 uses the procedure
        of  the  same  name  from  "Terminal".   Line  11  uses  the
        unqualified procedure call from "InOut", and lines 12 and 15
        use the qualified method of calling the procedures from both
        library modules.

            In this case,  the two procedures do the same thing, but
        it is not required that procedures with the same name do the
        same thing.   By adding the library module name to the front
        of  the procedure name with a period between them,  we  tell
        the system which of the two procedures we wish to  use.   If
        we  tried to explicitly import both "WriteString" procedures
        we would get a compile error,  so this is the way to use the
        same name twice.

                         WHAT IS A LIBRARY MODULE?

             What  I  have  been calling a library  module  is  more
        properly  termed a "module" and is the biggest benefit  that
        Modula-2  enjoys over other programming languages.   This is
        the  quality  that  gives  Modula-2  the  ability  to   have
        separately   compiled  modules,   because  a  module  is   a
        compilation  unit.   When  you  get  to  Part  III  of  this
        tutorial,  you  will  learn how to write  your  own  modules
        containing  your own favorite procedures,  and call them  in
        any  program  in the same manner that you have been  calling
        the procedures provided by your compiler writer.


                                 Page 49









                        Chapter 8 - Input/Output



            None of the procedures you have been importing are  part
        of  the  Modula-2  language,  they  are  extensions  to  the
        language  provided for you by your compiler  writer.   Since
        they  are not standard parts of the language,  they may vary
        from compiler to compiler.  For that reason, I have tried to
        use those defined by Niklaus Wirth in his definition of  the
        language, and no others.

                        STUDY YOUR REFERENCE MANUAL

             This  would  be a good place for you to stop and  spend
        some  time  reading  your reference  manual.   Look  up  the
        section in your manual that is probably called the "Library"
        and read through some of the details given there.   You will
        find  that there are many things listed there that you  will
        not  understand at this point,  but you will also find  many
        things there that you do understand.   Each module will have
        a  number of procedures that are "exported" so that you  can
        "import"  them  and use them.   Each procedure will  have  a
        definition  of  what arguments are required in order to  use
        it.   Most of these definitions should be understandable  to
        you.   One  thing you will find is that only the  "PROCEDURE
        procname;"  is  given  along with the  arguments,  with  the
        actual code of the procedure omitted.   We will study  about
        this  in  "Part III" also.   The part that is shown  is  the
        "DEFINITION   MODULE"   which   only   gives   the   calling
        requirements.  The  "IMPLEMENTATION MODULE" which gives  the
        actual program code of the procedure is usually not given by
        compiler writers.

             As  you  study  the  library  modules,  you  will  find
        procedures  to  handle strings,  variables  and  conversions
        between  the two.   You will find  "mouse"  drivers,  "BIOS"
        calls  to the inner workings of your operating  system,  and
        many other kinds of procedures.  All of these procedures are
        available  for you to use in your programs.   They have been
        written,  debugged,  and  documented  for your use once  you
        learn to use them.   In addition,  you will have the ability
        to add to this list by creating your own modules  containing
        your own procedures.

                       BACK TO THE PROGRAM "SIMPLOUT"

             Notice that in lines 13,  17,  and 22,  three different
        ways  are  used to call "WriteLn",  even  though  there  are
        actually  only  two procedures (that happen to do  the  same
        thing).  A little time spent here will be time well spent in
        preparing  for  the next few programs.   When you think  you
        understand this program, compile and run it.



                                 Page 50









                        Chapter 8 - Input/Output


                    NOW FOR SOME SIMPLE INPUT PROCEDURES

             Load  the  program  named  SIMPLIN.MOD  for  our  first
        example  of a program with some data input  procedures.   In
        every program we have run so far in this tutorial,  all data
        has  been stored right in the program statements.   It would
        be a very sad computer that did not have the ability to read
        variable data in from the keyboard and files.   This program
        is our first that can read from an external device,  and  it
        will be limited to only the keyboard.

             This   program  is  broken  up  into  four  groups   of
        statements,  each  illustrating some aspect of reading  data
        from the keyboard.  This could have been four separate files
        but  it  will  be  easier  to  compile  and  run  one  file.

             Beginning  with  line  14  we have an  example  of  the
        "ReadString"  procedure  which  reads  characters  until  it
        receives  a  space,   a  tab,   a  return,   or  some  other
        nonprintable character.   This loop will read three words on
        one  line,  one  word  on   each  of  three  lines,  or  any
        combination to get three words of groups of printable  ASCII
        characters.   After each word or group is read, it is simply
        "printed" to the monitor for your inspection.

                          ONE CHARACTER AT A TIME

             The  next  group of statements is a loop  in  which  50
        ASCII  characters are read in and immediately echoed out  to
        the  monitor.    It  should  be  evident  to  you  that  the
        characters  are  read  one at a time,  and  since  the  same
        variable is used for each character,  they are not stored or
        saved in any way.   In actual practice, the characters would
        be  stored for whatever purpose you intend to use them  for.
        When you run this part of the program, it will seem like the
        computer  is simply acting like a  word  processor,  echoing
        your  input back to the monitor.

                             ONE LINE AT A TIME

             The next section, beginning in line 32, reads in a full
        line before writing it out to the monitor.   In this program
        we  are introduced to the "EOL" which is a constant  defined
        by the system for our use.  It must be imported from "InOut"
        just like the procedures are,  and it is a constant that  is
        equal  to that ASCII value that is returned when we hit  the
        "return"  key.   It  is therefore equal to  the  End-Of-Line
        character,  and that is how it got its name.   If we compare
        the  input character to it,  we can determine when we get to
        the End-Of-Line.   That is exactly what this loop does.   It
        continues to read characters until we find an EOL,  then  it


                                 Page 51









                        Chapter 8 - Input/Output


        terminates  the  input loop and displays the line  of  data.
        Notice  that  this time we do not simply read the  data  and
        ignore  it but instead add it character by character to  the
        ARRAY  named  "StringOfData".   Of  course,  the  next  time
        through the loop we overwrite it.   The careful student will
        also  notice that,  in line 45 we wrote a zero character  in
        the  character  of the line just past the end of  the  line.
        The  zero  is to indicate the end-of-string for  the  string
        handling  procedures.   This portion of the program is easy,
        but  will require a little time on your part  to  completely
        dissect it.

                     READING IN SOME NUMBERS, CARDINAL

             Beginning in line 51,  we have an example of reading  6
        CARDINAL numbers in a loop.   The procedure "ReadCard" will,
        when  invoked  by your program,  read as many digits as  you
        give it.  When it reads any character other than a 0 through
        9,  it  will terminate and return the number to your calling
        program.   Notice that this time all 6 numbers are read  in,
        stored,  and when all are in,  they are all displayed on one
        line.  This should be easy for you to decipher.

                     COMPILING AND RUNNING THIS PROGRAM

             There  is no program that you have studied here that is
        as important for you to compile and run as this one is.  You
        should  spend  considerable time running  this  program  and
        comparing the results with the listing.   Enter some invalid
        data  when  you are running the "ReadCard" portion of it  to
        see what it does.  When you are running the "line at a time"
        portion, try to enter more than 80 characters to see what it
        will do with it.  This is a good point for you to learn what
        happens when errors occur.   After you understand what  this
        program does, we will proceed to file input and output.

                             FILE INPUT/OUTPUT

             Load  and  display the file named FILEIO.MOD  for  your
        first  file reading and writing.   The library module  named
        "InOut" has the ability to either read and write from/to the
        keyboard  and monitor,  or to read and write from/to  files.
        The  program  before you redirects the input and  output  to
        files for an illustration of how to do it.

             Line 16 requests the operator,  namely you,  to enter a
        filename  to be used for input.   There is nothing different
        about  this statement than the others you have  been  using.
        The  next  line  requests  the system to  open  a  file  for
        inputting, and part of the procedure "OpenInput" is to go to
        the  keyboard waiting for the filename to be typed  in.   So


                                 Page 52









                        Chapter 8 - Input/Output


        the  message  in line 16 is in preparation for what we  know
        will  happen in line 17.   Whatever filename is typed in  is
        opened for reading if it is found on the disk.  The "MOD" in
        the parentheses is a default extension supplied,  (this  can
        be  any extension you desire).   If no extension is supplied
        by  the operator,  and if the filename does not have  a  "."
        following it,  ".MOD" will be added to the filename.  If the
        system can find the requested filename.extension, the "Done"
        flag is made TRUE and we can test it.   In this example,  if
        the flag is returned FALSE, we ask the operator to try again
        until  he  finally  inputs  a filename that  exists  on  the
        default disk/directory.

                         NOW TO OPEN AN OUTPUT FILE

             Once  again,  in  line 21,  we request a  filename  for
        output  anticipating  the operation of the  "OpenOutput"  in
        line  22.   Line 22 waits for a keyboard input of a filename
        and  if the filename entered has no extension,  it adds  the
        extension  ".DOG" and attempts to open the file for  writing.
        When you input the filename,  adding a "." to the end of the
        filename  will prevent the extension being  added.   If  the
        Filename.extension  does not exist,  it will be created  for
        you.  If it does exist, it's contents will be erased.

             It is nearly assured that the file will be created  and
        the  "Done" flag will be supplied as TRUE,  but it would  be
        good practice to check the flag anyway.  It will be apparent
        when  we  get to the program on printer output,  that it  is
        impossible  to  open a file with certain  names,  one  being
        "PRN",   because   the   name  is   reserved   for   printer
        identification and the "Done" flag will be returned FALSE.

                       HOW DO I USE THE OPENED FILES?

             Anytime  you  use  this technique to open  a  file  for
        writing,  any procedure from InOut will now be redirected to
        that  file.   Anytime you use this technique to open a  file
        for  reading,  any procedure from InOut will access the file
        named  instead of the keyboard.   In addition,  the  library
        module  named  "RealInOut"  will  also  be  redirected  with
        "InOut".   Any time you read or write,  instead of using the
        keyboard  and  monitor,  the input and output files will  be
        used.   The  input  and output will be the same  except  for
        where it goes to and comes from,  and it is possible to only
        open one and leave the other intact.  Thus input can be from
        a file, and output can still go to the monitor.

             When  I/O is redirected, the module "Terminal" is  still
        available for use with the monitor and keyboard as I/O using
        this  module  can  not  be  redirected.   The  module  named


                                 Page 53









                        Chapter 8 - Input/Output


        "Terminal" does not have the flexibility of input and output
        that is found in "InOut" so it is a little more difficult to
        use.

          There is a major drawback when using "InOut" with the  I/O
        redirected.   You  are limited to one file for input and one
        file for output at one time.  Finally, this method cannot be
        used  to open a "fixed" or prenamed file,  since  it  always
        surveys  the  keyboard for the filename.   It will  probably
        come  as  no surprise to you that all of  these  limitations
        will  be overcome with another method given in the next  two
        programs.

             The  program itself should be easy to follow,  once you
        realize that the flag named "Done" returns TRUE when a valid
        character  is found following a "Read",  and FALSE  when  an
        End-Of-File  (EOF) is detected.   The "Done" flag is set  up
        following  each  operation so its use is dictated  by  which
        procedure  was called last.   The program simply copies  all
        characters  from one file to another.   When completed,  the
        two  procedures  named "CloseInput"  and  "CloseOutput"  are
        called  to do just that,  to close the files and once  again
        make the I/O available to the keyboard and monitor.  In this
        case,  however, we immediately terminate the program without
        taking advantage of the return to normal.

             Compile and run this program, being careful not to give
        it  the  name  of an existing file for output,  or  it  will
        overwrite  the old data in the file and copy new  data  into
        it.  That is the reason for the extension "DOG".  Few people
        will  have a file with that extension.   For input,  use the
        present  filename (FILEIO.MOD),  for  output,  use  "STUFF",
        "STUFF.",  and  "STUFF.STU",  observing  the  resulting  new
        filename each time.

                          THE COMPLETE FILESYSTEM

             Load  and  display the file named VARYFILE.MOD  for  an
        example  using the complete "FileSystem" module.   As stated
        earlier,  Modula-2  does not have any  input/output  methods
        defined  as part of the language.   This is because the  I/O
        available on computers is so diverse,  there would be no way
        of  defining  a method that could be used on all  computers.
        To  eliminate the problem,  Niklaus Wirth simply defined  no
        I/O  as  part  of the language,  but he did  suggest  a  few
        standard modules to perform the basic I/O tasks.  Since they
        are only suggestions,  compiler writers are not  constrained
        to  follow them,  but in the interest of  portability,  most
        will.   A  very limited subset of all of the procedures  are
        the  only ones that will be used in the tutorial portion  of
        this  course.   (A few other procedures will be used in  the


                                 Page 54









                        Chapter 8 - Input/Output


        example programs given in those chapters.)  It will be up to
        you  to  see  that  the procedures are in  order  with  your
        compiler,  and  where they differ,  to modify them.   A  few
        notes are available for your assistance in the  COMPILER.DOC
        file on your distribution disk for those compilers available
        at the time of release of this tutorial.

                     BACK TO THE PROGRAM NAMED VARYFILE

             This time we IMPORT several procedures from the library
        module named "FileSystem" for I/O use.   This time,  we  ask
        for  the input filename and store it internally in a  string
        variable.  This implies that we can also define the filename
        as  a  constant that is carried in the  program,  making  it
        possible to use a certain preprogrammed filename for  input.
        We  use  the  procedure "Lookup" to  open  the  file.   This
        procedure  uses three arguments within the parentheses,  the
        first  being  the  symbolic filename which is  a  record  of
        information about the file.  (We will come to records later,
        don't  worry too much about it at this point.)   The  second

        argument  is the name of the file on disk we wish to access,
        and  the third argument is a boolean variable  or  constant.
        If it is TRUE, and the file name is not found, a new file of
        that name will be created.   If it is FALSE, and the file is
        not  found,  a new file will not be created,  and the record
        variable  "InFile.res"  will  return  the  value  "notdone".
        (That refers to one variable named "res" which is a part  of
        the record "InFile".)

             Note  that the variable "InFile",  is a record composed
        of many parts, but for the immediate future  we only need to
        be  concerned  with  its definition.   It is  defined  as  a
        variable  of type "File" which is imported from  the  module
        named  "FileSystem".   Until  you study the lesson  in  this
        tutorial  on records,  simply copy the method used here  for
        file Input/Output.

             Once  the  file  is  opened,  you can use  any  of  the
        procedures  included  in  the  "FileSystem"  module,   being
        careful   to  follow  the  rules  given  in   your   library
        documentation.  The remainder of the program should be self-
        explanatory and will be left to your inspection.   With this
        example in hand,  spend some time studying your "FileSystem"
        module to become familiar with it,  then compile the program
        and run it to observe its operation.

                      NOW FOR MULTIPLE FILE OPERATIONS

             Load  and  display the file named PRINTFLE.MOD  for  an
        example program that uses 4 files at once,  and still writes
        to the monitor.  This program is very similar to the last in


                                 Page 55









                        Chapter 8 - Input/Output


        that it opens one file for reading, but it opens three files
        for writing.  Each of the four files has its own identifier,
        a record of type "File", and each has its own filename.  The
        three  output files are firmly fixed to  certain  filenames,
        rather  than  ask  the operator for  names,  and  the  third
        filename is a very special name,  "PRN".  This is not a file
        but is the access to the printer.   Anything written to this
        file  will go to your line printer,  so you should turn your
        printer on in anticipation of running it.  Your compiler may
        also allow a few other names such as  "LPT0",  "LPT1",  etc,
        and there may be other names reserved for serial I/O such as
        to  talk  to a modem,  a joystick,  etc.   You will need  to
        consult  your compiler documentation for a complete list  of
        special names.


             The  program itself is very simple and similar  to  the
        last  one.   A  character is read from the input  file,  and
        output to the three output files and to the monitor.  In the
        case of "CapFile", the character is capitalized before it is
        output  simply to indicate to you that the files are  indeed
        different.   Study it until you understand it,  then compile
        and run it.  Look at the contents of the new files to see if
        they are correct.

                   MORE NEAT THINGS WE CAN DO WITH FILES

             There  are  many more things that you can do  with  the
        "FileSystem" module.   It is possible to open a file,  begin
        reading until you come to a selected position, and change to
        a  write file to overwrite some of the data with  new  data.
        You can write to a file,  change it to a read file, reset it
        to  the  beginning,  and read the data back  out.   You  can
        rename a file,  or delete it.  It will be up to you to study
        the  documentation for your "FileSystem" module,  and  learn
        how to use it effectively.

                   YOU ARE AT A SPECIAL POINT IN MODULA-2

             With  the completion of this chapter,  you have arrived
        at  a very special point in your study  of  Modula-2.   Many
        people arrive at this point in a language and quit studying,
        preferring  to use the language in a somewhat limited  sense
        rather than to go on and learn the advanced topics.  If your
        needs  are few,  you can quit here also and be well  assured
        that  you can write many programs with  Modula-2.   In  fact
        there will be very few times when you cannot do all that you
        wish to do.  However, if you choose to go on to the advanced
        topics,  you  will find that some of the programming  chores
        will be greatly simplified.



                                 Page 56









                        Chapter 8 - Input/Output


             Whether  you decide to go on to the advanced topics  or
        not,  it  would  be wise for you to stop at this  point  and
        begin  using  what you have learned to actually  write  some
        programs  for  your own personal use.   Everybody  has  need
        occasionally for a program to do some sort of translation of
        data in a text file for example.   Write programs to do some
        data shuffling from file to file changing the format in some
        way.   You should be able to think up several programs  that
        you would find useful.

             Spend  some  time studying and running the programs  in
        the  next  chapter,  then modify them to  suit  your  needs,
        building  up  a few utilities for your software  collection.
        The  best way to learn to program is to program.   You  have
        all  of the tools you need to get started,  so you would  do
        well  to  get started.   Adding some programming  experience
        will be a big help if you decide to continue your study into
        the advanced features of Modula-2.



































                                 Page 57
