Implements a number of reusable components for I/O

Move to top-level taxonomy
Move to keyword list


Woodruff Collection
AR; C1 1.0 B
John P Woodruff
Lawrence Livermore National Laboratory
PO Box 808
Livermore CA 94550
(510) 422 4661
Released to the Ada community; distribution unlimited
Copyright (c) 1987 John Woodruff
19 Dec 1985
13 Nov 1992
13 Jul 1993
Portable with effort to non-DEC environment
Ada System Certifier_1 1.0
Date/Time of Processing: Thursday  02 June      1994 08:23:56Am
Overall Assessment of System: OK
Classification of System: B
Basis of Classification --
Syntax Errors                               PASS
Completeness                                PASS
Independence from External Libraries        PASS
Independence from a Specific Ada Compiler   FAIL

Explanations for failures --
System contains compiler-specific pragmas or uses Machine_Code

Number of ...
Files               3
Library Units      25
Lines            9212
Statements       2526
Comments         3127

Subunits and Parent Units --
1 parent program units
0 missing parent units
1 subunits
0 subunits found but not specified
0 subunits specified but not found


Directory Display

  File Name                 Size
  ---------                 ----
  README                      56
  woodruff.rpt               439
  woodruff.sda             7,969
  woodruff.sdf            43,618            54,875

  ==============  ==============
    5 Files              106,957


Woodruff Collection of Reusable Components for I/O in Ada

The complete list of items being submitted is

1. Set_of
This is an implementation of the generic Set type, patterned after
the Pascal language Set type.

Include the following among the declarations in your package visible part
   With Set_Of;
   Define some enumerated type (the basis type for some set variables) ;
   Package Set_Name is New Set_of (Enumerated_type) ;
Declare instances of the newly instantiated type within the package body:
   Set_Var : Set_Name.Set ;

Derived from Chapter 9.6 of Ada for Experienced Programmers, Habermann
and Chapter 13 of Programming in Ada, Barnes

2. Input_Collection
    Input Collection is a repository of user inputs that are to be
dispensed to individual Objects at the beginning of a simulation run.
The input is obtained from some file(s) and retained in this package 
until called for by some object.
    The collection that this package holds is appropriate for the
input that instances of the generic Name_IO might need.
    The user provides one or more text files structured like >
        <<    Object_Name
              {Any "contents" readable by the Object}
              END     >>
    Case is not significant in Name or in "End".  Each must occupy a
line by itself (no content text on same line).  Optional semicolons
delimiting Name and End are immaterial.
    This package imposes no rules on the content text, except that
blank lines are discarded.  Lines in the input file retain their
identity in the content text, with "ASCII_CR ASCII_LF" at places in
the content where line terminator was found.
    This package collects these, and indexes them by Object_Name.
There is no requirement that Object_Name be unique.  Both Object_name
and END must be on a line by itself;  otherwise there are no rules
imposed by this package about the form of the input file(s), and
the contents are delivered exactly as read from the file  (except 
that blank lines are removed).
    Any client package may call the Get_Contents procedure, citing
some Object_Name and receive the contents text.  If the same Object_name
occurs twice in the input file(s), then successive calls to give_contents
will deliver the inputs in FIFO order.  If no input has been collected
for an Object_name, the exception No_Input_For_Object is raised.
    The Contents that is delivered is a PERSISTENT string_Type.  When
the user has finished with it, s/he should do String_Pkg.Flush (Contents).
(Name_IO does follow this advice.)
    Some users of the input from this package might wish to get contents
during the ELABORATION of the user package.  It may be necessary to 
include Pragma Elaborate (Input_Collection) in the context of such a
package to assure that this package is ready for business when called.
Ref LRM 10.5.
    Procedure Read_Input_Collection is called during the elaboration
of this package body;  it is separately compiled so as to be only
loosely coupled to the body of the package, and could be replaced
by a NULL statement if no elaboration-time input is needed.
    As provided, Read_Input_Collection takes the name of a single file
from the command line (in VMS environment) and stocks its collection
of contents from that file.

3. Polite_IO
    Provide a polite, refined input organ for interactive data input.
The idea for this package comes from the package SafeIO in the Simtel20
repository, by J A Anderson of Texas Instruments.  
  GENERIC Polite_Get interacts with user to obtain a single Item
The type of Item, and a decoder that parses an Item from
an input stream, are provided at instantiation.
  The procedure is polite because it
      Prompts for the value;
      Forgives all errors that Decode declares;
      Raises No-Entry in case the input stream is empty;
      User procedures may implement default value binding.
  For each of integer and long_float types, there are two overloaded
Get procedures;  one prompts and returns the value; and the other
allows the program to offer a default in case the user types no value.
A Menu option returns an upper case  letter which is member of 
the specified set of choices.  Choices are letters in an input string;
For Choices = "" (an empty set of choices), any letter is acceptable.
Cases of the letters are not significant:  neither the case of the
set of choices, nor the case of the user's response affects the menu.
  Aft is a function that yields the number of digits aft of the radix point
that are needed to render just the significant fraction of an input floating
  Give Exp that will be the parameter of Float_Text_IO . Put
Aft (10.001, 0) == 3; Put (10.001, aft=>3, exp=>0) == "10.001"
Aft (10.001, 2) == 4; Put (10.001, aft=>4, exp=>2) == "1.0001E+1"
  Float_Decode is a procedure that adds value to the library GET entry
which decodes a string to a floating number.  The library version recognizes
ONLY numbers formed as Ada literals, viz i.i[Ei] for i an integer.
The float_decode entry here returns a long float value of any of the 
following input notations:
     i.i  |  i.iei  |  i  |  i.  |  .i  |  iEi  |  i.Ei  |  .iei

4. Matrix_IO
  Matrix_IO provides a full set of IO services based on text_io that
can read and write Vectors and Matrices.  The interface entry names and 
parameter signatures exactly duplicate the procedures in long_float_text_io.
  Input is read using the Polite_IO.Float_Decode procedure that 
defines a user-friendly representation for real numbers.  Any of the
following notations return a legal Ada real number for any integer i:
     i.i  |  i.iei  |  i  |  i.  |  .i  |  iEi  |  i.Ei  |  .iei
  This package reads a vector as a sequence of real numbers.  In case 
the parameter WIDTH is non-zero, then every element occupies exactly
WIDTH characters in the input.  In the default case, WIDTH = 0, and
each element is read regardless of its spacing.  When WIDTH = 0 
elements of the vector are optionally delimited by commas.  Individual 
elements may be defaulted by elision: the input stream 1,,,4 results 
in the vector (1.0, 0.0, 0.0, 4.0).
  Rows in a matrix are defined to be vectors separated by line terminators.
The exception Input_Too_Small is raised if too few rows are input to 
a matrix get from a string.
  Additional procedures are included that extend the interactive 
GET procedures found in Polite_IO, including prompting, optional 
default values. ((coupling to optional (vms-specific) Help libraries 
  The function Aft, which computes the number of digits needed to 
represent the significant values of its argument, is provided for 
both vector and matrix types.  

5. Name_IO
  Name_IO implements name-directed input in a generic package.  
The package is able to deliver values bound to variables from an input
stream that looks like:
      A = 1.0 ;               		 a floating scalar
      V := 3, 4, 5 ;				 a three-vector
      Filename => "Test.dat;2" ;		 a string
      Enum  = Users_Enumerated_Constant ;	 Enumeration value
      The format for the input to be parsed is a sequence of
    {   [assignment]  ; }.    
   is any legal Ada identifier.
  The optional [assignment] can be any of "=", ":=", or "=>".  
  Semicolon separators are required between assignments.  
  The form of  is determined by the type of
the variable, and is defined by Polite_IO.Float_Decode for floating
values, and by Matrix_IO.Get for vectors and matrices.
(The semicolon forms a terminator on a string that will be
parsed as a value, without placing any lexical requirement on
value, allowing the generic get_item to deliver an enumerated value.)
  The parameters to be provided at instantiation are an enumerated 
type whose literals are  and an optional Put_Error_Msg for
accepting error data.

                       USAGE  OVERVIEW  
  The package is a FINITE STATE MACHINE which can be used 
successively to recognize different streams of data all with the 
same collection of 's.  The sequence of actions on the state
machine are:
  1) initialize the input data by EITHER
  1a) Accept_Input    called by user to provide a dynamic string
of type String_Pkg.String_Type which is the input to be parsed.
Use this procedure when there is a unique string of input to be
  1b) Acquire_Input   given a Object_Name, this procedure will 
invoke Input_Collection.Get_Contents to get its own dynamic string
of data that are to be parsed.  Use this method when this package
is used in an Object-Oriented program in which arbitrarily many
distinct objects of some type each need the same kind of input.
(There is more discussion of Object-Oriented input further on).
  2) Arbitrarily many calls of Get    called to obtain the 
value that was bound to a particular  in the input;
  3) Forget_Contents  called by user to signal that user has
obtained all the values that s/he intends to obtain.  After 
forgetting, calls to Get raise No_Input until a new call of 
Accept_Input or Acquire_Input has provided a new string.

                       GETTING VALUES  
  Five overloaded calls to Get are provided, for any
of Integer, Long_Float, Vector, Matrix, and String values.
Each is called with a value of Name_Type (which is represented
by a literal that is expected to occur as  in the input).
  There are two ways to use any of the Get procedures 
     (a)      Get (Name => Name_List.A,
                   Item => A ) ;
  Returns a value for the variable A which appeared in the input
as a binding like 'A := 10.3';   If no binding exists in the input,
then raise No_Input.
  Use this way in a program that has default values for some input,
which can be replaced at run time.  Assign the default value of A in
the exception handler for exception No_Input.
     (b)      Get (Name   => Name_List.B,
                   Item   => B,
                   Prompt => "Please give value for B") ;
  Returns the value of B which appeared in the input if the binding
exists, ELSE prompt Standard-Input for a value. 
  Use this way if your program will not run unless user input is
given for some variable.
  The Get which returns string has an additional out parameter, 
Last : Natural, which means the number of characters in the Item 
which were copied from the input.
  This Get resembles Text_IO . Get_Line in its handling of the 
arbitrary length of an input string with a fixed length parameter.
In case Last = Item'Length, successive calls of Get return 
sequential pieces of the input.
  The generic procedure Get_Item may be instantiated with the user's
enumerated type, and calls to the instance will return values of that 
type.  (Get_Item has a distinct name because otherwise it is a homograph
of the Get procedure already defined for Integer.)

                       A SUGGESTION ABOUT NAMES  
  A program that instantiates this package might wish to declare 
          TYPE Input_Names_Type  IS  ( A, B, C ) ;
          A   : Integer ;
      ET CETERA  
  This program is NOT a legal Ada program!  The declaration A  : Integer
is an illegal redeclaration of the enumeral A that occurs in the 
preceeding line.  (ref LRM 8.3(17))
  An acceptable alternative that retains the appearance of the NAME A
in agreement with the VARIABLE A is as follows :
            PACKAGE Name_List IS
                TYPE Input_Names_Type IS ( A, B, C ) ;
            END Name_List ;
            A   : Integer ;
            PACKAGE NIO IS NEW Name_IO  ( 
                Names_Type   => Name_List . Input_Names_Type ) ;
        ET CETERA  -

  This package may be used in conjunction with Package Input_Collection
to acquire input in a program where there are arbitrarily many distinct
objects of some (application defined) type which each need some input.
  Suppose you have an Object_Package with an interface procedure Create
which you call to create an instance of a private type.  You don't know 
a priori how many instances there will be.  Nor do you wish to constrain
how the input will be taken.
  Your Object_Package should instantiate this package with names 
that define the input needed to specify an object of its private type.
  Some part of your program (not necessarily the object package)
calls Input_Collection.Read_File arbitrarily many times to read 
some input files.  (refer to the documentation in Input_Collection).
  Let your Object_Package.Create call Name_IO.Acquire_Input ("OBJECT") 
followed by calls to Get.  The effect of this call to Create will be
to process all the input for "OBJECT" that was in one of the input files.
If you call create repeatedly, it will process successive instances 
of OBJECT that were defined in all the input files that had earlier
been given to Input_Collection.Read_File.
  In case your object_package needs input during ELABORATION, refer
to the notes in Input_Collection about elaboration of that package.
  You may wish to call Set_Object_Instance_Name after a call to 
Acquire_Input.  This will bind an instance name to the error messages
and prompts so the user can know which of several object inputs is
delivering a particular message.    

6. Test_Name_IO
  Demonstrate the ability of Name_IO to obtain each of its input types.

  Note that the file containing this test driver program is paired with
the data file used to drive the test.

The file contains the following files:
  readme.txt -- introduction
  support.src -- pager2 source of support routines from New Abstractions
              -- COMPILE THIS FIRST
  main.src    -- pager2 source of the Woodruff Collection
              -- COMPILE THIS SECOND
  testprog.src -- test program Test_Name_IO
  data.src     -- data file used by Test_Name_IO

 Length  Method   Size  Ratio   Date    Time   CRC-32     Name
 ------  ------   ----  -----   ----    ----   ------     ----
    287  Deflate    165  43%  07-26-93  14:38  00f75b7a   readme.txt
    803  Deflate    367  54%  07-26-93  14:09  f7bbf24d   data.src
 116920  Deflate  24568  79%  07-26-93  14:09  f7fabb53   main.src
 180674  Deflate  27988  85%  07-26-93  14:13  81ac37b6   support.src
   3630  Deflate   1287  65%  07-26-93  14:09  f9ce1d36   testprog.src
 ------          ------  ---                              -------
 302314           54375  82%                              5      


9 Aug 93  Woodruff  Initial release to the PAL


This prologue must be included in all copies of this software.
Restrictions on use or distribution:  NONE

This software was prepared as an account of work sponsored by an agency
of the United States Government.  Neither the United States Government
nor the University of California nor any of their employees makes any
warranty, express or implied, or assumes any liability or responsibility
for the accuracy, completeness, or usefulness of any information


        This software and its documentation are provided "AS IS" and
without any expressed or implied warranties whatsoever.  No warranties
as to performance, merchantability, or fitness for a particular
purpose exist.
        The user is advised to test the software thoroughly before
relying on it.  The user must assume the entire risk and liability of
using this software.  In no event shall any person or organization of
people be held responsible for any direct, indirect, consequential or
inconsequential damages or lost profits.