home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / misc / abstract.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  559.2 KB  |  17,977 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --VMSLIB.SPC
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4.  
  5. package VMS_Lib is
  6.  
  7. ----------------------------------------------------------------
  8.  
  9. procedure Set_Error;
  10.  
  11. ----------------------------------------------------------------
  12.    
  13. procedure get_foreign(
  14.     P : out STRING
  15.     );
  16.         
  17. pragma interface (EXTERNAL,GET_FOREIGN);
  18. pragma IMPORT_VALUED_PROCEDURE(GET_FOREIGN,"LIB$GET_FOREIGN",
  19.     (STRING),
  20.     (DESCRIPTOR(S))
  21.     );
  22.  
  23. ----------------------------------------------------------------    
  24.  
  25. end VMS_Lib;
  26. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  27. --STRING.SPC
  28. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  29. -- $Source: /nosc/work/abstractions/string/RCS/string.spc,v $
  30. -- $Revision: 1.1 $ -- $Date: 85/01/10 17:51:46 $ -- $Author: ron $
  31.  
  32. -- $Source: /nosc/work/abstractions/string/RCS/string.spc,v $
  33. -- $Revision: 1.1 $ -- $Date: 85/01/10 17:51:46 $ -- $Author: ron $
  34.  
  35. package string_pkg is
  36.  
  37. --| Overview:
  38. --| Package string_pkg exports an abstract data type, string_type.  A
  39. --| string_type value is a sequence of characters.  The values have arbitrary
  40. --| length.  For a value, s, with length, l, the individual characters are
  41. --| numbered from 1 to l.  These values are immutable; characters cannot be
  42. --| replaced or appended in a destructive fashion.  
  43. --|
  44. --| In the documentation for this package, we are careful to distinguish 
  45. --| between string_type objects, which are Ada objects in the usual sense, 
  46. --| and string_type values, the members of this data abstraction as described
  47. --| above.  A string_type value is said to be associated with, or bound to,
  48. --| a string_type object after an assignment (:=) operation.  
  49. --| 
  50. --| The operations provided in this package fall into three categories: 
  51. --|
  52. --| 1. Constructors:  These functions typically take one or more string_type
  53. --|      objects as arguments.  They work with the values associated with 
  54. --|      these objects, and return new string_type values according to 
  55. --|      specification.  By a slight abuse of language, we will sometimes 
  56. --|      coerce from string_type objects to values for ease in description.
  57. --|
  58. --| 2. Heap Management:   
  59. --|      These operations (make_persistent, flush, mark, release) control the
  60. --|      management of heap space.  Because string_type values are
  61. --|      allocated on the heap, and the type is not limited, it is necessary
  62. --|      for a user to assume some responsibility for garbage collection.  
  63. --|      String_type is not limited because of the convenience of
  64. --|      the assignment operation, and the usefulness of being able to 
  65. --|      instantiate generic units that contain private type formals.  
  66. --|      ** Important: To use this package properly, it is necessary to read
  67. --|      the descriptions of the operations in this section.
  68. --|
  69. --| 3. Queries:  These functions return information about the values 
  70. --|      that are associated with the argument objects.  The same conventions 
  71. --|      for description of operations used in (1) is adopted.
  72. --| 
  73. --| A note about design decisions...  The decision to not make the type 
  74. --| limited causes two operations to be carried over from the representation.
  75. --| These are the assignment operation, :=, and the "equality" operator, "=".
  76. --| See the discussion at the beginning of the Heap Management section for a 
  77. --| discussion of :=.
  78. --| See the spec for the first of the equal functions for a discussion of "=".
  79. --| 
  80. --| The following is a complete list of operations, written in the order
  81. --| in which they appear in the spec.  Overloaded subprograms are followed
  82. --| by (n), where n is the number of subprograms of that name.
  83. --|
  84. --| 1. Constructors:
  85. --|        create
  86. --|        "&" (3)
  87. --|        substr
  88. --|        splice
  89. --|        insert (3)
  90. --|        lower (2) 
  91. --|        upper (2)
  92. --| 2. Heap Management:
  93. --|        make_persistent (2)
  94. --|        flush
  95. --|        mark, release
  96. --| 3. Queries:
  97. --|        is_empty
  98. --|        length
  99. --|        value
  100. --|        fetch
  101. --|        equal (3)
  102. --|        "<" (3), 
  103. --|       "<=" (3)
  104. --|        match_c
  105. --|        match_not_c
  106. --|        match_s (2)
  107. --|        match_any (2)
  108. --|        match_none (2)
  109.  
  110. --| Notes:
  111. --| Programmer: Ron Kownacki
  112.  
  113.     type string_type is private;
  114.  
  115.     bounds:          exception;  --| Raised on index out of bounds.
  116.     any_empty:       exception;  --| Raised on incorrect use of match_any.
  117.     illegal_alloc:   exception;  --| Raised by value creating operations.
  118.     illegal_dealloc: exception;  --| Raised by release.
  119.     
  120.     
  121. -- Constructors:
  122.  
  123.     function create(s: string)
  124.         return string_type;
  125.  
  126.       --| Raises: illegal_alloc
  127.       --| Effects:
  128.       --| Return a value consisting of the sequence of characters in s.
  129.       --| Sometimes useful for array or record aggregates.
  130.       --| Raises illegal_alloc if string space has been improperly
  131.       --| released.  (See procedures mark/release.)
  132.  
  133.     function "&"(s1, s2: string_type)
  134.         return string_type;
  135.  
  136.       --| Raises: illegal_alloc
  137.       --| Effects:
  138.       --| Return the concatenation of s1 and s2.
  139.       --| Raises illegal_alloc if string space has been improperly
  140.       --| released.  (See procedures mark/release.)
  141.  
  142.     function "&"(s1: string_type; s2: string)
  143.         return string_type;
  144.  
  145.       --| Raises: illegal_alloc
  146.       --| Effects:
  147.       --| Return the concatenation of s1 and create(s2).
  148.       --| Raises illegal_alloc if string space has been improperly
  149.       --| released.  (See procedures mark/release.)
  150.  
  151.     function "&"(s1: string; s2: string_type)
  152.         return string_type;
  153.  
  154.       --| Raises: illegal_alloc
  155.       --| Effects:
  156.       --| Return the concatenation of create(s1) and s2.
  157.       --| Raises illegal_alloc if string space has been improperly
  158.       --| released.  (See procedures mark/release.)
  159.  
  160.     function substr(s: string_type; i: positive; len: natural)
  161.     return string_type;
  162.   
  163.       --| Raises: bounds, illegal_alloc
  164.       --| Effects:
  165.       --| Return the substring, of specified length, that occurs in s at
  166.       --| position i.  If len = 0, then returns the empty value.  
  167.       --| Otherwise, raises bounds if either i or (i + len - 1)
  168.       --| is not in 1..length(s).
  169.       --| Raises illegal_alloc if string space has been improperly
  170.       --| released.  (See procedures mark/release.)
  171.   
  172.     function splice(s: string_type; i: positive; len: natural)
  173.     return string_type;
  174.   
  175.       --| Raises: bounds, illegal_alloc
  176.       --| Effects:
  177.       --| Let s be the string, abc, where a, b and c are substrings.  If
  178.       --| substr(s, i, length(b)) = b, for some i in 1..length(s), then
  179.       --| splice(s, i, length(b)) = ac.  
  180.       --| Returns a value equal to s if len = 0.  Otherwise, raises bounds if
  181.       --| either i or (i + len - 1) is not in 1..length(s).
  182.       --| Raises illegal_alloc if string space has been improperly
  183.       --| released.  (See procedures mark/release.)
  184.   
  185.     function insert(s1, s2: string_type; i: positive)
  186.     return string_type;
  187.   
  188.       --| Raises: bounds, illegal_alloc
  189.       --| Effects:
  190.       --| Return substr(s1, 1, i - 1) & s2 &
  191.       --|        substr(s1, i, length(s1) - i + 1).
  192.       --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  193.       --| exception is raised by insert.
  194.       --| Raises bounds if is_empty(s1) or else i is not in 1..length(s1).
  195.       --| Raises illegal_alloc if string space has been improperly
  196.       --| released.  (See procedures mark/release.)
  197.  
  198.     function insert(s1: string_type; s2: string; i: positive)
  199.     return string_type;
  200.   
  201.       --| Raises: bounds, illegal_alloc
  202.       --| Effects:
  203.       --| Return substr(s1, 1, i - 1) & s2 &
  204.       --|        substr(s1, i, length(s1) - i + 1).
  205.       --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  206.       --| exception is raised by insert.
  207.       --| Raises bounds if is_empty(s1) or else i is not in 1..length(s1).
  208.       --| Raises illegal_alloc if string space has been improperly
  209.       --| released.  (See procedures mark/release.)
  210.       
  211.     function insert(s1: string; s2: string_type; i: positive)
  212.     return string_type;
  213.   
  214.       --| Raises: bounds, illegal_alloc
  215.       --| Effects:
  216.       --| Return s1(s1'first..i - 1) & s2 &
  217.       --|        s1(i..length(s1) - i + 1).
  218.       --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  219.       --| exception is raised by insert.
  220.       --| Raises bounds if i is not in s'range.
  221.       --| Raises illegal_alloc if string space has been improperly
  222.       --| released.  (See procedures mark/release.)
  223.       
  224.     function lower(s: string)
  225.     return string_type;
  226.   
  227.       --| Raises: illegal_alloc
  228.       --| Effects:
  229.       --| Return a value that contains exactly those characters in s with
  230.       --| the exception that all upper case characters are replaced by their 
  231.       --| lower case counterparts.
  232.       --| Raises illegal_alloc if string space has been improperly
  233.       --| released.  (See procedures mark/release.)
  234.  
  235.     function lower(s: string_type)
  236.     return string_type;
  237.   
  238.       --| Raises: illegal_alloc
  239.       --| Effects:
  240.       --| Return a value that is a copy of s with the exception that all
  241.       --| upper case characters are replaced by their lower case counterparts.
  242.       --| Raises illegal_alloc if string space has been improperly
  243.       --| released.  (See procedures mark/release.)
  244.  
  245.     function upper(s: string)
  246.     return string_type;
  247.   
  248.       --| Raises: illegal_alloc
  249.       --| Effects:
  250.       --| Return a value that contains exactly those characters in s with
  251.       --| the exception that all lower case characters are replaced by their 
  252.       --| upper case counterparts.
  253.       --| Raises illegal_alloc if string space has been improperly
  254.       --| released.  (See procedures mark/release.)
  255.  
  256.     function upper(s: string_type)
  257.     return string_type;
  258.   
  259.       --| Raises: illegal_alloc
  260.       --| Effects:
  261.       --| Return a value that is a copy of s with the exception that all
  262.       --| lower case characters are replaced by their upper case counterparts.
  263.       --| Raises illegal_alloc if string space has been improperly
  264.       --| released.  (See procedures mark/release.)
  265.       
  266.  
  267. -- Heap Management (including object/value binding):
  268. --
  269. -- Two forms of heap management are provided.  The general scheme is to "mark"
  270. -- the current state of heap usage, and to "release" in order to reclaim all
  271. -- space that has been used since the last mark.  However, this alone is 
  272. -- insufficient because it is frequently desirable for objects to remain 
  273. -- associated with values for longer periods of time, and this may come into 
  274. -- conflict with the need to clean up after a period of "string hacking."
  275. -- To deal with this problem, we introduce the notions of "persistent" and
  276. -- "nonpersistent" values.
  277. --
  278. -- The nonpersistent values are those that are generated by the constructors 
  279. -- in the previous section.  These are claimed by the release procedure.
  280. -- Persistent values are generated by the two make_persistent functions
  281. -- described below.  These values must be disposed of individually by means of
  282. -- the flush procedure.  
  283. --
  284. -- This allows a description of the meaning of the ":=" operation.  For a 
  285. -- statement of the form, s := expr, where expr is a string_type expression, 
  286. -- the result is that the value denoted/created by expr becomes bound to the
  287. -- the object, s.  Assignment in no way affects the persistence of the value.
  288. -- If expr happens to be an object, then the value associated  with it will be
  289. -- shared.  Ideally, this sharing would not be visible, since values are
  290. -- immutable.  However, the sharing may be visible because of the memory
  291. -- management, as described below.  Programs which depend on such sharing are 
  292. -- erroneous.
  293.    
  294.     function make_persistent(s: string_type) 
  295.     return string_type; 
  296.  
  297.       --| Effects: 
  298.       --| Returns a persistent value, v, containing exactly those characters in
  299.       --| value(s).  The value v will not be claimed by any subsequent release.
  300.       --| Only an invocation of flush will claim v.  After such a claiming
  301.       --| invocation of flush, the use (other than :=) of any other object to 
  302.       --| which v was bound is erroneous, and program_error may be raised for
  303.       --| such a use.
  304.  
  305.     function make_persistent(s: string) 
  306.     return string_type; 
  307.  
  308.       --| Effects: 
  309.       --| Returns a persistent value, v, containing exactly those chars in s.
  310.       --| The value v will not be claimed by any subsequent release.
  311.       --| Only an invocation of flush will reclaim v.  After such a claiming
  312.       --| invocation of flush, the use (other than :=) of any other object to 
  313.       --| which v was bound is erroneous, and program_error may be raised for
  314.       --| such a use.
  315.     
  316.     procedure flush(s: in out string_type);
  317.     
  318.       --| Effects:
  319.       --| Return heap space used by the value associated with s, if any, to 
  320.       --| the heap.  s becomes associated with the empty value.  After an
  321.       --| invocation of flush claims the value, v, then any use (other than :=)
  322.       --| of an object to which v was bound is erroneous, and program_error 
  323.       --| may be raised for such a use.
  324.       --| 
  325.       --| This operation should be used only for persistent values.  The mark 
  326.       --| and release operations are used to deallocate space consumed by other
  327.       --| values.  For example, flushing a nonpersistent value implies that a
  328.       --| release that tries to claim this value will be erroneous, and
  329.       --| program_error may be raised for such a use.
  330.  
  331.     procedure mark;
  332.  
  333.       --| Effects:
  334.       --| Marks the current state of heap usage for use by release.  
  335.       --| An implicit mark is performed at the beginning of program execution.
  336.  
  337.     procedure release;
  338.  
  339.       --| Raises: illegal_dealloc
  340.       --| Effects:
  341.       --| Releases all heap space used by nonpersistent values that have been
  342.       --| allocated since the last mark.  The values that are claimed include
  343.       --| those bound to objects as well as those produced and discarded during
  344.       --| the course of general "string hacking."  If an invocation of release
  345.       --| claims a value, v, then any subsequent use (other than :=) of any 
  346.       --| other object to which v is bound is erroneous, and program_error may
  347.       --| be raised for such a use.
  348.       --|
  349.       --| Raises illegal_dealloc if the invocation of release does not balance
  350.       --| an invocation of mark.  It is permissible to match the implicit
  351.       --| initial invocation of mark.  However, subsequent invocations of 
  352.       --| constructors will raise the illegal_alloc exception until an 
  353.       --| additional mark is performed.  (Anyway, there is no good reason to 
  354.       --| do this.)  In any case, a number of releases matching the number of
  355.       --| currently active marks is implicitly performed at the end of program
  356.       --| execution.
  357.       --|
  358.       --| Good citizens generally perform their own marks and releases
  359.       --| explicitly.  Extensive string hacking without cleaning up will 
  360.       --| cause your program to run very slowly, since the heap manager will
  361.       --| be forced to look hard for chunks of space to allocate.
  362.       
  363. -- Queries:
  364.       
  365.     function is_empty(s: string_type)
  366.         return boolean;
  367.  
  368.       --| Effects:
  369.       --| Return true iff s is the empty sequence of characters.
  370.  
  371.     function length(s: string_type)
  372.         return natural;
  373.  
  374.       --| Effects:
  375.       --| Return number of characters in s.
  376.  
  377.     function value(s: string_type)
  378.         return string;
  379.  
  380.       --| Effects:
  381.       --| Return a string, s2, that contains the same characters that s
  382.       --| contains.  The properties, s2'first = 1 and s2'last = length(s),
  383.       --| are satisfied.  This implies that, for a given string, s3,
  384.       --| value(create(s3))'first may not equal s3'first, even though
  385.       --| value(create(s3)) = s3 holds.  Thus, "content equality" applies
  386.       --| although the string objects may be distinguished by the use of
  387.       --| the array attributes.
  388.  
  389.     function fetch(s: string_type; i: positive)
  390.         return character;
  391.  
  392.       --| Raises: bounds
  393.       --| Effects:
  394.       --| Return the ith character in s.  Characters are numbered from
  395.       --| 1 to length(s).  Raises bounds if i not in 1..length(s).
  396.  
  397.     function equal(s1, s2: string_type)
  398.         return boolean;
  399.  
  400.       --| Effects:
  401.       --| Value equality relation; return true iff length(s1) = length(s2) 
  402.       --| and, for all i in 1..length(s1), fetch(s1, i) = fetch(s2, i).
  403.       --| The "=" operation is carried over from the representation.
  404.       --| It allows one to distinguish among the heap addresses of
  405.       --| string_type values.  Even "equal" values may not be "=", although
  406.       --| s1 = s2 implies equal(s1, s2).  
  407.       --| There is no reason to use "=".
  408.  
  409.     function equal(s1: string_type; s2: string)
  410.         return boolean;
  411.  
  412.       --| Effects:
  413.       --| Return equal(s1, create(s2)).
  414.  
  415.     function equal(s1: string; s2: string_type)
  416.         return boolean;
  417.  
  418.       --| Effects:
  419.       --| Return equal(create(s1), s2).
  420.  
  421.     function "<"(s1: string_type; s2: string_type)
  422.         return boolean; 
  423.  
  424.       --| Effects: 
  425.       --| Lexicographic comparison; return value(s1) < value(s2).
  426.  
  427.     function "<"(s1: string_type; s2: string)
  428.         return boolean; 
  429.  
  430.       --| Effects: 
  431.       --| Lexicographic comparison; return value(s1) < s2.
  432.  
  433.     function "<"(s1: string; s2: string_type)
  434.         return boolean; 
  435.  
  436.       --| Effects: 
  437.       --| Lexicographic comparison; return s1 < value(s2).
  438.  
  439.     function "<="(s1: string_type; s2: string_type)
  440.         return boolean; 
  441.  
  442.       --| Effects: 
  443.       --| Lexicographic comparison; return value(s1) <= value(s2).
  444.  
  445.     function "<="(s1: string_type; s2: string)
  446.         return boolean; 
  447.  
  448.       --| Effects: 
  449.       --| Lexicographic comparison; return value(s1) <= s2.
  450.  
  451.     function "<="(s1: string; s2: string_type)
  452.         return boolean; 
  453.  
  454.       --| Effects: 
  455.       --| Lexicographic comparison; return s1 <= value(s2).
  456.  
  457.     function match_c(s: string_type; c: character; start: positive := 1)
  458.         return natural;
  459.  
  460.       --| Raises: no_match
  461.       --| Effects:
  462.       --| Return the minimum index, i in start..length(s), such that
  463.       --| fetch(s, i) = c.  Returns 0 if no such i exists, 
  464.       --| including the case where is_empty(s).
  465.  
  466.     function match_not_c(s: string_type; c: character; start: positive := 1)
  467.         return natural;
  468.   
  469.       --| Raises: no_match
  470.       --| Effects:
  471.       --| Return the minimum index, i in start..length(s), such that
  472.       --| fetch(s, i) /= c.  Returns 0 if no such i exists,
  473.       --| including the case where is_empty(s).
  474.  
  475.     function match_s(s1, s2: string_type; start: positive := 1)
  476.         return natural;
  477.  
  478.       --| Raises: no_match.
  479.       --| Effects:
  480.       --| Return the minimum index, i, in start..length(s1), such that,
  481.       --| for all j in 1..length(s2), fetch(s2, j) = fetch(s1, i + j - 1).
  482.       --| This is the position of the substring, s2, in s1.
  483.       --| Returns 0 if no such i exists, including the cases
  484.       --| where is_empty(s1) or is_empty(s2).
  485.       --| Note that equal(substr(s1, match_s(s1, s2, i), length(s2)), s2)
  486.       --| holds, providing that match_s does not raise an exception.
  487.  
  488.     function match_s(s1: string_type; s2: string; start: positive := 1)
  489.         return natural;
  490.  
  491.       --| Raises: no_match.
  492.       --| Effects:
  493.       --| Return the minimum index, i, in start..length(s1), such that,
  494.       --| for all j in s2'range, s2(j) = fetch(s1, i + j - 1).
  495.       --| This is the position of the substring, s2, in s1.
  496.       --| Returns 0 if no such i exists, including the cases
  497.       --| where is_empty(s1) or s2 = "".
  498.       --| Note that equal(substr(s1, match_s(s1, s2, i), s2'length), s2)
  499.       --| holds, providing that match_s does not raise an exception.
  500.  
  501.     function match_any(s, any: string_type; start: positive := 1)
  502.         return natural;
  503.  
  504.       --| Raises: no_match, any_empty
  505.       --| Effects:
  506.       --| Return the minimum index, i in start..length(s), such that
  507.       --| fetch(s, i) = fetch(any, j), for some j in 1..length(any).
  508.       --| Raises any_empty if is_empty(any).
  509.       --| Otherwise, returns 0 if no such i exists, including the case
  510.       --| where is_empty(s).
  511.  
  512.  
  513.     function match_any(s: string_type; any: string; start: positive := 1)
  514.         return natural;
  515.  
  516.       --| Raises: no_match, any_empty
  517.       --| Effects:
  518.       --| Return the minimum index, i, in start..length(s), such that
  519.       --| fetch(s, i) = any(j), for some j in any'range.
  520.       --| Raises any_empty if any = "".
  521.       --| Otherwise, returns 0 if no such i exists, including the case
  522.       --| where is_empty(s).
  523.  
  524.     function match_none(s, none: string_type; start: positive := 1)
  525.         return natural;
  526.  
  527.       --| Raises: no_match
  528.       --| Effects:
  529.       --| Return the minimum index, i in start..length(s), such that
  530.       --| fetch(s, i) /= fetch(none, j) for each j in 1..length(none).
  531.       --| If (not is_empty(s)) and is_empty(none), then i is 1.
  532.       --| Returns 0 if no such i exists, including the case
  533.       --| where is_empty(s).
  534.  
  535.     function match_none(s: string_type; none: string; start: positive := 1)
  536.         return natural;
  537.  
  538.       --| Raises: no_match.
  539.       --| Effects:
  540.       --| Return the minimum index, i in start..length(s), such that
  541.       --| fetch(s, i) /= none(j) for each j in none'range.
  542.       --| If not is_empty(s) and none = "", then i is 1.
  543.       --| Returns 0 if no such i exists, including the case
  544.       --| where is_empty(s).
  545.  
  546.  
  547. private
  548.  
  549.     type string_type is access string;
  550.  
  551.       --| Abstract data type, string_type, is a constant sequence of chars
  552.       --| of arbitrary length.  Representation type is access string.
  553.       --| It is important to distinguish between an object of the rep type
  554.       --| and its value; for an object, r, val(r) denotes the value.
  555.       --|
  556.       --| Representation Invariant:  I: rep --> boolean
  557.       --| I(r: rep) = (val(r) = null) or else
  558.       --|             (val(r).all'first = 1 &
  559.       --|              val(r).all'last >= 0 &
  560.       --|              (for all r2, val(r) = val(r2) /= null => r is r2))
  561.       --|
  562.       --| Abstraction Function:  A: rep --> string_type
  563.       --| A(r: rep) = if r = null then
  564.       --|                 the empty sequence
  565.       --|             elsif r'last = 0 then  
  566.       --|                 the empty sequence
  567.       --|             else
  568.       --|                 the sequence consisting of r(1),...,r(r'last).
  569.  
  570. end string_pkg;
  571.  
  572. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  573. --SCANNER.SPC
  574. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  575. with String_Pkg;            use String_Pkg;
  576.  
  577. package String_Scanner is
  578.  
  579. --| Functions for scanning tokens from strings.
  580.                                                     pragma Page;
  581. --| Overview
  582. --| This package provides a set of functions used to scan tokens from
  583. --| strings.  After the function make_Scanner is called to convert a string
  584. --| into a string Scanner, the following functions may be called to scan
  585. --| various tokens from the string:
  586. --|-
  587. --| Make_Scanner    Given a string returns a Scanner
  588. --| Destroy_Scanner    Free storage used by Scanner
  589. --| More        Return TRUE iff unscanned characters remain
  590. --| Forward             Bump the Scanner
  591. --| Backward        Bump back the Scanner
  592. --| Get            Return character 
  593. --| Next        Return character and bump the Scanner
  594. --| Get_String        Return String_Type in Scanner
  595. --| Get_Remainder    Return String_Type in Scanner from current Index
  596. --| Mark        Mark the current Index for Restore 
  597. --| Restore        Restore the previously marked Index
  598. --| Position        Return the current position of the Scanner
  599. --| Is_Word        Return TRUE iff Scanner is at a non-blank character
  600. --| Scan_Word        Return sequence of non blank characters
  601. --| Is_Number        Return TRUE iff Scanner is at a digit
  602. --| Scan_Number (2)    Return sequence of decimal digits
  603. --| Is_Signed_Number    Return TRUE iff Scanner is at a digit or sign
  604. --| Scan_Signed_Number (2)
  605. --|            sequence of decimal digits with optional sign (+/-)
  606. --| Is_Space        Return TRUE iff Scanner is at a space or tab
  607. --| Scan_Space        Return sequence of spaces or tabs
  608. --| Skip_Space        Advance Scanner past white space
  609. --| Is_Ada_Id        Return TRUE iff Scanner is at first character of ada id
  610. --| Scan_Ada_Id        Scan an Ada identifier
  611. --| Is_Quoted        Return TRUE iff Scanner is at a double quote
  612. --| Scan_Quoted        Scan quoted string, embedded quotes doubled
  613. --| Is_Enclosed        Return TRUE iff Scanner is at an enclosing character
  614. --| Scan_Enclosed    Scan enclosed string, embedded enclosing character doubled
  615. --| Is_Sequence        Return TRUE iff Scanner is at some character in sequence
  616. --| Scan_Sequence    Scan user specified sequence of chars
  617. --| Is_Not_Sequence    Return TRUE iff Scanner is not at the characters in sequence
  618. --| Scan_Not_Sequence    Scan string up to but not including a given sequence of chars
  619. --| Is_Literal            Return TRUE iff Scanner is at literal
  620. --| Scan_Literal    Scan user specified literal
  621. --| Is_Not_Literal    Return TRUE iff Scanner is not a given literal
  622. --| Scan_Not_Literal    Scan string up to but not including a given literal
  623. --|+
  624.  
  625. ----------------------------------------------------------------
  626.  
  627. Out_Of_Bounds : exception;    --| Raised when a operation is attempted on a
  628.                 --| Scanner that has passed the end
  629. Scanner_Already_Marked : exception;
  630.                 --| Raised when a Mark is attemped on a Scanner
  631.                 --| that has already been marked
  632.  
  633. ----------------------------------------------------------------
  634.  
  635. type Scanner is private;    --| Scanner type
  636.  
  637. ----------------------------------------------------------------
  638.                                                     pragma Page;
  639. function Make_Scanner(        --| Construct a Scanner from S.
  640.     S : in String_Type        --| String to be scanned.
  641.     ) return Scanner;
  642.  
  643. --| Effects: Construct a Scanner from S.
  644. --| N/A: Raises, Modifies, Errors
  645.  
  646. ----------------------------------------------------------------
  647.  
  648. procedure Destroy_Scanner(    --| Free Scanner storage
  649.     T : in out Scanner        --| Scanner to be freed
  650.     );
  651.  
  652. --| Effects: Free space occupied by the Scanner.
  653. --| N/A: Raises, Modifies, Errors
  654.  
  655. ----------------------------------------------------------------
  656.  
  657. function More(            --| Check if Scanner is exhausted
  658.     T : in Scanner        --| Scanner to check
  659.     ) return boolean;
  660.  
  661. --| Effects: Return TRUE iff additional characters remain to be scanned.
  662. --| N/A: Raises, Modifies, Errors
  663.  
  664. ----------------------------------------------------------------
  665.  
  666. procedure Forward(        --| Bump scanner
  667.     T : in Scanner        --| Scanner
  668.     );
  669.  
  670. --| Effects: Update the scanner position.
  671. --| N/A: Raises, Modifies, Errors
  672.  
  673. ----------------------------------------------------------------
  674.  
  675. procedure Backward(        --| Bump back scanner
  676.     T : in Scanner        --| Scanner
  677.     );
  678.  
  679. --| Effects: Update the scanner position.
  680. --| N/A: Raises, Modifies, Errors
  681.  
  682. ----------------------------------------------------------------
  683.  
  684. function Get(            --| Return character
  685.     T : in     Scanner        --| Scanner to check
  686.     ) return character;
  687.  
  688. --| Raises: Out_Of_Bounds
  689. --| Effects: Return character at the current Scanner position.
  690. --| The scanner position remains unchanged.
  691. --| N/A: Modifies, Errors
  692.  
  693. ----------------------------------------------------------------
  694.  
  695. procedure Next(            --| Return character and bump scanner
  696.     T : in     Scanner;        --| Scanner to check
  697.     C :    out character    --| Character to be returned
  698.     );
  699.  
  700. --| Raises: Out_Of_Bounds
  701. --| Effects: Return character at the current Scanner position and update
  702. --| the position.
  703. --| N/A: Modifies, Errors
  704.  
  705. ----------------------------------------------------------------
  706.  
  707. function Position(        --| Return current Scanner position
  708.     T : in Scanner        --| Scanner to check
  709.     ) return positive;
  710.  
  711. --| Raises: Out_Of_Bounds
  712. --| Effects: Return a positive integer indicating the current Scanner position,
  713. --| N/A: Modifies, Errors
  714.  
  715. ----------------------------------------------------------------
  716.  
  717. function Get_String(        --| Return contents of Scanner
  718.     T : in Scanner        --| Scanner
  719.     ) return String_Type;
  720.  
  721. --| Effects: Return a String_Type corresponding to the contents of the Scanner
  722. --| N/A: Raises, Modifies, Errors
  723.  
  724. ----------------------------------------------------------------
  725.  
  726. function Get_Remainder(        --| Return contents of Scanner from index
  727.     T : in Scanner
  728.     ) return String_Type;
  729.  
  730. --| Effects: Return a String_Type starting at the current index of the Scanner
  731. --| N/A: Raises, Modifies, Errors
  732.  
  733. ----------------------------------------------------------------
  734.  
  735. procedure Mark(
  736.     T : in Scanner
  737.     );
  738.  
  739. --| Raises: Scanner_Already_Marked
  740. --| Effects: Mark the current index for possible future use
  741. --| N/A: Modifies, Errors
  742.  
  743. ----------------------------------------------------------------
  744.  
  745. procedure Restore(
  746.     T : in Scanner
  747.     );
  748.  
  749. --| Effects: Restore the index to the previously marked value
  750. --| N/A: Raises, Modifies, Errors
  751.  
  752. ----------------------------------------------------------------
  753.  
  754.                                                     pragma Page;
  755. function Is_Word(        --| Check if Scanner is at the start of a word.
  756.     T : in Scanner        --| Scanner to check
  757.     ) return boolean;
  758.  
  759. --| Effects: Return TRUE iff Scanner is at the start of a word.
  760. --| N/A: Raises, Modifies, Errors
  761.  
  762. ----------------------------------------------------------------
  763.  
  764. procedure Scan_word(        --| Scan sequence of non blank characters
  765.     T      : in     Scanner;    --| String to be scanned
  766.     Found  :    out boolean;    --| TRUE iff a word found
  767.     Result :    out String_Type;--| Word scanned from string
  768.     Skip   : in     boolean := false
  769.                 --| Skip white spaces before scan
  770.     );
  771.  
  772. --| Effects: Scan T for a sequence of non blank 
  773. --| characters.  If at least one is found, return Found => TRUE, 
  774. --| Result => <the characters>.
  775. --| Otherwise return Found => FALSE and Result is unpredictable.
  776.  
  777. --| N/A: Raises, Modifies, Errors
  778.                                                     pragma Page;
  779. function Is_Number(        --| Return TRUE iff Scanner is at a decimal digit
  780.     T : in Scanner        --| The string being scanned
  781.     ) return boolean;
  782.  
  783. --| Effects: Return TRUE iff Scan_Number would return a non-null string.
  784. --| N/A: Raises, Modifies, Errors
  785.  
  786. ----------------------------------------------------------------
  787.  
  788. procedure Scan_Number(        --| Scan sequence of digits
  789.     T      : in     Scanner;    --| String to be scanned
  790.     Found  :    out boolean;    --| TRUE iff one or more digits found
  791.     Result :    out String_Type;--| Number scanned from string
  792.     Skip   : in     boolean := false
  793.                 --| Skip white spaces before scan
  794.     );
  795.  
  796. --| Effects: Scan T for a sequence of digits.
  797. --| If at least one is found, return Found => TRUE, Result => <the digits>.
  798. --| Otherwise return Found => FALSE and Result is unpredictable.
  799.  
  800. --| Modifies: Raises, Modifies, Errors
  801.  
  802. ----------------------------------------------------------------
  803.  
  804. procedure Scan_Number(        --| Scan sequence of digits
  805.     T      : in     Scanner;    --| String to be scanned
  806.     Found  :    out boolean;    --| TRUE iff one or more digits found
  807.     Result :    out integer;    --| Number scanned from string
  808.     Skip   : in     boolean := false
  809.                 --| Skip white spaces before scan
  810.     );
  811.  
  812. --| Effects: Scan T for a sequence of digits.
  813. --| If at least one is found, return Found => TRUE, Result => <the digits>.
  814. --| Otherwise return Found => FALSE and Result is unpredictable.
  815.  
  816. --| Modifies: Raises, Modifies, Errors
  817.                                                     pragma Page;
  818. function Is_Signed_Number(    --| Check if Scanner is at a decimal digit or
  819.                 --| sign (+/-)
  820.     T : in Scanner        --| The string being scanned
  821.     ) return boolean;
  822.  
  823. --| Effects: Return TRUE iff Scan_Signed_Number would return a non-null
  824. --| string.
  825.  
  826. --| N/A: Raises, Modifies, Errors
  827.  
  828. ----------------------------------------------------------------
  829.  
  830. procedure Scan_Signed_Number(    --| Scan signed sequence of digits 
  831.     T      : in     Scanner;    --| String to be scanned
  832.     Found  :    out boolean;    --| TRUE iff one or more digits found
  833.     Result :    out String_Type;--| Number scanned from string
  834.     Skip   : in     boolean := false
  835.                 --| Skip white spaces before scan
  836.     );
  837.  
  838. --| Effects: Scan T for a sequence of digits preceeded with optional sign.
  839. --| If at least one digit is found, return Found => TRUE, 
  840. --| Result => <the digits>.
  841. --| Otherwise return Found => FALSE and Result is unpredictable.
  842.  
  843. --| Modifies: Raises, Modifies, Errors
  844.  
  845. ----------------------------------------------------------------
  846.  
  847. procedure Scan_Signed_Number(    --| Scan signed sequence of digits 
  848.     T      : in     Scanner;    --| String to be scanned
  849.     Found  :    out boolean;    --| TRUE iff one or more digits found
  850.     Result :    out integer;    --| Number scanned from string
  851.     Skip   : in     boolean := false
  852.                 --| Skip white spaces before scan
  853.     );
  854.  
  855. --| Effects: Scan T for a sequence of digits preceeded with optional sign.
  856. --| If at least one digit is found, return Found => TRUE, 
  857. --| Result => <the digits>.
  858. --| Otherwise return Found => FALSE and Result is unpredictable.
  859.  
  860. --| Modifies: Raises, Modifies, Errors
  861.                                                     pragma Page;
  862. function Is_Space(        --| Check if T is at a space or tab
  863.     T : in Scanner        --| The string being scanned
  864.     ) return boolean;
  865.  
  866. --| Effects: Return TRUE iff Scan_Space would return a non-null string.
  867. --| Modifies: Raises, Modifies, Errors
  868.  
  869. ----------------------------------------------------------------
  870.  
  871. procedure Scan_Space(        --| Scan sequence of white space characters
  872.     T      : in     Scanner;    --| String to be scanned
  873.     Found  :    out boolean;    --| TRUE iff space found
  874.     Result :    out String_Type    --| Spaces scanned from string
  875.     );
  876.  
  877. --| Effects: Scan T past all white space (spaces
  878. --| and tabs.  If at least one is found, return Found => TRUE,
  879. --| Result => <the characters>.
  880. --| Otherwise return Found => FALSE and Result is unpredictable.
  881.  
  882. --| Modifies: Raises, Modifies, Errors
  883.  
  884. ----------------------------------------------------------------
  885.  
  886. procedure Skip_Space(        --| Skip white space
  887.     T : in Scanner        --| String to be scanned
  888.     );
  889.  
  890. --| Effects: Scan T past all white space (spaces and tabs).  
  891. --| Modifies: Raises, Modifies, Errors
  892.                                                     pragma Page;
  893. function Is_Ada_Id(        --| Check if T is at an Ada identifier
  894.     T : in Scanner        --| The string being scanned
  895.     ) return boolean;
  896.  
  897. --| Effects: Return TRUE iff Scan_Ada_Id would return a non-null string.
  898. --| Modifies: Raises, Modifies, Errors
  899.  
  900. ----------------------------------------------------------------
  901.  
  902. procedure Scan_Ada_Id(        --| Scan Ada identifier
  903.     T      : in     Scanner;    --| String to be scanned
  904.     Found  :    out boolean;    --| TRUE iff an Ada identifier found
  905.     Result :    out String_Type;--| Identifier scanned from string
  906.     Skip   : in     boolean := false
  907.                 --| Skip white spaces before scan
  908.     );
  909.  
  910. --| Effects: Scan T for a valid Ada identifier.
  911. --| If one is found, return Found => TRUE, Result => <the characters>.
  912. --| Otherwise return Found => FALSE and Result is unpredictable.
  913.  
  914. --| Modifies: Raises, Modifies, Errors
  915.                                                     pragma Page;
  916. function Is_Quoted(        --| Check if T is at a double quote
  917.     T : in Scanner        --| The string being scanned
  918.     ) return boolean;
  919.  
  920. --| Effects: Return TRUE iff T is at a quoted string (eg. ... "Hello" ...).
  921. --| Modifies: Raises, Modifies, Errors
  922.  
  923. ----------------------------------------------------------------
  924.  
  925. procedure Scan_Quoted(        --| Scan a quoted string
  926.     T      : in     Scanner;    --| String to be scanned
  927.     Found  :    out boolean;    --| TRUE iff a quoted string found
  928.     Result :    out String_Type;--| Quoted string scanned from string
  929.     Skip   : in     boolean := false
  930.                 --| Skip white spaces before scan
  931.     );
  932.  
  933. --| Effects: Scan at T for an opening quote
  934. --| followed by a sequence of characters and ending with a closing
  935. --| quote.  If successful, return Found => TRUE, Result => <the characters>.
  936. --| Otherwise return Found => FALSE and Result is unpredictable.
  937. --| A pair of quotes within the quoted string is converted to a single quote.
  938. --| The outer quotes are stripped. 
  939.  
  940. --| Modifies: Raises, Modifies, Errors
  941.                                                     pragma Page;
  942. function Is_Enclosed(        --| Check if T is at an enclosing character
  943.     B : in character;        --| Enclosing open character
  944.     E : in character;        --| Enclosing close character
  945.     T : in Scanner        --| The string being scanned
  946.     ) return boolean;
  947.  
  948. --| Effects: Return TRUE iff T as encosed by B and E (eg. ... [ABC] ...).
  949. --| Modifies: Raises, Modifies, Errors
  950.  
  951. ----------------------------------------------------------------
  952.  
  953. procedure Scan_Enclosed(    --| Scan an enclosed string
  954.     B      : in character;    --| Enclosing open character
  955.     E      : in character;    --| Enclosing close character
  956.     T      : in     Scanner;    --| String to be scanned
  957.     Found  :    out boolean;    --| TRUE iff a quoted string found
  958.     Result :    out String_Type;--| Quoted string scanned from string
  959.     Skip   : in     boolean := false
  960.                 --| Skip white spaces before scan
  961.     );
  962.  
  963. --| Effects: Scan at T for an enclosing character
  964. --| followed by a sequence of characters and ending with an enclosing character.
  965. --| If successful, return Found => TRUE, Result => <the characters>.
  966. --| Otherwise return Found => FALSE and Result is unpredictable.
  967. --| The enclosing characters are stripped. 
  968.  
  969. --| Modifies: Raises, Modifies, Errors
  970.                                                     pragma Page;
  971. function Is_Sequence(        --| Check if T is at some sequence characters 
  972.     Chars : in String_Type;    --| Characters to be scanned
  973.     T     : in Scanner        --| The string being scanned
  974.     ) return boolean;
  975.  
  976. --| Effects: Return TRUE iff T is at some character of Chars.
  977. --| Modifies: Raises, Modifies, Errors
  978.  
  979. ----------------------------------------------------------------
  980.  
  981. function Is_Sequence(        --| Check if T is at some sequence characters 
  982.     Chars : in string;        --| Characters to be scanned
  983.     T     : in Scanner        --| The string being scanned
  984.     ) return boolean;
  985.  
  986. --| Effects: Return TRUE iff T is at some character of Chars.
  987. --| Modifies: Raises, Modifies, Errors
  988.  
  989. ----------------------------------------------------------------
  990.  
  991. procedure Scan_Sequence(    --| Scan arbitrary sequence of characters
  992.     Chars  : in     String_Type;--| Characters that should be scanned
  993.     T      : in     Scanner;    --| String to be scanned
  994.     Found  :    out boolean;    --| TRUE iff a sequence found
  995.     Result :    out String_Type;--| Sequence scanned from string
  996.     Skip   : in     boolean := false
  997.                 --| Skip white spaces before scan
  998.     );
  999.  
  1000. --| Effects: Scan T for a sequence of characters C such that C appears in 
  1001. --| Char.  If at least one is found, return Found => TRUE, 
  1002. --| Result => <the characters>.
  1003. --| Otherwise return Found => FALSE and Result is unpredictable.
  1004.  
  1005. --| Modifies: Raises, Modifies, Errors
  1006.  
  1007. --| Notes:
  1008. --| Scan_Sequence("0123456789", S, Index, Found, Result)
  1009. --| is equivalent to Scan_Number(S, Index, Found, Result)
  1010. --| but is less efficient.
  1011.  
  1012. ----------------------------------------------------------------
  1013.  
  1014. procedure Scan_Sequence(    --| Scan arbitrary sequence of characters
  1015.     Chars  : in     string;    --| Characters that should be scanned
  1016.     T      : in     Scanner;    --| String to be scanned
  1017.     Found  :    out boolean;    --| TRUE iff a sequence found
  1018.     Result :    out String_Type;--| Sequence scanned from string
  1019.     Skip   : in     boolean := false
  1020.                 --| Skip white spaces before scan
  1021.     );
  1022.  
  1023. --| Effects: Scan T for a sequence of characters C such that C appears in 
  1024. --| Char.  If at least one is found, return Found => TRUE, 
  1025. --| Result => <the characters>.
  1026. --| Otherwise return Found => FALSE and Result is unpredictable.
  1027.  
  1028. --| Modifies: Raises, Modifies, Errors
  1029.  
  1030. --| Notes:
  1031. --| Scan_Sequence("0123456789", S, Index, Found, Result)
  1032. --| is equivalent to Scan_Number(S, Index, Found, Result)
  1033. --| but is less efficient.
  1034.                                                     pragma Page;
  1035. function Is_Not_Sequence(    --| Check if T is not at some seuqnce of character 
  1036.     Chars : in String_Type;    --| Characters to be scanned
  1037.     T     : in Scanner        --| The string being scanned
  1038.     ) return boolean;
  1039.  
  1040. --| Effects: Return TRUE iff T is not at some character of Chars.
  1041. --| Modifies: Raises, Modifies, Errors
  1042.  
  1043. ----------------------------------------------------------------
  1044.  
  1045. function Is_Not_Sequence(    --| Check if T is at some sequence of characters 
  1046.     Chars : in string;        --| Characters to be scanned
  1047.     T     : in Scanner        --| The string being scanned
  1048.     ) return boolean;
  1049.  
  1050. --| Effects: Return TRUE iff T is not at some character of Chars.
  1051. --| Modifies: Raises, Modifies, Errors
  1052.  
  1053. ----------------------------------------------------------------
  1054.  
  1055. procedure Scan_Not_Sequence(    --| Scan arbitrary sequence of characters
  1056.     Chars  : in     String_Type;--| Characters that should be scanned
  1057.     T      : in     Scanner;    --| String to be scanned
  1058.     Found  :    out boolean;    --| TRUE iff a sequence found
  1059.     Result :    out String_Type;--| Sequence scanned from string
  1060.     Skip   : in     boolean := false
  1061.                 --| Skip white spaces before scan
  1062.     );
  1063.  
  1064. --| Effects: Scan T for a sequence of characters C such that C does not appear
  1065. --| in Chars.  If at least one such C is found, return Found => TRUE, 
  1066. --| Result => <the characters>.
  1067. --| Otherwise return Found => FALSE and Result is unpredictable.
  1068.  
  1069. --| Modifies: Raises, Modifies, Errors
  1070.  
  1071. ----------------------------------------------------------------
  1072.  
  1073. procedure Scan_Not_Sequence(    --| Scan arbitrary sequence of characters
  1074.     Chars  : in     string;    --| Characters that should be scanned
  1075.     T      : in     Scanner;    --| String to be scanned
  1076.     Found  :    out boolean;    --| TRUE iff a sequence found
  1077.     Result :    out String_Type;--| Sequence scanned from string
  1078.     Skip   : in     boolean := false
  1079.                 --| Skip white spaces before scan
  1080.     );
  1081.  
  1082. --| Effects: Scan T for a sequence of characters C such that C does not appear
  1083. --| in Chars.  If at least one such C is found, return Found => TRUE, 
  1084. --| Result => <the characters>.
  1085. --| Otherwise return Found => FALSE and Result is unpredictable.
  1086.  
  1087. --| Modifies: Raises, Modifies, Errors
  1088.                                                     pragma Page;
  1089. function Is_Literal(        --| Check if T is at literal Chars
  1090.     Chars : in String_Type;    --| Characters to be scanned
  1091.     T     : in Scanner        --| The string being scanned
  1092.     ) return boolean;
  1093.  
  1094. --| Effects: Return TRUE iff T is at literal Chars.
  1095. --| Modifies: Raises, Modifies, Errors
  1096.  
  1097. ----------------------------------------------------------------
  1098.  
  1099. function Is_Literal(        --| Check if T is at literal Chars
  1100.     Chars : in string;        --| Characters to be scanned
  1101.     T     : in Scanner        --| The string being scanned
  1102.     ) return boolean;
  1103.  
  1104. --| Effects: Return TRUE iff T is at literal Chars.
  1105. --| Modifies: Raises, Modifies, Errors
  1106.  
  1107. ----------------------------------------------------------------
  1108.  
  1109. procedure Scan_Literal(        --| Scan arbitrary literal
  1110.     Chars  : in     String_Type;--| Literal that should be scanned
  1111.     T      : in     Scanner;    --| String to be scanned
  1112.     Found  :    out boolean;    --| TRUE iff a sequence found
  1113.     Skip   : in     boolean := false
  1114.                 --| Skip white spaces before scan
  1115.     );
  1116.  
  1117. --| Effects: Scan T for a litral Chars such that Char matches the sequence
  1118. --| of characters in T.  If found, return Found => TRUE, 
  1119. --| Otherwise return Found => FALSE
  1120.  
  1121. --| Modifies: Raises, Modifies, Errors
  1122.  
  1123. ----------------------------------------------------------------
  1124.  
  1125. procedure Scan_Literal(        --| Scan arbitrary literal
  1126.     Chars  : in     string;    --| Literal that should be scanned
  1127.     T      : in     Scanner;    --| String to be scanned
  1128.     Found  :    out boolean;    --| TRUE iff a sequence found
  1129.     Skip   : in     boolean := false
  1130.                 --| Skip white spaces before scan
  1131.     );
  1132.  
  1133. --| Effects: Scan T for a litral Chars such that Char matches the sequence
  1134. --| of characters in T.  If found, return Found => TRUE, 
  1135. --| Otherwise return Found => FALSE
  1136.  
  1137. --| Modifies: Raises, Modifies, Errors
  1138.                                                     pragma Page;
  1139. function Is_Not_Literal(    --| Check if T is not at literal Chars
  1140.     Chars : in string;        --| Characters to be scanned
  1141.     T     : in Scanner        --| The string being scanned
  1142.     ) return boolean;
  1143.  
  1144. --| Effects: Return TRUE iff T is not at literal Chars
  1145. --| Modifies: Raises, Modifies, Errors
  1146.  
  1147. ----------------------------------------------------------------
  1148.  
  1149. function Is_Not_Literal(    --| Check if T is not at literal Chars
  1150.     Chars : in String_Type;    --| Characters to be scanned
  1151.     T     : in Scanner        --| The string being scanned
  1152.     ) return boolean;
  1153.  
  1154. --| Effects: Return TRUE iff T is not at literal Chars
  1155. --| Modifies: Raises, Modifies, Errors
  1156.  
  1157. ----------------------------------------------------------------
  1158.  
  1159. procedure Scan_Not_Literal(    --| Scan arbitrary literal
  1160.     Chars  : in     string;    --| Literal that should be scanned
  1161.     T      : in     Scanner;    --| String to be scanned
  1162.     Found  :    out boolean;    --| TRUE iff a sequence found
  1163.     Result :    out String_Type;--| String up to literal
  1164.     Skip   : in     boolean := false
  1165.                 --| Skip white spaces before scan
  1166.     );
  1167.  
  1168. --| Effects: Scan T for a litral Chars such that Char does not match the
  1169. --| sequence of characters in T.  If found, return Found => TRUE, 
  1170. --| Otherwise return Found => FALSE
  1171.  
  1172. --| Modifies: Raises, Modifies, Errors
  1173.  
  1174. ----------------------------------------------------------------
  1175.  
  1176. procedure Scan_Not_Literal(    --| Scan arbitrary literal
  1177.     Chars  : in     String_Type;--| Literal that should be scanned
  1178.     T      : in     Scanner;    --| String to be scanned
  1179.     Found  :    out boolean;    --| TRUE iff a sequence found
  1180.     Result :    out String_Type;--| String up to literal
  1181.     Skip   : in     boolean := false
  1182.                 --| Skip white spaces before scan
  1183.     );
  1184.  
  1185. --| Effects: Scan T for a litral Chars such that Char does not match the
  1186. --| sequence of characters in T.  If found, return Found => TRUE, 
  1187. --| Otherwise return Found => FALSE
  1188.  
  1189. --| Modifies: Raises, Modifies, Errors
  1190.                                                     pragma Page;
  1191. private
  1192.                                                     pragma List(off);
  1193.     type Scan_Record is
  1194.     record
  1195.         text  : String_Type;    --| Copy of string being scanned
  1196.         index : positive := 1;    --| Current position of Scanner
  1197.         mark  : natural := 0;    --| Mark
  1198.     end record;
  1199.  
  1200.     type Scanner is access Scan_Record;
  1201.                                                     pragma List(on);
  1202. end String_Scanner;
  1203.                                                     pragma Page;
  1204. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1205. --CLI.SPC
  1206. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1207. with String_pkg;
  1208. use String_pkg;
  1209.  
  1210. --------------------------------------------------------------------
  1211.  
  1212. Package command_line_interface is
  1213. --| Provides primitives for getting at the command line arguments.
  1214.  
  1215. --| Overview
  1216. --| This package provides a universal and portable interface to 
  1217. --| the arguments typed on a command line when a program is invoked.
  1218. --| Each command line argument is either a Word (sequence of non-blank
  1219. --| characters) or a quoted string, with embedded quotes doubled.
  1220. --| 
  1221. --| Both named and positional arguments may be given on the command
  1222. --| line.  However, once a named parameter is used, all the subseqent
  1223. --| parameters on the command line must be named parameters.  For example, 
  1224. --| the commands
  1225. --|-
  1226. --|     compile  abc pqr xyz library => plib
  1227. --|     compile  abc,pqr,unit=>xyz,library=>plib
  1228. --|+
  1229. --| have one named argument and three positional arguments.  This
  1230. --| package separates the named parameters from the positional
  1231. --| parameters, ignores spaces around the "bound to" (=>) symbol, and
  1232. --| allows parameters to be separated by either spaces or commas,
  1233. --| so these command lines are indistinguishable.
  1234. --| 
  1235. --| At program elaboration time, the command line string is automatically
  1236. --| obtained from the host operating system and parsed into
  1237. --| individual arguments.  The following operations may then be used:
  1238. --|-
  1239. --| Named_arg_count()        Returns number of named arguments entered
  1240. --| Positional_arg_count()    Returns number of positional arguments
  1241. --| Positional_arg_value(N)    Returns the Nth positional argument
  1242. --| Named_arg_value(Name, Dflt)    Returns value of a named argument
  1243. --| Arguments()            Returns the entire command line 
  1244. --|+
  1245.  
  1246. ----------------------------------------------------------------
  1247.  
  1248. max_args: constant := 255;
  1249. --| Maximum number of command line arguments (arbitrary).
  1250.  
  1251. subtype Argument_count is integer range 0..max_args;
  1252. --| For number of arguments
  1253. subtype Argument_index is Argument_count range 1..Argument_count'last;
  1254. --| Used to number the command line arguments.
  1255.  
  1256. no_arg: exception;    
  1257.   --| Raised when request made for nonexistent argument
  1258.  
  1259. missing_positional_arg: exception;
  1260.   --| Raised when command line is missing positional argument (A,,B)
  1261.  
  1262. invalid_named_association: exception;
  1263.   --| Raised when command line is missing named argument value (output=> ,A,B)
  1264.  
  1265. unreferenced_named_arg: exception;
  1266.   --| Raised when not all named parameters have been retrieved
  1267.  
  1268. invalid_parameter_order: exception;
  1269.   --| Raised when a positional parameter occurs after a named parameter
  1270.   --  in the command line
  1271.  
  1272. ----------------------------------------------------------------
  1273.  
  1274. procedure Initialize;           --| Initializes command_line_interface
  1275.  
  1276. --| N/A: modifies, errors, raises
  1277.  
  1278. ---------------------------------------------------------------------
  1279.  
  1280. function Named_arg_count    --| Return number of named arguments
  1281.   return Argument_count;
  1282. --| N/A: modifies, errors, raises
  1283.  
  1284.  
  1285. function Positional_arg_count    --| Return number of positional arguments
  1286.   return Argument_count;
  1287. --| N/A: modifies, errors, raises
  1288.  
  1289.  
  1290. ----------------------------------------------------------------
  1291.  
  1292. function Positional_arg_value(    --| Return an argument value
  1293.   N: Argument_index            --| Position of desired argument
  1294.   ) return string;              --| Raises: no_arg
  1295.  
  1296. --| Effects: Return the Nth argument.  If there is no argument at
  1297. --| position N, no_arg is raised.
  1298.  
  1299. --| N/A: modifies, errors
  1300.  
  1301.  
  1302. function Positional_arg_value(        --| Return an argument value
  1303.   N: Argument_index                --| Position of desired argument
  1304.   ) return String_type;             --| Raises: no_arg
  1305.  
  1306. --| Effects: Return the Nth argument.  If there is no argument at
  1307. --| position N, no_arg is raised.
  1308.  
  1309. --| N/A: modifies, errors
  1310.  
  1311. --------------------------------------------------------------------
  1312.  
  1313. function Named_arg_value(--| Return a named argument value
  1314.   Name: string;
  1315.   Default: string
  1316.   ) return string;
  1317.  
  1318. --| Effects: Return the value associated with Name on the command
  1319. --| line.  If there was none, return Default.
  1320.  
  1321. --| N/A: modifies, errors
  1322.  
  1323.  
  1324. function Named_arg_value(--| Return a named argument value
  1325.   Name: string;
  1326.   Default: String_type
  1327.   ) return String_type;
  1328.  
  1329. --| Effects: Return the value associated with Name on the command
  1330. --| line.  If there was none, return Default.
  1331.  
  1332. --| N/A: modifies, errors
  1333.  
  1334. ----------------------------------------------------------------
  1335.  
  1336. function Arguments    --| Return the entire argument string
  1337.   return string;
  1338. --| Effects: Return the entire command line, except for the name
  1339. --| of the command itself.
  1340.  
  1341. --| N/A: modifies, errors, raises
  1342.  
  1343. ----------------------------------------------------------------
  1344.  
  1345. procedure Finalize ;    --| Raises: unrecognized parameters
  1346.  
  1347. --| Effects: If not all named parameters have been retrieved
  1348. --| unrecognized parameters is raised.
  1349. --| N/A: modifies, errors
  1350.  
  1351. end command_line_interface;
  1352.  
  1353. ----------------------------------------------------------------
  1354. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1355. --CLI.BDY
  1356. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1357. with Text_IO; use Text_IO;
  1358. with VMS_Lib;    -- For lib$get_foreign
  1359. with String_pkg;
  1360. with String_scanner;
  1361. ----------------------------------------------------------------
  1362.  
  1363. Package body command_line_interface is
  1364. --| Provides primitives for getting at the command line arguments.
  1365.  
  1366. --| Overview
  1367.  
  1368. Package sp renames String_pkg;
  1369. Package ss renames String_scanner;
  1370.  
  1371. type Name_value is                  --| Name/Value pair
  1372.   record
  1373.     Name:  sp.String_type;          --| Name of value
  1374.     Value: sp.String_type;          --| Value associated with name
  1375.     Was_retrieved: boolean:=FALSE;  --| Flag indicating whether name-value
  1376.   end record;                       --  association has been retrieved by tool
  1377.  
  1378. type Token_type is (Ada_ID,Word,Bound_to,None);
  1379.  
  1380. Package Token_type_IO is new Enumeration_IO(Token_type);
  1381. use Token_type_IO;
  1382.  
  1383. Arg_string: string(1..132);        --| String obtained from operating system
  1384.                                     --  (ie. from get_foreign)
  1385. N_arg_count: Argument_count;        --| Count of named args 
  1386. P_arg_count: Argument_count;        --| Count of positional args 
  1387. Rejected: boolean := FALSE;
  1388.  
  1389. Named_args: array(argument_index)
  1390.    of Name_value;
  1391.     
  1392. Positional_args: array(argument_index)
  1393.    of sp.String_type;
  1394.  
  1395. ----------------------------------------------------------------
  1396.  
  1397. -- Local functions:
  1398.  
  1399. procedure Get_token(
  1400.   Scan_string : in out ss.Scanner;
  1401.   Argument : in out sp.String_type;
  1402.   Kind: in out Token_type
  1403.   ) is
  1404.  
  1405.   Last_arg: sp.String_type;
  1406.   Last_kind: Token_type;
  1407.   Found: boolean;
  1408.   Delimeter: sp.String_type;
  1409.   Delim_string: ss.Scanner;
  1410.   More_commas: boolean := FALSE;
  1411.   Tail: sp.String_type;
  1412.   
  1413. begin
  1414.  
  1415.   if Rejected then
  1416.     Argument := Last_arg;
  1417.     Kind := Last_kind;
  1418.     Rejected := FALSE;
  1419.   else    
  1420.     if ss.Is_sequence(" ,",Scan_string) then
  1421.         ss.Scan_sequence(" ,",Scan_string,Found,Delimeter);
  1422.         Delim_string := ss.Make_scanner(Delimeter);
  1423.         loop
  1424.             ss.Skip_space(Delim_string);
  1425.             exit when not ss.More(Delim_string);
  1426.             ss.Forward(Delim_string);
  1427.             if More_commas then
  1428.                 raise missing_positional_arg;
  1429.             end if;
  1430.             More_commas := TRUE;
  1431.         end loop;
  1432.     end if;
  1433.        if ss.Is_Ada_Id(Scan_string) then
  1434.         ss.Scan_Ada_Id(Scan_string,Found,Argument);
  1435.         if ss.Is_Literal("=>",Scan_string) or 
  1436.            ss.Is_Literal("""",Scan_string) or 
  1437.            ss.Is_sequence(" ,",Scan_string) or
  1438.            not ss.More(Scan_string) then 
  1439.             Kind := Ada_ID;
  1440.         else
  1441.             if ss.Is_not_sequence(" ,",Scan_string) then
  1442.                 ss.Scan_not_sequence(" ,",Scan_string,Found,Tail);
  1443.                 Argument := sp."&"(Argument,Tail);
  1444.                 Kind := Word;
  1445.             else
  1446.                 ss.Scan_word(Scan_string,Found,Tail);
  1447.                 Argument := sp."&"(Argument,Tail);
  1448.                 Kind := Word;
  1449.             end if;
  1450.         end if;
  1451.     elsif ss.Is_Literal("=>",Scan_string) then
  1452.         ss.Scan_Literal("=>",Scan_string,Found);
  1453.         Argument := sp.Create("=>");
  1454.         Kind := Bound_to;
  1455.     elsif ss.Is_quoted(Scan_string) then
  1456.         ss.Scan_quoted(Scan_string,Found,Argument);
  1457.         Kind := Word;
  1458.     elsif ss.Is_enclosed('(',')',Scan_string) then
  1459.         ss.Scan_enclosed('(',')',Scan_string,Found,Argument);
  1460.         Kind := Word;
  1461.     elsif ss.Is_not_sequence(" ,",Scan_string) then
  1462.         ss.Scan_not_sequence(" ,",Scan_string,Found,Argument);
  1463.         Kind := Word;
  1464.        elsif ss.Is_word(Scan_string) then
  1465.         ss.Scan_word(Scan_string,Found,Argument);
  1466.         Kind := Word;
  1467.     else
  1468.           Argument := sp.Create("");
  1469.         Kind := None;
  1470.     end if;
  1471.     Last_kind := Kind;
  1472.     Last_arg := Argument;
  1473.   end if;
  1474. end Get_token;
  1475.  
  1476. -----------------------------------------------------------------------
  1477.  
  1478. procedure Save_named(
  1479.   Name : in sp.String_type;
  1480.   Value : in sp.String_type
  1481.   ) is
  1482.  
  1483. begin
  1484.   N_arg_count := N_arg_count + 1;
  1485.   Named_args(N_arg_count).Name := Name;
  1486.   Named_args(N_arg_count).Value := Value;
  1487. end Save_named;
  1488.  
  1489. procedure Save_positional(
  1490.   Value : in sp.String_type
  1491.   ) is
  1492.  
  1493. begin
  1494.   if N_arg_count > 0 then
  1495.     raise invalid_parameter_order;
  1496.   end if;
  1497.   P_arg_count := P_arg_count + 1;
  1498.   Positional_args(P_arg_count) := Value;
  1499. end Save_positional;
  1500.  
  1501. procedure Reject_token is
  1502.  
  1503. begin
  1504.   Rejected := TRUE;
  1505. end Reject_token;
  1506.  
  1507. ----------------------------------------------------------------
  1508.  
  1509. procedure Initialize is
  1510.  
  1511. begin
  1512.  
  1513.   declare
  1514.  
  1515.      type State_type is (Have_nothing,Have_Ada_ID,Have_bound_to);
  1516.  
  1517.      Index: integer;            --| Index of characters in argument string
  1518.      Scan_string: ss.Scanner;  --| Scanned argument string
  1519.      Argument: sp.String_Type; --| Argument scanned from argument string
  1520.      Kind: Token_type;         --| Kind of argument- WORD, =>, Ada_ID
  1521.      Old_arg: sp.String_Type;  --| Previously scanned argument 
  1522.      Found: boolean;
  1523.  
  1524.      State: State_type := Have_nothing;
  1525.      --| State of argument in decision tree 
  1526.    
  1527.   begin
  1528.  
  1529.      Index := Arg_string'first;
  1530.      N_arg_count := 0;
  1531.      P_arg_count := 0;
  1532.  
  1533.      -- Get the command line from the operating system
  1534.      VMS_Lib.get_foreign(Arg_string);
  1535.  
  1536.      -- Remove trailing blanks and final semicolon  
  1537.      for i in reverse Arg_string'range loop
  1538.     if Arg_string(i) /= ' ' then
  1539.         if Arg_string(i) = ';' then
  1540.         Index := i - 1;
  1541.         else
  1542.         Index := i;
  1543.         end if;
  1544.         exit;
  1545.     end if;
  1546.      end loop;
  1547.  
  1548.      -- Convert argument string to scanner and remove enclosing parantheses
  1549.  
  1550.      Scan_string :=  ss.Make_scanner(sp.Create(Arg_string(Arg_string'first..index)));
  1551.      if ss.Is_enclosed('(',')',Scan_string) then
  1552.     ss.Mark(Scan_string);
  1553.     ss.Scan_enclosed('(',')',Scan_string,Found,Argument); 
  1554.     ss.Skip_Space(Scan_string);
  1555.     if not ss.More(Scan_string) then
  1556.         ss.Destroy_Scanner(Scan_string);
  1557.         Scan_string :=  ss.Make_scanner(Argument);
  1558.     else
  1559.         ss.Restore(Scan_string);
  1560.     end if;
  1561.      end if;
  1562.  
  1563.      -- Parse argument string and save arguments 
  1564.      loop 
  1565.     Get_token(Scan_string,Argument,Kind);
  1566.     case State is
  1567.         when Have_nothing =>
  1568.             case Kind is
  1569.                 when Ada_ID => 
  1570.                     Old_arg := Argument;
  1571.                     State := Have_Ada_ID;
  1572.                 when Word => 
  1573.                     Save_positional(Argument);
  1574.                     State := Have_nothing;
  1575.                 when Bound_to => 
  1576.                     State := Have_nothing;
  1577.                     raise invalid_named_association;
  1578.                 when None => 
  1579.                     null;
  1580.             end case;
  1581.         when Have_Ada_ID =>
  1582.             case Kind is
  1583.                 when Ada_ID => 
  1584.                     Save_positional(Old_arg);
  1585.                     Old_arg := Argument;
  1586.                     State := Have_Ada_ID;
  1587.                 when Word => 
  1588.                     Save_positional(Old_arg);
  1589.                     Save_positional(Argument);
  1590.                     State := Have_nothing;
  1591.                 when Bound_to => 
  1592.                     State := Have_bound_to;
  1593.                 when None =>
  1594.                     Save_positional(Old_arg);
  1595.             end case;
  1596.         when Have_bound_to => 
  1597.             case Kind is
  1598.                 when Ada_ID | Word => 
  1599.                     Save_named(Old_arg,Argument);
  1600.                     State := Have_nothing;
  1601.                 when Bound_to => 
  1602.                     State := Have_bound_to;
  1603.                     raise invalid_named_association;
  1604.                 when None => 
  1605.                     raise invalid_named_association;
  1606.  
  1607.             end case;
  1608.     end case;
  1609.     exit when Kind = None;
  1610.      end loop;
  1611.   end;
  1612. end Initialize;
  1613.  
  1614. --------------------------------------------------------------------------
  1615.  
  1616. function Named_arg_count    --| Return number of named arguments
  1617.   return Argument_count is
  1618.  
  1619. begin
  1620.   return N_arg_count;
  1621. end;
  1622.  
  1623. ----------------------------------------------------------------
  1624.  
  1625. function Positional_arg_count    --| Return number of positional arguments
  1626.   return Argument_count is
  1627.  
  1628. begin
  1629.   return P_arg_count;
  1630. end;
  1631.  
  1632. ----------------------------------------------------------------
  1633.  
  1634. function Positional_arg_value(    --| Return an argument value
  1635.   N: Argument_index         --| Position of desired argument
  1636.   ) return string is            --| Raises: no_arg
  1637.  
  1638. --| Effects: Return the Nth argument.  If there is no argument at
  1639. --| position N, no_arg is raised.
  1640.  
  1641. --| N/A: modifies, errors
  1642.  
  1643. begin
  1644.   if N > P_arg_count then
  1645.      raise no_arg;   
  1646.   else
  1647.      return sp.Value(Positional_args(N));
  1648.   end if;
  1649. end;
  1650.  
  1651. ----------------------------------------------------------------
  1652.  
  1653. function Positional_arg_value(    --| Return an argument value
  1654.   N: Argument_index         --| Position of desired argument
  1655.   ) return sp.String_type is    --| Raises: no_arg
  1656.  
  1657. --| Effects: Return the Nth argument.  If there is no argument at
  1658. --| position N, no_arg is raised.
  1659.  
  1660. --| N/A: modifies, errors
  1661.  
  1662. begin
  1663.   if N > P_arg_count then
  1664.      raise no_arg;   
  1665.   else
  1666.      return Positional_args(N);
  1667.   end if;
  1668. end;
  1669.  
  1670. ----------------------------------------------------------------
  1671.  
  1672. function Named_arg_value(--| Return a named argument value
  1673.   Name: string;
  1674.   Default: string
  1675.   ) return string is
  1676.  
  1677. --| Effects: Return the value associated with Name on the command
  1678. --| line.  If there was none, return Default.
  1679.  
  1680. begin
  1681.   for i in 1..N_arg_count
  1682.   loop
  1683.      if sp.Equal(sp.Upper(Named_args(i).Name),sp.Upper(sp.Create(Name))) then
  1684.         Named_args(i).Was_retrieved := TRUE;
  1685.     return sp.Value(Named_args(i).Value);
  1686.      end if;
  1687.   end loop;
  1688.   return Default;
  1689. end;
  1690. ----------------------------------------------------------------
  1691.  
  1692. function Named_arg_value(--| Return a named argument value
  1693.   Name: string;
  1694.   Default: sp.String_type
  1695.   ) return sp.String_type is
  1696.  
  1697. --| Effects: Return the value associated with Name on the command
  1698. --| line.  If there was none, return Default.
  1699.  
  1700. begin
  1701.   for i in 1..N_arg_count
  1702.   loop
  1703.      if sp.Equal(sp.Upper(Named_args(i).Name),sp.Upper(sp.Create(Name))) then
  1704.         Named_args(i).Was_retrieved := TRUE;
  1705.     return Named_args(i).Value;
  1706.      end if;
  1707.   end loop;
  1708.   return Default;
  1709. end;
  1710.  
  1711. ----------------------------------------------------------------
  1712.  
  1713. function Arguments    --| Return the entire argument string
  1714.   return string is
  1715.  
  1716. --| Effects: Return the entire command line, except for the name
  1717. --| of the command itself.
  1718.  
  1719. begin
  1720.   return Arg_string;
  1721. end;
  1722. ----------------------------------------------------------------
  1723.  
  1724. procedure Finalize is   --| Raises: unreferenced_named_arg
  1725.  
  1726. begin
  1727.   for i in 1..Named_arg_count loop
  1728.      if Named_args(i).Was_retrieved = FALSE then
  1729.         raise unreferenced_named_arg;
  1730.      end if;
  1731.   end loop;
  1732. end Finalize;
  1733.  
  1734. -------------------------------------------------------------------
  1735.  
  1736. end command_line_interface;
  1737. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1738. --LISTS.SPC
  1739. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1740.  
  1741. generic
  1742.       type ItemType is private;  --| This is the data being manipulated.
  1743.       
  1744.       with function Equal ( X,Y: in ItemType) return boolean is "=";
  1745.                                  --| This allows the user to define
  1746.                                  --| equality on ItemType.  For instance
  1747.                  --| if ItemType is an abstract type
  1748.                  --| then equality is defined in terms of
  1749.                  --| the abstract type.  If this function
  1750.                  --| is not provided equality defaults to
  1751.                  --| =.
  1752. package Lists is
  1753.  
  1754. --| This package provides singly linked lists with elements of type
  1755. --| ItemType, where ItemType is specified by a generic parameter.
  1756.  
  1757. --| Overview
  1758. --| When this package is instantiated, it provides a linked list type for
  1759. --| lists of objects of type ItemType, which can be any desired type.  A
  1760. --| complete set of operations for manipulation, and releasing
  1761. --| those lists is also provided.  For instance, to make lists of strings,
  1762. --| all that is necessary is:
  1763. --|
  1764. --| type StringType is string(1..10);
  1765. --|
  1766. --| package Str_List is new Lists(StringType); use Str_List;
  1767. --| 
  1768. --|    L:List;
  1769. --|    S:StringType;
  1770. --|
  1771. --| Then to add a string S, to the list L, all that is necessary is
  1772. --|
  1773. --|    L := Create;
  1774. --|    Attach(S,L);
  1775. --| 
  1776. --| 
  1777. --| This package provides basic list operations.
  1778. --|
  1779. --| Attach          append an object to an object, an object to a list,
  1780. --|                 or a list to an object, or a list to a list.
  1781. --| Copy            copy a list using := on elements
  1782. --| CopyDeep        copy a list by copying the elements using a copy
  1783. --|                 operation provided by the user
  1784. --| Create          Creates an empty list
  1785. --| DeleteHead      removes the head of a list
  1786. --| DeleteItem      delete the first occurrence of an element from a list
  1787. --| DeleteItems     delete all occurrences of an element from a list
  1788. --| Destroy         remove a list
  1789. --| Equal           are two lists equal
  1790. --| FirstValue      get the information from the first element of a list
  1791. --| IsInList        determines whether a given element is in a given list
  1792. --| IsEmpty         returns true if the list is empty
  1793. --| LastValue       return the last value of a list
  1794. --| Length          Returns the length of a list 
  1795. --| MakeListIter    prepares for an iteration over a list
  1796. --| More            are there any more items in the list
  1797. --| Next            get the next item in a list
  1798. --| ReplaceHead     replace the information at the head of the list
  1799. --| ReplaceTail     replace the tail of a list with a new list
  1800. --| Tail            get the tail of a list
  1801. --|   
  1802.  
  1803. --| N/A: Effects, Requires, Modifies, and Raises.
  1804.  
  1805. --| Notes
  1806. --| Programmer Buddy Altus
  1807.  
  1808. --|                           Types
  1809. --|                           -----
  1810.  
  1811.           type List       is private;
  1812.           type ListIter   is private;
  1813.  
  1814.  
  1815. --|                           Exceptions
  1816. --|                           ----------
  1817.  
  1818.     CircularList     :exception;     --| Raised if an attemp is made to
  1819.                                      --| create a circular list.  This
  1820.                                      --| results when a list is attempted
  1821.                                      --| to be attached to itself.
  1822.      
  1823.     EmptyList        :exception;     --| Raised if an attemp is made to
  1824.                                      --| manipulate an empty list.
  1825.                      
  1826.     ItemNotPresent   :exception;     --| Raised if an attempt is made to
  1827.                                      --| remove an element from a list in
  1828.                                      --| which it does not exist.
  1829.                      
  1830.     NoMore           :exception;     --| Raised if an attemp is made to
  1831.                                      --| get the next element from a list
  1832.                      --| after iteration is complete.
  1833.                      
  1834.  
  1835.  
  1836. --|                           Operations
  1837. --|                           ---------- 
  1838.  
  1839. ----------------------------------------------------------------------------
  1840.  
  1841. procedure Attach(                  --| appends List2 to List1
  1842.           List1:     in out List;  --| The list being appended to.
  1843.           List2:     in     List   --| The list being appended.
  1844. );
  1845.  
  1846. --| Raises
  1847. --| CircularList
  1848.  
  1849. --| Effects
  1850. --| Appends List1 to List2.  This makes the next field of the last element
  1851. --| of List1 refer to List2.  This can possibly change the value of List1
  1852. --| if List1 is an empty list.  This causes sharing of lists.  Thus if
  1853. --| user Destroys List1 then List2 will be a dangling reference.
  1854. --| This procedure raises CircularList if List1 equals List2.  If it is 
  1855. --| necessary to Attach a list to itself first make a copy of the list and 
  1856. --| attach the copy.
  1857.  
  1858. --| Modifies
  1859. --| Changes the next field of the last element in List1 to be List2.
  1860.  
  1861. -------------------------------------------------------------------------------
  1862.  
  1863. function Attach(                 --| Creates a new list containing the two
  1864.                                  --| Elements.
  1865.          Element1: in ItemType;  --| This will be first element in list.
  1866.          Element2: in ItemType   --| This will be second element in list.
  1867. ) return List;
  1868.  
  1869. --| Effects
  1870. --| This creates a list containing the two elements in the order
  1871. --| specified.
  1872.  
  1873. -------------------------------------------------------------------------------
  1874. procedure Attach(                   --| List L is appended with Element.
  1875.          L:       in out List;      --| List being appended to.
  1876.          Element: in     ItemType   --| This will be last element in l    ist.
  1877. );
  1878.  
  1879. --| Effects
  1880. --| Appends Element onto the end of the list L.  If L is empty then this
  1881. --| may change the value of L.
  1882. --|
  1883. --| Modifies
  1884. --| This appends List L with Element by changing the next field in List.
  1885.  
  1886. --------------------------------------------------------------------------------
  1887. procedure Attach(                   --| Makes Element first item in list L.
  1888.          Element: in      ItemType; --| This will be the first element in list.
  1889.          L:       in  out List      --| The List which Element is being
  1890.                                     --| prepended to.
  1891. );
  1892.  
  1893. --| Effects
  1894. --| This prepends list L with Element.
  1895. --|
  1896. --| Modifies
  1897. --| This modifies the list L.
  1898.  
  1899. --------------------------------------------------------------------------
  1900.  
  1901. function Attach (                      --| attaches two lists
  1902.          List1: in     List;           --| first list
  1903.          List2: in     List            --| second list
  1904. ) return List;
  1905.  
  1906. --| Raises
  1907. --| CircularList
  1908.  
  1909. --| Effects
  1910. --| This returns a list which is List1 attached to List2.  If it is desired
  1911. --| to make List1 be the new attached list the following ada code should be
  1912. --| used.
  1913. --|  
  1914. --| List1 := Attach (List1, List2);
  1915. --| This procedure raises CircularList if List1 equals List2.  If it is 
  1916. --| necessary to Attach a list to itself first make a copy of the list and 
  1917. --| attach the copy.
  1918.  
  1919. -------------------------------------------------------------------------
  1920.  
  1921. function Attach (                   --| prepends an element onto a list
  1922.          Element: in    ItemType;   --| element being prepended to list
  1923.          L:       in    List        --| List which element is being added
  1924.                                     --| to
  1925. ) return List;
  1926.  
  1927. --| Effects
  1928. --| Returns a new list which is headed by Element and followed by L.
  1929.  
  1930. ------------------------------------------------------------------------
  1931.  
  1932. function Attach (                  --| Adds an element to the end of a list
  1933.          L: in          List;      --| The list which element is being added to.
  1934.          Element: in    ItemType   --| The element being added to the end of
  1935.                                    --| the list.
  1936. ) return List;
  1937.  
  1938. --| Effects
  1939. --| Returns a new list which is L followed by Element.
  1940.  
  1941. --------------------------------------------------------------------------  
  1942.  
  1943.  
  1944. function Copy(          --| returns a copy of list1 
  1945.        L: in List       --| list being copied
  1946. ) return List;
  1947.  
  1948. --| Effects
  1949. --| Returns a copy of L.
  1950.  
  1951. --------------------------------------------------------------------------
  1952.  
  1953. generic
  1954.         with function Copy(I: in     ItemType) return ItemType;
  1955.     
  1956.  
  1957. function CopyDeep(      --| returns a copy of list using a user supplied
  1958.                         --| copy function.  This is helpful if the type
  1959.             --| of a list is an abstract data type.
  1960.          L: in     List --| List being copied.
  1961. ) return List;
  1962.   
  1963. --| Effects
  1964. --| This produces a new list whose elements have been duplicated using
  1965. --| the Copy function provided by the user.
  1966.  
  1967. ------------------------------------------------------------------------------
  1968.  
  1969. function Create           --| Returns an empty List
  1970.  
  1971. return List;
  1972.  
  1973. ------------------------------------------------------------------------------
  1974.  
  1975. procedure DeleteHead(            --| Remove the head element from a list.
  1976.           L: in out List         --| The list whose head is being removed.
  1977. ); 
  1978.  
  1979. --| Raises
  1980. --| EmptyList
  1981. --|
  1982. --| Effects
  1983. --| This will return the space occupied by the first element in the list
  1984. --| to the heap.  If sharing exists between lists this procedure
  1985. --| could leave a dangling reference.  If L is empty EmptyList will be
  1986. --| raised.
  1987.  
  1988. ------------------------------------------------------------------------------
  1989.  
  1990. procedure DeleteItem(           --| remove the first occurrence of Element
  1991.                                 --| from L
  1992.       L:       in out List;     --| list element is being  removed from
  1993.       Element: in     ItemType  --| element being removed
  1994. );
  1995.  
  1996. --| Raises
  1997. --| ItemNotPresent
  1998.  
  1999. --| Effects
  2000. --| Removes the first element of the list equal to Element.  If there is
  2001. --| not an element equal to Element than ItemNotPresent is raised.
  2002.  
  2003. --| Modifies
  2004. --| This operation is destructive, it returns the storage occupied by
  2005. --| the elements being deleted.
  2006.  
  2007. ------------------------------------------------------------------------------
  2008.  
  2009. procedure DeleteItems(          --| remove all occurrences of Element
  2010.                                 --| from  L.
  2011.       L:       in out List;     --| The List element is being removed from
  2012.       Element: in     ItemType  --| element being removed
  2013. );
  2014.  
  2015. --| Raises
  2016. --| ItemNotPresent
  2017. --|
  2018. --| Effects
  2019. --| This procedure walks down the list L and removes all elements of the
  2020. --| list equal to Element.  If there are not any elements equal to Element
  2021. --| then raise ItemNotPresent.
  2022.  
  2023. --| Modifies
  2024. --| This operation is destructive the storage occupied by the items
  2025. --| removed is returned.
  2026.  
  2027. ------------------------------------------------------------------------------
  2028.  
  2029. procedure Destroy(            --| removes the list
  2030.           L: in out List      --| the list being removed
  2031. );
  2032.  
  2033. --| Effects
  2034. --| This returns to the heap all the storage that a list occupies.  Keep in
  2035. --| mind if there exists sharing between lists then this operation can leave
  2036. --| dangling references.
  2037.  
  2038. ------------------------------------------------------------------------------
  2039.  
  2040. function FirstValue(      --| returns the contents of the first record of the 
  2041.                           --| list
  2042.          L: in List       --| the list whose first element is being
  2043.               --| returned
  2044.  
  2045. ) return ItemType;
  2046.  
  2047. --| Raises
  2048. --| EmptyList
  2049. --|
  2050. --| Effects
  2051. --| This returns the Item in the first position in the list.  If the list
  2052. --| is empty EmptyList is raised.
  2053.  
  2054. -------------------------------------------------------------------------------
  2055.  
  2056. function IsEmpty(            --| Checks if a list is empty.
  2057.          L: in     List      --| List being checked.
  2058. ) return boolean;
  2059.  
  2060. --------------------------------------------------------------------------
  2061.  
  2062. function IsInList(                 --| Checks if element is an element of
  2063.                                    --| list.
  2064.          L:       in     List;     --| list being scanned for element
  2065.          Element: in     ItemType  --| element being searched for
  2066. ) return boolean;
  2067.  
  2068. --| Effects
  2069. --| Walks down the list L looking for an element whose value is Element.
  2070.  
  2071. ------------------------------------------------------------------------------
  2072.  
  2073. function LastValue(       --| Returns the contents of the last record of
  2074.                           --| the list.
  2075.          L: in List       --| The list whose first element is being
  2076.                           --| returned.
  2077. ) return ItemType;
  2078.  
  2079. --| Raises
  2080. --| EmptyList
  2081. --|
  2082. --| Effects
  2083. --| Returns the last element in a list.  If the list is empty EmptyList is
  2084. --| raised.
  2085.  
  2086.  
  2087. ------------------------------------------------------------------------------
  2088.  
  2089. function Length(         --| count the number of elements on a list
  2090.          L: in List      --| list whose length is being computed
  2091. ) return integer;
  2092.  
  2093. ------------------------------------------------------------------------------
  2094.  
  2095. function MakeListIter(          --| Sets a variable to point to  the head
  2096.                                 --| of the list.  This will be used to
  2097.                                 --| prepare for iteration over a list.
  2098.          L: in List             --| The list being iterated over.
  2099. ) return ListIter;
  2100.  
  2101.                                                                           
  2102. --| This prepares a user for iteration operation over a list.  The iterater is
  2103. --| an operation which returns successive elements of the list on successive
  2104. --| calls to the iterator.  There needs to be a mechanism which marks the
  2105. --| position in the list, so on successive calls to the Next operation the
  2106. --| next item in the list can be returned.  This is the function of the
  2107. --| MakeListIter and the type ListIter.  MakeIter just sets the Iter to the
  2108. --| the beginning  of the list. On subsequent calls to Next the Iter
  2109. --| is updated with each call.
  2110.  
  2111. -----------------------------------------------------------------------------
  2112.  
  2113. function More(           --| Returns true if there are more elements in
  2114.                          --| the and false if there aren't any more
  2115.                          --| the in the list.
  2116.          L: in ListIter  --| List being checked for elements.
  2117. ) return boolean;
  2118.  
  2119. ------------------------------------------------------------------------------
  2120.  
  2121. procedure Next(                 --| This is the iterator operation.  Given
  2122.                                 --| a ListIter in the list it returns the
  2123.                                 --| current item and updates the ListIter.
  2124.                                 --| If ListIter is at the end of the list,
  2125.                                 --| More returns false otherwise it
  2126.                                 --| returns true.
  2127.     Place:    in out ListIter;  --| The Iter which marks the position in
  2128.                                 --| the list.
  2129.     Info:        out ItemType   --| The element being returned.
  2130.  
  2131. );
  2132.  
  2133. --| The iterators subprograms MakeListIter, More, and Next should be used
  2134. --| in the following way:
  2135. --|
  2136. --|         L:        List;
  2137. --|         Place:    ListIter;
  2138. --|         Info:     SomeType;
  2139. --|
  2140. --|     
  2141. --|         Place := MakeListIter(L);
  2142. --|
  2143. --|         while ( More(Place) ) loop
  2144. --|               Next(Place, Info);
  2145. --|               process each element of list L;
  2146. --|               end loop;
  2147.  
  2148.  
  2149. ----------------------------------------------------------------------------
  2150.  
  2151. procedure ReplaceHead(     --| Replace the Item at the head of the list
  2152.                            --| with the parameter Item.
  2153.      L:    in out List;    --| The list being modified.
  2154.      Info: in     ItemType --| The information being entered.
  2155. );
  2156. --| Raises 
  2157. --| EmptyList
  2158.  
  2159. --| Effects
  2160. --| Replaces the information in the first element in the list.  Raises
  2161. --| EmptyList if the list is empty.
  2162.  
  2163. ------------------------------------------------------------------------------
  2164.  
  2165. procedure ReplaceTail(           --| Replace the Tail of a list
  2166.                                  --| with a new list.
  2167.           L:       in out List;  --| List whose Tail is replaced.
  2168.           NewTail: in     List   --| The list which will become the
  2169.                  --| tail of Oldlist.
  2170. );
  2171. --| Raises
  2172. --| EmptyList
  2173. --|
  2174. --| Effects
  2175. --| Replaces the tail of a list with a new list.  If the list whose tail
  2176. --| is being replaced is null EmptyList is raised.
  2177.  
  2178. -------------------------------------------------------------------------------
  2179.  
  2180. function Tail(           --| returns the tail of a list L
  2181.          L: in List      --| the list whose tail is being returned
  2182. ) return List;
  2183.  
  2184. --| Raises
  2185. --| EmptyList
  2186. --|
  2187. --| Effects
  2188. --| Returns a list which is the tail of the list L.  Raises EmptyList if
  2189. --| L is empty.  If L only has one element then Tail returns the Empty
  2190. --| list.
  2191.  
  2192. ------------------------------------------------------------------------------
  2193.  
  2194. function Equal(            --| compares list1 and list2 for equality
  2195.          List1: in List;   --| first list
  2196.          List2: in List    --| second list
  2197.  )  return boolean;
  2198.  
  2199. --| Effects
  2200. --| Returns true if for all elements of List1 the corresponding element
  2201. --| of List2 has the same value.  This function uses the Equal operation
  2202. --| provided by the user.  If one is not provided then = is used.
  2203.  
  2204. ------------------------------------------------------------------------------
  2205. private
  2206.     type Cell;
  2207.     
  2208.     type List is access Cell;      --| pointer added by this package
  2209.                                    --| in order to make a list
  2210.                    
  2211.     
  2212.     type Cell is                   --| Cell for the lists being created
  2213.          record
  2214.               Info: ItemType;
  2215.               Next: List;
  2216.          end record;
  2217.  
  2218.     
  2219.     type ListIter is new List;     --| This prevents Lists being assigned to
  2220.                                    --| iterators and vice versa
  2221.   
  2222. end Lists;
  2223.  
  2224.  
  2225.  
  2226. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2227. --LISTS.BDY
  2228. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2229.  
  2230. with unchecked_deallocation;
  2231.  
  2232. package body Lists is
  2233.  
  2234.     procedure Free is new unchecked_deallocation (Cell, List);
  2235.  
  2236. --------------------------------------------------------------------------
  2237.  
  2238.    function Last (L: in     List) return List is
  2239.  
  2240.        Place_In_L:        List;
  2241.        Temp_Place_In_L:   List;
  2242.  
  2243.    --|  Link down the list L and return the pointer to the last element
  2244.    --| of L.  If L is null raise the EmptyList exception.
  2245.  
  2246.    begin
  2247.        if L = null then
  2248.            raise EmptyList;
  2249.        else
  2250.  
  2251.            --|  Link down L saving the pointer to the previous element in 
  2252.            --|  Temp_Place_In_L.  After the last iteration Temp_Place_In_L
  2253.            --|  points to the last element in the list.
  2254.  
  2255.            Place_In_L := L;
  2256.            while Place_In_L /= null loop
  2257.                Temp_Place_In_L := Place_In_L;
  2258.                Place_In_L := Place_In_L.Next;
  2259.            end loop;
  2260.            return Temp_Place_In_L;
  2261.        end if;
  2262.     end Last;
  2263.     
  2264.     
  2265. --------------------------------------------------------------------------
  2266.  
  2267.     procedure Attach (List1: in out List;
  2268.                       List2: in     List ) is
  2269.         EndOfList1: List;
  2270.  
  2271.     --| Attach List2 to List1. 
  2272.     --| If List1 is null return List2
  2273.     --| If List1 equals List2 then raise CircularList
  2274.     --| Otherwise get the pointer to the last element of List1 and change
  2275.     --| its Next field to be List2.
  2276.  
  2277.     begin
  2278.         if List1 = null then
  2279.         List1 := List2;
  2280.             return;
  2281.         elsif List1 = List2 then
  2282.             raise CircularList;
  2283.         else     
  2284.             EndOfList1 := Last (List1);
  2285.             EndOfList1.Next := List2;
  2286.         end if;
  2287.     end Attach;
  2288.  
  2289. --------------------------------------------------------------------------
  2290.  
  2291.    procedure Attach (L:       in out List;
  2292.                      Element: in     ItemType ) is
  2293.  
  2294.        NewEnd:    List;
  2295.  
  2296.    --| Create a list containing Element and attach it to the end of L
  2297.  
  2298.    begin
  2299.        NewEnd := new Cell'(Info => Element, Next => null);
  2300.        Attach (L, NewEnd);
  2301.    end;
  2302.  
  2303. --------------------------------------------------------------------------
  2304.  
  2305.    function Attach (Element1: in   ItemType;
  2306.                     Element2: in   ItemType ) return List is
  2307.        NewList: List;
  2308.  
  2309.    --| Create a new list containing the information in Element1 and
  2310.    --| attach Element2 to that list.
  2311.  
  2312.    begin
  2313.        NewList := new Cell'(Info => Element1, Next => null);
  2314.        Attach (NewList, Element2);
  2315.        return NewList;
  2316.    end;
  2317.  
  2318. --------------------------------------------------------------------------
  2319.  
  2320.    procedure Attach (Element: in     ItemType;
  2321.                      L:       in out List      ) is
  2322.  
  2323.    --|  Create a new cell whose information is Element and whose Next
  2324.    --|  field is the list L.  This prepends Element to the List L.
  2325.  
  2326.    begin
  2327.        L := new Cell'(Info => Element, Next => L);
  2328.    end;
  2329.  
  2330. --------------------------------------------------------------------------
  2331.  
  2332.    function Attach ( List1: in    List;
  2333.                      List2: in    List   ) return List is
  2334.  
  2335.    Last_Of_List1: List;
  2336.  
  2337.    begin 
  2338.        if List1 = null then
  2339.            return List2;
  2340.        elsif List1 = List2 then
  2341.            raise CircularList;
  2342.        else 
  2343.            Last_Of_List1 := Last (List1);
  2344.            Last_Of_List1.Next := List2;
  2345.            return List1;   
  2346.        end if;
  2347.    end  Attach;
  2348.  
  2349. -------------------------------------------------------------------------
  2350.  
  2351.    function Attach( L:       in     List;
  2352.                     Element: in     ItemType ) return List is
  2353.  
  2354.    NewEnd: List;
  2355.    Last_Of_L: List;
  2356.  
  2357.    --| Create a list called NewEnd and attach it to the end of L.
  2358.    --| If L is null return NewEnd 
  2359.    --| Otherwise get the last element in L and make its Next field
  2360.    --| NewEnd.
  2361.  
  2362.    begin 
  2363.        NewEnd := new Cell'(Info => Element, Next => null);
  2364.        if L = null then
  2365.            return NewEnd;
  2366.        else 
  2367.            Last_Of_L := Last (L);
  2368.            Last_Of_L.Next := NewEnd;
  2369.            return L;
  2370.        end if;
  2371.    end Attach;
  2372.  
  2373. --------------------------------------------------------------------------
  2374.  
  2375.    function Attach (Element: in     ItemType;
  2376.                     L:       in     List        ) return List is
  2377.  
  2378.    begin
  2379.        return (new Cell'(Info => Element, Next => L));
  2380.    end Attach;
  2381.  
  2382. --------------------------------------------------------------------------
  2383.  
  2384.    function Copy (L: in     List) return List is
  2385.    
  2386.    --| If L is null return null
  2387.    --| Otherwise recursively copy the list by first copying the information
  2388.    --| at the head of the list and then making the Next field point to 
  2389.    --| a copy of the tail of the list.
  2390.  
  2391.    begin
  2392.        if L = null then
  2393.        return null;
  2394.        else
  2395.        return new Cell'(Info => L.Info, Next => Copy (L.Next));
  2396.        end if;
  2397.    end Copy;
  2398.  
  2399.  
  2400. --------------------------------------------------------------------------
  2401.  
  2402.    function CopyDeep (L: in List) return List is
  2403.        
  2404.    --|  If L is null then return null.
  2405.    --|  Otherwise copy the first element of the list into the head of the
  2406.    --|  new list and copy the tail of the list recursively using CopyDeep.
  2407.  
  2408.    begin
  2409.        if L = null then
  2410.        return null;
  2411.        else
  2412.        return new Cell'( Info => Copy (L.Info), Next => CopyDeep(L.Next));
  2413.        end if;
  2414.    end CopyDeep;
  2415.        
  2416. --------------------------------------------------------------------------
  2417.  
  2418.     function Create return List is
  2419.  
  2420.     --| Return the empty list.
  2421.  
  2422.     begin
  2423.         return null;
  2424.     end Create;
  2425.     
  2426. --------------------------------------------------------------------------
  2427.    procedure DeleteHead (L: in out List) is
  2428.  
  2429.        TempList: List;
  2430.  
  2431.    --| Remove the element of the head of the list and return it to the heap.
  2432.    --| If L is null EmptyList.
  2433.    --| Otherwise save the Next field of the first element, remove the first
  2434.    --| element and then assign to L the Next field of the first element.
  2435.  
  2436.    begin
  2437.        if L = null then
  2438.            raise EmptyList;
  2439.        else
  2440.            TempList := L.Next;
  2441.            Free (L);
  2442.            L := TempList;
  2443.        end if;
  2444.    end DeleteHead;
  2445.  
  2446. --------------------------------------------------------------------------
  2447.  
  2448.    procedure DeleteItem (L:       in out List;
  2449.                          Element: in     ItemType ) is
  2450.  
  2451.        Temp_L  :List;
  2452.  
  2453.    --| Remove the first element in the list with the value Element.
  2454.    --| If the first element of the list is equal to element then
  2455.    --| remove it.  Otherwise, recurse on the tail of the list.
  2456.  
  2457.    begin
  2458.        if Equal(L.Info, Element) then
  2459.            DeleteHead(L);
  2460.        else
  2461.            DeleteItem(L.Next, Element);
  2462.        end if; 
  2463.    exception
  2464.        when constraint_error =>  
  2465.            raise ItemNotPresent; 
  2466.    end DeleteItem;
  2467.  
  2468. --------------------------------------------------------------------------
  2469.  
  2470.    procedure DeleteItems (L:       in out List;
  2471.                           Element: in     ItemType ) is
  2472.  
  2473.        Place_In_L       :List;     --| Current place in L.
  2474.        Last_Place_In_L  :List;     --| Last place in L.
  2475.        Temp_Place_In_L  :List;     --| Holds a place in L to be removed.
  2476.        Found            :boolean := false;  --| Indicates if an element with
  2477.                                             --| the correct value was found. 
  2478.  
  2479.    --| Walk over the list removing all elements with the value Element.
  2480.  
  2481.    begin
  2482.        Place_In_L := L;
  2483.        Last_Place_In_L := null;
  2484.        while (Place_In_L /= null) loop
  2485.            
  2486.            --| Found an element equal to Element
  2487.  
  2488.            if Equal(Place_In_L.Info, Element) then
  2489.                 Found := true;
  2490.       
  2491.                 --| If Last_Place_In_L is null then we are at first element
  2492.                 --| in L.
  2493.      
  2494.                 if Last_Place_In_L = null then
  2495.                      Temp_Place_In_L := Place_In_L;
  2496.                      L := Place_In_L.Next;
  2497.                 else
  2498.                      Temp_Place_In_L := Place_In_L;
  2499.                
  2500.                      --| Relink the list Last's Next gets Place's Next
  2501.  
  2502.                      Last_Place_In_L.Next := Place_In_L.Next;
  2503.                 end if;
  2504.  
  2505.                 --| Move Place_In_L to the next position in the list.
  2506.                 --| Free the element.
  2507.                 --| Do not update the last element in the list it remains the
  2508.                 --| same. 
  2509.  
  2510.                 Place_In_L := Place_In_L.Next;                       
  2511.                 Free (Temp_Place_In_L);
  2512.            else
  2513.                 --| Update the last place in L and the place in L.
  2514.  
  2515.                 Last_Place_In_L := Place_In_L;
  2516.                 Place_In_L := Place_In_L.Next;                       
  2517.            end if;    
  2518.        end loop;
  2519.  
  2520.    --| If we have not found an element raise an exception.
  2521.  
  2522.    if not Found then 
  2523.       raise ItemNotPresent;
  2524.    end if;
  2525.  
  2526.    end DeleteItems;
  2527.  
  2528. --------------------------------------------------------------------------
  2529.  
  2530.    procedure Destroy (L: in out List) is
  2531.  
  2532.        Place_In_L:  List;
  2533.        HoldPlace:   List;
  2534.  
  2535.    --| Walk down the list removing all the elements and set the list to
  2536.    --| the empty list. 
  2537.  
  2538.    begin
  2539.        Place_In_L := L;
  2540.        while Place_In_L /= null loop
  2541.            HoldPlace := Place_In_L;
  2542.            Place_In_L := Place_In_L.Next;
  2543.            Free (HoldPlace);
  2544.        end loop;
  2545.        L := null;
  2546.    end Destroy;
  2547.  
  2548. --------------------------------------------------------------------------
  2549.  
  2550.    function FirstValue (L: in    List) return ItemType is
  2551.  
  2552.    --| Return the first value in the list.
  2553.  
  2554.    begin
  2555.        if L = null then
  2556.        raise EmptyList;
  2557.        else
  2558.            return (L.Info);
  2559.        end if;
  2560.    end FirstValue;
  2561.    
  2562. --------------------------------------------------------------------------
  2563.  
  2564.    procedure Forword (I: in out ListIter) is
  2565.  
  2566.    --| Return the pointer to the next member of the list.
  2567.  
  2568.    begin
  2569.        I := ListIter (I.Next);
  2570.    end Forword;
  2571.    
  2572. --------------------------------------------------------------------------
  2573.  
  2574.    function IsInList (L:       in    List; 
  2575.                       Element: in    ItemType  ) return boolean is
  2576.  
  2577.    Place_In_L: List;
  2578.  
  2579.    --| Check if Element is in L.  If it is return true otherwise return false.
  2580.  
  2581.    begin
  2582.        Place_In_L := L;
  2583.        while Place_In_L /= null loop
  2584.        if Equal(Place_In_L.Info, Element) then
  2585.            return true;
  2586.        end if;
  2587.            Place_In_L := Place_In_L.Next;
  2588.     end loop;
  2589.     return false;
  2590.    end IsInList;
  2591.  
  2592. --------------------------------------------------------------------------
  2593.  
  2594.     function IsEmpty (L: in     List) return boolean is
  2595.     
  2596.     --| Is the list L empty.
  2597.  
  2598.     begin
  2599.     return (L = null);
  2600.     end IsEmpty;
  2601.     
  2602. --------------------------------------------------------------------------
  2603.  
  2604.    function LastValue (L: in     List) return ItemType is
  2605.        
  2606.        LastElement: List;
  2607.  
  2608.    --| Return the value of the last element of the list. Get the pointer
  2609.    --| to the last element of L and then return its information.
  2610.  
  2611.    begin
  2612.        LastElement := Last (L);
  2613.        return LastElement.Info;
  2614.    end LastValue;
  2615.        
  2616. --------------------------------------------------------------------------
  2617.  
  2618.    function Length (L: in     List) return integer is
  2619.  
  2620.    --| Recursively compute the length of L.  The length of a list is
  2621.    --| 0 if it is null or  1 + the length of the tail.
  2622.  
  2623.    begin
  2624.        if L = null then
  2625.            return (0);
  2626.        else
  2627.            return (1 + Length (Tail (L)));
  2628.        end if;
  2629.    end Length;
  2630.  
  2631. --------------------------------------------------------------------------
  2632.  
  2633.    function MakeListIter (L: in     List) return ListIter is
  2634.    
  2635.    --| Start an iteration operation on the list L.  Do a type conversion
  2636.    --| from List to ListIter.
  2637.     
  2638.    begin
  2639.        return ListIter (L);
  2640.    end MakeListIter;
  2641.  
  2642. --------------------------------------------------------------------------
  2643.  
  2644.    function More (L: in     ListIter) return boolean is
  2645.  
  2646.    --| This is a test to see whether an iteration is complete.
  2647.   
  2648.    begin
  2649.        return L /= null;
  2650.    end;
  2651.  
  2652. --------------------------------------------------------------------------
  2653.  
  2654.    procedure Next (Place:   in out ListIter;
  2655.                    Info:       out ItemType ) is
  2656.        PlaceInList: List;
  2657.    
  2658.    --| This procedure gets the information at the current place in the List
  2659.    --| and moves the ListIter to the next postion in the list.
  2660.    --| If we are at the end of a list then exception NoMore is raised.
  2661.  
  2662.    begin
  2663.        if Place = null then
  2664.       raise NoMore;
  2665.        else
  2666.           PlaceInList := List(Place);  
  2667.           Info := PlaceInList.Info;
  2668.           Place := ListIter(PlaceInList.Next);
  2669.        end if;
  2670.    end Next;
  2671.  
  2672. --------------------------------------------------------------------------
  2673.  
  2674.    procedure ReplaceHead (L:    in out  List;
  2675.                           Info: in      ItemType ) is
  2676.  
  2677.    --| This procedure replaces the information at the head of a list
  2678.    --| with the given information. If the list is empty the exception
  2679.    --| EmptyList is raised.
  2680.  
  2681.    begin
  2682.        if L = null then
  2683.        raise EmptyList;
  2684.        else
  2685.            L.Info := Info;
  2686.        end if;
  2687.    end ReplaceHead;
  2688.  
  2689. --------------------------------------------------------------------------
  2690.  
  2691.    procedure ReplaceTail (L:        in out List;
  2692.                           NewTail:  in     List  ) is
  2693.        Temp_L: List;
  2694.    
  2695.    --| This destroys the tail of a list and replaces the tail with
  2696.    --| NewTail.  If L is empty EmptyList is raised.
  2697.  
  2698.    begin
  2699.        Destroy(L.Next); 
  2700.        L.Next := NewTail; 
  2701.    exception
  2702.        when constraint_error =>
  2703.            raise EmptyList;
  2704.    end ReplaceTail;
  2705.  
  2706. --------------------------------------------------------------------------
  2707.  
  2708.     function Tail (L: in    List) return List is
  2709.  
  2710.     --| This returns the list which is the tail of L.  If L is null Empty
  2711.     --| List is raised.
  2712.  
  2713.     begin
  2714.     if L = null then
  2715.         raise EmptyList;
  2716.     else
  2717.         return L.Next;
  2718.     end if;
  2719.     end Tail;
  2720.     
  2721. --------------------------------------------------------------------------
  2722.     function Equal (List1: in    List;
  2723.                     List2: in    List ) return boolean is
  2724.  
  2725.         PlaceInList1: List;
  2726.         PlaceInList2: LIst;
  2727.     Contents1:    ItemType;
  2728.     Contents2:    ItemType;
  2729.  
  2730.     --| This function tests to see if two lists are equal.  Two lists
  2731.     --| are equal if for all the elements of List1 the corresponding
  2732.     --| element of List2 has the same value.  Thus if the 1st elements
  2733.     --| are equal and the second elements are equal and so up to n.
  2734.     --|  Thus a necessary condition for two lists to be equal is that
  2735.     --| they have the same number of elements.
  2736.  
  2737.     --| This function walks over the two list and checks that the
  2738.     --| corresponding elements are equal.  As soon as we reach 
  2739.     --| the end of a list (PlaceInList = null) we fall out of the loop.
  2740.     --| If both PlaceInList1 and PlaceInList2 are null after exiting the loop
  2741.     --| then the lists are equal.  If they both are not null the lists aren't 
  2742.     --| equal.  Note that equality on elements is based on a user supplied
  2743.     --| function Equal which is used to test for item equality.
  2744.  
  2745.     begin
  2746.         PlaceInList1 := List1;
  2747.         PlaceInList2 := List2;
  2748.         while   (PlaceInList1 /= null) and (PlaceInList2 /= null) loop
  2749.             if not Equal (PlaceInList1.Info, PlaceInList2.Info) then
  2750.                 return false;
  2751.             end if;
  2752.         PlaceInList1 := PlaceInList1.Next;
  2753.         PlaceInList2 := PlaceInList2.Next;
  2754.         end loop;
  2755.         return ((PlaceInList1 = null) and (PlaceInList2 = null) );
  2756.     end Equal;
  2757. end Lists;
  2758.  
  2759. --------------------------------------------------------------------------
  2760.  
  2761. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2762. --SET.SPC
  2763. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2764. -- $Source: /nosc/work/abstractions/set2/RCS/set.spc,v $
  2765. -- $Revision: 1.2 $ -- $Date: 85/02/01 12:07:55 $ -- $Author: ron $
  2766.  
  2767. with lists;   --| Implementation uses lists.
  2768. pragma elaborate(lists);
  2769.  
  2770. generic
  2771.     type elem_type is private;
  2772.     
  2773.       --| Component type of the set.
  2774.  
  2775.     with function equal(e1, e2: elem_type) return boolean is "=";
  2776.     
  2777.       --| equal is required to form an equality relation on elem_type.
  2778.  
  2779.       
  2780. package set_pkg is
  2781.  
  2782. --| Overview:
  2783. --| This package provides the set abstract data type.  All standard set
  2784. --| operations are provided.  Standard mathematical set notation is
  2785. --| employed to describe the effects of the operations.
  2786. --|
  2787. --| The component type, and an equality relation used for membership
  2788. --| tests, are generic formals of the package. The implementation isn't
  2789. --| particularly fast, since the only available information about the
  2790. --| component type is the equality relation. However, this shouldn't be a
  2791. --| concern unless the sets become large or speed becomes important.
  2792. --| See scalar_set_pkg, hashed_set_pkg and ordered_set_pkg for other
  2793. --| implementations.
  2794. --|
  2795. --| The following is a complete list of operations, written in the order
  2796. --| in which they appear in the spec.
  2797. --|
  2798. --| Constructors:
  2799. --|        create
  2800. --|        insert
  2801. --|        delete
  2802. --|        intersect
  2803. --|        union
  2804. --|        copy
  2805. --| Query Operations:
  2806. --|        equal
  2807. --|        is_empty
  2808. --|        is_member
  2809. --|        size
  2810. --| Iterators:
  2811. --|        make_members_iter, more, next
  2812. --| Heap Management:
  2813. --|        destroy
  2814.  
  2815. --| Notes:
  2816. --| Programmer: Ron Kownacki
  2817. --| One of a family of set packages:
  2818. --| sets, scalar sets, hashed sets, ordered sets
  2819.  
  2820.     type set is private;      --| The set abstract data type.
  2821.  
  2822.  
  2823.   -- Exceptions:
  2824.  
  2825.     no_more: exception;       --| Raised on incorrect use of an iterator.
  2826.  
  2827.   -- Iterators:
  2828.   
  2829.  
  2830.     type members_iter is private;  --| Members of a set in arbitrary order
  2831.  
  2832.     
  2833.   -- Constructors:
  2834.  
  2835.     function create
  2836.         return set;
  2837.  
  2838.       --| Effects:
  2839.       --| Return {}.  This operation is not strictly necessary, since an
  2840.       --| uninitialized set object is viewed as the empty set.
  2841.  
  2842.     procedure insert(s: in out set;
  2843.                      e: in     elem_type);
  2844.  
  2845.       --| Effects:
  2846.       --| Insert the element, e, into the set, s.
  2847.  
  2848.     procedure delete(s: in out set;
  2849.                      e: in     elem_type);
  2850.  
  2851.       --| Effects:
  2852.       --| If e is in s, then remove e from s.  Otherwise, no effect.
  2853.       
  2854.     function intersect(s1, s2: set)
  2855.     return set;
  2856.  
  2857.       --| Effects:
  2858.       --| Return {e | member(s1, e) and member(s2, e)}.
  2859.       
  2860.     function union(s1, s2: set)
  2861.     return set;
  2862.  
  2863.       --| Effects:
  2864.       --| Return {e | member(s1, e) or member(s2, e)}.
  2865.  
  2866.     function copy(s: set)
  2867.     return set;
  2868.   
  2869.       --| Effects:
  2870.       --| Returns a copy of s.  Subsequent changes to s will not be
  2871.       --| visible through the application of operations to the copy of s.
  2872.       --| Assignment or parameter passing without copying will result
  2873.       --| in a single set value being shared among objects.
  2874.       --| The assignment operation is used to transfer the values of
  2875.       --| the elem_type components of s; consequently, changes in these
  2876.       --| values may be observable through both sets if these types are
  2877.       --| access types, or if they contain access type components.
  2878.   
  2879.  
  2880.   -- Query Operations:
  2881.  
  2882.     function equal(s1, s2: set)
  2883.         return boolean;
  2884.  
  2885.       --| Effects:
  2886.       --| Return (for all e: elem_type (member(s1, e) iff member(s2, e))).
  2887.       --| Note that (s1 = s2) implies equal(s1, s2) holds for all time.
  2888.       --| "=" is object equality, equal is state equality.
  2889.  
  2890.     function is_empty(s: set)
  2891.         return boolean;
  2892.  
  2893.       --| Effects:
  2894.       --| Return s = {}.
  2895.  
  2896.     function is_member(s: set;
  2897.                        e: elem_type)
  2898.         return boolean;
  2899.  
  2900.       --| Effects:
  2901.       --| Return true iff e is a member of s.
  2902.  
  2903.     function size(s: set)
  2904.         return natural;
  2905.  
  2906.       --| Effects:
  2907.       --| Return |s|, the cardinality of s.
  2908.  
  2909.  
  2910.   -- Iterators:
  2911.  
  2912.     function make_members_iter(s: set)
  2913.         return members_iter;
  2914.  
  2915.       --| Effects:
  2916.       --| Create and return a members iterator based on s.  This object
  2917.       --| can then be used in conjunction with the more function and the
  2918.       --| next procedure to iterate over the members of s in some
  2919.       --| arbitrary order.
  2920.  
  2921.     function more(iter: members_iter)
  2922.         return boolean;
  2923.  
  2924.       --| Effects:
  2925.       --| Return true iff the members iterator has not been exhausted.
  2926.  
  2927.     procedure next(iter: in out members_iter;
  2928.                    e:    out    elem_type);
  2929.  
  2930.       --| Raises: no_more
  2931.       --| Effects:
  2932.       --| Let iter be based on the set, s.  Successive calls of next
  2933.       --| will return the members of s in some arbitrary order.
  2934.       --| After all members have been returned, then the procedure will
  2935.       --| raise no_more.
  2936.       --| Requires:
  2937.       --| s must not be changed between the invocations of
  2938.       --| make_nodes_iterator(g) and next.
  2939.  
  2940.  
  2941.   -- Heap management:
  2942.  
  2943.     procedure destroy(s: in out set);
  2944.     
  2945.       --| Effects:
  2946.       --| Return space consumed by the set value associated with object
  2947.       --| s to the heap.  If other objects share the same set value, then
  2948.       --| further use of these objects is erroneous.  Components of type
  2949.       --| elem_type, if they are access types, are not garbage collected.
  2950.       --| It is the user's responsibility to dispose of these objects.
  2951.       --| s is set to {}.
  2952.  
  2953.  
  2954. private
  2955.  
  2956.     package list_pkg is new lists(elem_type, equal);
  2957.     use list_pkg;
  2958.     
  2959.     type set is new list;
  2960.  
  2961.       --| Representation Invariants:
  2962.       --|   None; all lists are legal representations of sets.
  2963.       --| Abstraction Function:  A: representation --> set
  2964.       --|   A(null) = create.
  2965.       --|   A(attach(r, e)) = insert(A(r), e).
  2966.       --|   Sufficient since all lists can be generated by null, attach.
  2967.       --|
  2968.       --|     Note that this implementation allows faster insertion and
  2969.       --| membership testing than if duplicate insertions of an element
  2970.       --| caused a check to ensure that each element is only kept once in
  2971.       --| the list.  This implies that deleting an element always involves
  2972.       --| a scan of the entire list.
  2973.     
  2974.     type members_iter is new list;
  2975.  
  2976.       --| For a set, s, make returns members_iter(copy(list(s))).
  2977.       --| More(iter) returns true iff list(iter) isn't empty.
  2978.       --| Next(iter) returns the first element in list(iter).  Before doing 
  2979.       --| this, it removes all occurrences of this element from list(iter).
  2980.  
  2981. end set_pkg;
  2982.  
  2983. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2984. --HASHMAP.SPC
  2985. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2986. -- $Source: /nosc/work/abstractions/mapping/RCS/hash_map.spc,v $
  2987. -- $Revision: 1.2 $ -- $Date: 85/02/01 13:24:20 $ -- $Author: ron $
  2988.  
  2989. with lists;       -- Lists used in implementation.  (private)
  2990. pragma elaborate(lists);
  2991.  
  2992. generic
  2993.     type key_type is private;
  2994.     
  2995.       --| Domain type of the mapping.
  2996.       
  2997.      with function equal(k1, k2: key_type) return boolean is "=";
  2998.       
  2999.       --| equal is required to form an equality relation on key_type.
  3000.     
  3001.      type bucket_range is range <>;
  3002.  
  3003.       --| Defines the number of hash buckets, one for each member of
  3004.       --| bucket_range.
  3005.       
  3006.      with function hash(k: key_type) return bucket_range;
  3007.     
  3008.       --| Required property: equal(e1, e2) => hash(e1) = hash(e2).
  3009.       --| Best results if hash produces a uniform distribution
  3010.       --| over bucket_range.
  3011.     
  3012.      type value_type is private;
  3013.     
  3014.       --| Target type of the mapping.
  3015.     
  3016.     
  3017. package hashed_mapping_pkg is
  3018.  
  3019. --| Overview:
  3020. --| This package provides a mapping from one arbitrary type, key_type, to
  3021. --| another arbitrary type, value_type.  These types are generic formals
  3022. --| to the package, along with an equality relation on key_type, an
  3023. --| integer subtype that determines the number of hash buckets, and a
  3024. --| hashing function on key_type that maps to that integer subtype.
  3025. --|
  3026. --| For the purpose of specifying the operations in this package, we will
  3027. --| view a mapping as a set of bindings, or key/value pairs.  This allows
  3028. --| the use of set notation in description.
  3029. --|
  3030. --| The following is a complete list of operations, written in the order
  3031. --| in which they appear in the spec.
  3032. --|
  3033. --| Constructors:
  3034. --|        create
  3035. --|        bind
  3036. --|        unbind
  3037. --|        copy
  3038. --| Query Operations:
  3039. --|        is_empty
  3040. --|        size
  3041. --|        is_bound
  3042. --|        fetch
  3043. --| Iterators:
  3044. --|        make_keys_iter, more, next
  3045. --|        make_values_iter, more, next
  3046. --|        make_bindings_iter, more, next
  3047. --| Heap Management:
  3048. --|        destroy
  3049.  
  3050. --| Notes:
  3051. --| Programmer: Ron Kownacki
  3052.  
  3053.  
  3054.     type mapping is private;    --| The hashed mapping abstract data type.
  3055.  
  3056.  
  3057.   -- Exceptions:
  3058.  
  3059.     no_more: exception;
  3060.       --| Raised on incorrect use of an iterator.
  3061.  
  3062.     uninitialized_mapping: exception;
  3063.         --| Raised on use of an unitialized mapping by most operations.
  3064.       
  3065.     already_bound: exception;
  3066.         --| Raised on attempt to rebind a key that is currently bound.
  3067.  
  3068.     not_bound: exception;
  3069.         --| Raised when a key that is expected to be bound is unbound.
  3070.  
  3071.   -- Iterators:
  3072.  
  3073.     type keys_iter is private;     --| Bound keys in arbitrary order.
  3074.     type values_iter is private;   --| Bound values in arbitrary order.
  3075.     type bindings_iter is private; --| Key,value pairs in arbitrary order
  3076.  
  3077.  
  3078.   -- Constructors:
  3079.  
  3080.     function create
  3081.         return mapping;
  3082.  
  3083.       --| Effects:
  3084.       --| Return {}.
  3085.  
  3086.     procedure bind(map:   in out mapping;
  3087.                    key:   in     key_type;
  3088.                    value: in     value_type);
  3089.  
  3090.       --| Raises: already_bound, uninitialized_mapping
  3091.       --| Effects:
  3092.       --| Insert the binding, <key, value>, into map.  Raises
  3093.       --| already_bound iff a pair, <k', v'>, where equal(key, k'),
  3094.       --| is in map.
  3095.       --| Raises uninitialized_mapping iff map has not been initialized.
  3096.  
  3097.     procedure unbind(map: in out mapping;
  3098.                      key: in     key_type);
  3099.  
  3100.       --| Raises: not_bound, uninitialized_mapping
  3101.       --| Effects:
  3102.       --| If <k, v>, where equal(key, k), is in map, then removes
  3103.       --| <k, v> from map.  Raises not_bound if no such pair exists.
  3104.       --| Raises uninitialized_mapping iff map has not been initialized.
  3105.       
  3106.     function copy(map: mapping)
  3107.     return mapping;
  3108.   
  3109.       --| Raises: uninitialized_mapping
  3110.       --| Effects:
  3111.       --| Returns a copy of map.  Subsequent changes to map will not be
  3112.       --| visible through applying operations to the copy of map.
  3113.       --| Assignment or parameter passing without copying will result
  3114.       --| in a single mapping value being shared among mapping objects.
  3115.       --| Raises uninitialized_mapping iff map has not been initialized.
  3116.       --| The assignment operation is used to transfer the values of the
  3117.       --| key_type and value_type type components of map; consequently,
  3118.       --| changes in the values of these types may be observable through
  3119.       --| both mappings if these are access types, or if they contain
  3120.       --| components of an access type.
  3121.   
  3122.  
  3123.   -- Query Operations:
  3124.  
  3125.     function is_empty(map: mapping)
  3126.         return boolean;
  3127.  
  3128.       --| Raises: uninitialized_mapping
  3129.       --| Effects:
  3130.       --| Return map = {}.
  3131.       --| Raises uninitialized_mapping iff map has not been initialized.
  3132.  
  3133.     function size(map: mapping)
  3134.         return natural;
  3135.  
  3136.       --| Raises: uninitialized_mapping
  3137.       --| Effects:
  3138.       --| Return |map|, the number of bindings in map.
  3139.       --| Raises uninitialized_mapping iff map has not been initialized.
  3140.  
  3141.     function is_bound(map: mapping;
  3142.                       key: key_type)
  3143.     return boolean;
  3144.               
  3145.        --| Raises: uninitialized_mapping
  3146.        --| Return true iff equal(key, k) for some <k, v> in map.
  3147.        --| Raises uninitialized_mapping iff map has not been initialized.
  3148.     
  3149.     function fetch(map: mapping;
  3150.                    key: key_type)
  3151.     return value_type;
  3152.     
  3153.       --| Raises: not_bound, uninitialized_mapping
  3154.       --| If <k, v>, where equal(key, k), is in map, then return v.
  3155.       --| Raises not_bound if no such <k, v> exists.
  3156.       --| Raises uninitialized_mapping iff map has not been initialized.
  3157.  
  3158.  
  3159.   -- Iterators:
  3160.  
  3161.     function make_keys_iter(map: mapping)
  3162.         return keys_iter;
  3163.  
  3164.       --| Raises: uninitialized_mapping
  3165.       --| Effects:
  3166.       --| Create and return a keys iterator based on map.  This object
  3167.       --| can then be used in conjunction with the more function and the
  3168.       --| next procedure to iterate over all keys that are bound in map.
  3169.       --| Raises uninitialized_mapping iff map has not been initialized.
  3170.  
  3171.     function more(iter: keys_iter)
  3172.         return boolean;
  3173.  
  3174.       --| Effects:
  3175.       --| Return true iff the keys iterator has not been exhausted.
  3176.  
  3177.     procedure next(iter: in out keys_iter;
  3178.                    key:  out    key_type);
  3179.  
  3180.       --| Raises: no_more
  3181.       --| Effects:
  3182.       --| Let iter be based on the mapping, map.  Successive calls of next
  3183.       --| will return the bound keys of map in some arbitrary order.
  3184.       --| After all bound keys have been returned, then the procedure will
  3185.       --| raise no_more.
  3186.       --| Requires:
  3187.       --| map must not be changed between the invocations of
  3188.       --| make_keys_iterator(map) and next.
  3189.       
  3190.     function make_values_iter(map: mapping)
  3191.     return values_iter;
  3192.  
  3193.       --| Raises: uninitialized_mapping
  3194.       --| Effects:
  3195.       --| Create and return a values iterator based on map.  This object
  3196.       --| can then be used in conjunction with the more function and the
  3197.       --| next procedure to iterate over all values that are bound to keys
  3198.       --| in map.
  3199.       --| Raises uninitialized_mapping iff map has not been initialized.
  3200.   
  3201.     function more(iter: values_iter)
  3202.     return boolean;
  3203.   
  3204.       --| Effects:
  3205.       --| Return true iff the values iterator has not been exhausted.
  3206.   
  3207.     procedure next(iter: in out values_iter;
  3208.            val:  out    value_type);
  3209.            
  3210.       --| Raises: no_more
  3211.       --| Effects:
  3212.       --| Let iter be based on the mapping, map.  Successive calls of next
  3213.       --| will return the bound values of map in some arbitrary order.
  3214.       --| After all bound values have been returned, then the procedure
  3215.       --| will raise no_more.
  3216.       --| Requires:
  3217.       --| map must not be changed between the invocations of
  3218.       --| make_values_iterator(map) and next.
  3219.     
  3220.     function make_bindings_iter(map: mapping)
  3221.     return bindings_iter;
  3222.   
  3223.       --| Raises: uninitialized_mapping
  3224.       --| Effects:
  3225.       --| Create and return a bindings iterator based on map.  This object
  3226.       --| can then be used in conjunction with the more function and the
  3227.       --| next procedure to iterate over all key/value pairs in map.
  3228.       --| Raises uninitialized_mapping iff map has not been initialized.
  3229.     
  3230.     function more(iter: bindings_iter)
  3231.     return boolean;
  3232.     
  3233.       --| Effects:
  3234.       --| Return true iff the bindings iterator has not been exhausted.
  3235.     
  3236.     procedure next(iter: in out bindings_iter;
  3237.            key:  out    key_type;
  3238.            val:  out    value_type);
  3239.              
  3240.       --| Raises: no_more
  3241.       --| Effects:
  3242.       --| Let iter be based on the mapping, map.  Successive calls of next
  3243.       --| will return the key/value pairs of map in some arbitrary order.
  3244.       --| After all such pairs have been returned, then the procedure will
  3245.       --| raise no_more.
  3246.       --| Requires:
  3247.       --| map must not be changed between the invocations of
  3248.       --| make_bindings_iterator(map) and next.
  3249.     
  3250.     
  3251.   -- Heap management:
  3252.  
  3253.     procedure destroy(m: in out mapping);
  3254.     
  3255.       --| Effects:
  3256.       --| Return space consumed by mapping value associated with object
  3257.       --| m to the heap.  (If m is uninitialized, this operation does
  3258.       --| nothing.)  If other objects share the same mapping value, the
  3259.       --| further use of these objects is erroneous.  Components of type
  3260.       --| value_type, if they are access types, are not garbage collected.
  3261.       --| It is the user's responsibility to dispose of these objects.
  3262.       --| m is left in the uninitialized state.
  3263.  
  3264.       
  3265. private
  3266.  
  3267.     type component is record
  3268.         key: key_type;
  3269.     val: value_type;
  3270.     end record;
  3271.     
  3272.     function equal(c1, c2: component) return boolean;
  3273.         --| Effects: Return true iff equal(c1.key, c2.key).
  3274.     
  3275.     package bucket_pkg is new lists(component, equal);
  3276.     use bucket_pkg;
  3277.     
  3278.     
  3279.     type bucket_array is array(bucket_range) of list;
  3280.     
  3281.     type mapping_rec is record
  3282.         size: natural;
  3283.         buckets: bucket_array;
  3284.     end record;
  3285.     
  3286.     type mapping is access mapping_rec;
  3287.     
  3288.     --| Representation Invariants:
  3289.     --| 1. r /= null.  (This would be the uninitialized case)
  3290.     --| 2. If for some i, a component, c, is in bucket r.buckets(i),
  3291.     --|    then hash(c.key) = i.
  3292.     --| 3. If a component, c1, is in bucket, r.buckets(i), then there is
  3293.     --|    no other c2 in r.buckets(i) such that equal(c1, c2).
  3294.     --|    (Enforce one binding to a given key at any time.)
  3295.     --| 4. r.size equals the total number of components in buckets
  3296.     --|    r.buckets(bucket_range'first) through
  3297.     --|    r.buckets(bucket_range'last).
  3298.     --|
  3299.     --| Abstraction Function:
  3300.     --| A(r) is the set consisting of all key, value pairs that appear as
  3301.     --| components in buckets r.buckets(bucket_range'first) through
  3302.     --| r.buckets(bucket_range'last).
  3303.     
  3304.     
  3305.     type general_iter is record
  3306.         map: mapping;
  3307.     current: bucket_range;
  3308.     position: list;
  3309.     end record;
  3310.     
  3311.     --| For a given general_iter, i, the make, more and next operations
  3312.     --| have the following effects:
  3313.     --| make: Sets map field to the given mapping, sets i.current to the
  3314.     --| lowest idx of a nonempty bucket, and sets i.position to the head
  3315.     --| of that bucket.
  3316.     --| more: Returns not empty(i.position).
  3317.     --| next: key, val fields of first component of i.position.
  3318.     --| Advances i.position to next component in bucket, if it exists.
  3319.     --| Otherwise, increments i.current until a nonempty bucket, and sets
  3320.     --| i.position to this bucket.  When this fails, sets i.position to an
  3321.     --| empty bucket.
  3322.     
  3323.     
  3324.     type keys_iter is new general_iter;
  3325.     type values_iter is new general_iter;
  3326.     type bindings_iter is new general_iter;
  3327.     
  3328. end hashed_mapping_pkg;
  3329.  
  3330. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3331. --SET.BDY
  3332. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3333. -- $Source: /nosc/work/abstractions/set2/RCS/set.bdy,v $
  3334. -- $Revision: 1.2 $ -- $Date: 85/02/01 12:07:30 $ -- $Author: ron $
  3335.  
  3336. package body set_pkg is
  3337.  
  3338. --| Overview:
  3339. --| See the package spec, private part, for the representation invariants
  3340. --| and abstraction function for sets.  These define the implementation
  3341. --| scheme.
  3342.  
  3343.  
  3344.   -- Constructors:
  3345.  
  3346.     function create
  3347.         return set is
  3348.     begin
  3349.         return set(list'(create));
  3350.     end create;
  3351.  
  3352.     procedure insert(s: in out set;
  3353.                      e: in     elem_type) is
  3354.     begin
  3355.     s := set(attach(e, list(s)));
  3356.     end insert;
  3357.  
  3358.  
  3359.     procedure delete(s: in out set;
  3360.                      e: in     elem_type) is
  3361.     begin
  3362.     DeleteItems(list(s), e);
  3363.     exception
  3364.         when ItemNotPresent =>
  3365.             null;
  3366.     end delete;
  3367.     
  3368.     function intersect(s1, s2: set)
  3369.     return set is
  3370.     intersect_list: list := create;
  3371.     iter: ListIter;
  3372.     e: elem_type;
  3373.     begin
  3374.     iter := MakeListIter(list(s1));
  3375.     while more(iter) loop
  3376.         next(iter, e);
  3377.         if IsInList(list(s2), e) then
  3378.         intersect_list := attach(intersect_list, e);
  3379.         end if;
  3380.     end loop;
  3381.     return set(intersect_list);
  3382.     end intersect;
  3383.  
  3384.     function union(s1, s2: set)
  3385.     return set is
  3386.     union_list: list;
  3387.     begin
  3388.     return set(attach(copy(list(s1)), copy(list(s2))));
  3389.     end union;
  3390.  
  3391.     function copy(s: set)
  3392.     return set is
  3393.     begin
  3394.     return set(copy(list(s)));
  3395.     end copy;
  3396.   
  3397.  
  3398.   -- Query Operations:
  3399.  
  3400.     function equal(s1, s2: set)
  3401.         return boolean is
  3402.         iter: members_iter;
  3403.         e: elem_type;
  3404.     begin
  3405.         -- s2 contains s1?
  3406.         iter := make_members_iter(s1);
  3407.         while more (iter) loop 
  3408.             next(iter, e); 
  3409.             if not is_member(s2, e) then return false; end if; 
  3410.         end loop;
  3411.  
  3412.         -- s1 contains s2?
  3413.         iter := make_members_iter(s2);
  3414.         while more (iter) loop 
  3415.             next(iter, e); 
  3416.             if not is_member(s1, e) then return false; end if; 
  3417.         end loop;
  3418.  
  3419.         -- s2 contains s1 and s1 contains s2 => equal(s1 = s2)
  3420.         return true;
  3421.     end equal;
  3422.  
  3423.     function is_empty(s: set)
  3424.         return boolean is
  3425.     begin
  3426.     return IsEmpty(list(s));
  3427.     end is_empty;
  3428.  
  3429.     function is_member(s: set;
  3430.                        e: elem_type)
  3431.         return boolean is
  3432.     begin
  3433.         return IsInList(list(s), e);
  3434.     end is_member;
  3435.  
  3436.     function size(s: set)
  3437.         return natural is
  3438.     l: list := copy(list(s));
  3439.     count: natural := 0;
  3440.     begin
  3441.     while not IsEmpty(l) loop
  3442.         count := count + 1;
  3443.         DeleteItems(l, FirstValue(l));
  3444.     end loop;
  3445.     return count;
  3446.     end size;
  3447.     
  3448.  
  3449.   -- Iterators:
  3450.  
  3451.     function make_members_iter(s: set)
  3452.         return members_iter is
  3453.     begin
  3454.         return members_iter(copy(list(s)));
  3455.     end make_members_iter;
  3456.  
  3457.     function more(iter: members_iter)
  3458.         return boolean is
  3459.     begin
  3460.     return not IsEmpty(list(iter));
  3461.     end more;
  3462.     
  3463.     procedure next(iter: in out members_iter;
  3464.                    e:    out    elem_type) is
  3465.         e2: elem_type;
  3466.     begin
  3467.         e := FirstValue(list(iter));
  3468.         DeleteItems(list(iter), FirstValue(list(iter)));
  3469.     exception
  3470.         when EmptyList =>
  3471.         raise no_more;
  3472.     end next;
  3473.  
  3474.  
  3475. -- Heap Management:
  3476.  
  3477.     procedure destroy(s: in out set) is
  3478.     begin
  3479.     destroy(list(s));
  3480.     end destroy;
  3481.  
  3482. end set_pkg;
  3483.  
  3484. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3485. --HASHMAP.BDY
  3486. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3487. -- $Source: /nosc/work/abstractions/mapping/RCS/hash_map.bdy,v $
  3488. -- $Revision: 1.3 $ -- $Date: 85/02/01 14:48:43 $ -- $Author: ron $
  3489.  
  3490. with unchecked_deallocation;
  3491.  
  3492. package body hashed_mapping_pkg is
  3493.     
  3494.     function equal(c1, c2: component)
  3495.     return boolean is
  3496.     begin
  3497.     return equal(c1.key, c2.key);
  3498.     end equal;
  3499.     
  3500.       
  3501.   -- Utilities:
  3502.     
  3503.     procedure free is new unchecked_deallocation(mapping_rec, mapping);
  3504.      
  3505.     function make_general_iter(map: mapping)
  3506.     return general_iter;
  3507.       --| Raises: uninitialized_mapping
  3508.       --| Effects:
  3509.       --| Create and return a general iterator based on map.  Sets up
  3510.       --| map, current and position fields as in the spec.
  3511.       --| Raises uninitialized_mapping iff map has not been initialized.
  3512.   
  3513.     function more(iter: general_iter)
  3514.     return boolean;
  3515.       --| Effects:
  3516.       --| Returns true iff the general iter has not been exhausted, i.e.,
  3517.       --| returns not IsEmpty(iter.position).
  3518.        
  3519.     procedure advance(iter: in out general_iter);
  3520.       --| Effects:
  3521.       --| Advances iter.position, and if necessary, iter.current to the
  3522.       --| next component, as detailed in the spec.  iter.position will
  3523.       --| be empty if no more elements remain to be iterated over.
  3524.       --| Requires:
  3525.       --| iter.position is not null, i.e., caller has determined that iter
  3526.       --| was not exhausted before calling advance.
  3527.  
  3528.  
  3529.   -- Constructors:
  3530.  
  3531.     function create
  3532.         return mapping is
  3533.         m: mapping;
  3534.     begin
  3535.         -- deleted because of Decada bug:
  3536. --      return new mapping_rec'(size => 0,
  3537. --                              buckets => (bucket_range => create));
  3538.         m := new mapping_rec; 
  3539.         m.size := 0;
  3540.         m.all.buckets := (bucket_array'range => create);
  3541.         return m;
  3542.     end create;
  3543.  
  3544.     procedure bind(map:   in out mapping;
  3545.                    key:   in     key_type;
  3546.                    value: in     value_type) is
  3547.     idx: bucket_range := hash(key);
  3548.     c: component := (key => key, val => value);
  3549.     begin
  3550.     if IsInList(map.buckets(idx), c) then
  3551.         raise already_bound;
  3552.     end if;
  3553.     
  3554.     map.buckets(idx) := attach(c, map.buckets(idx));
  3555.     map.size := map.size + 1;
  3556.     
  3557.     exception
  3558.         when constraint_error =>       -- null dereference
  3559.         raise uninitialized_mapping;
  3560.     end bind;
  3561.  
  3562.     procedure unbind(map: in out mapping;
  3563.                      key: in     key_type) is
  3564.     idx: bucket_range := hash(key);
  3565.     tmpc: component;
  3566.     begin
  3567.     tmpc.key := key;   -- don't need a value, equality just tests keys
  3568.     DeleteItem(map.buckets(idx), tmpc);
  3569.     map.size := map.size - 1;
  3570.     
  3571.     exception
  3572.         when ItemNotPresent =>
  3573.             raise not_bound;
  3574.     when constraint_error =>       -- null dereference
  3575.         raise uninitialized_mapping;
  3576.     end unbind;
  3577.       
  3578.     function copy(map: mapping)
  3579.     return mapping is
  3580.     new_map: mapping;
  3581.     begin
  3582.     if map = null then raise uninitialized_mapping; end if;
  3583.     
  3584.     new_map := new mapping_rec;
  3585.     new_map.size := map.size;
  3586.     for idx in bucket_range loop
  3587.         new_map.buckets(idx) := copy(map.buckets(idx));
  3588.     end loop;
  3589.     return new_map;
  3590.     end copy;
  3591.   
  3592.  
  3593.   -- Query Operations:
  3594.  
  3595.     function is_empty(map: mapping)
  3596.         return boolean is
  3597.     begin
  3598.     return map.size = 0;
  3599.     exception
  3600.     when constraint_error =>       -- null dereference
  3601.         raise uninitialized_mapping;
  3602.     end is_empty;
  3603.  
  3604.     function size(map: mapping)
  3605.         return natural is
  3606.     begin
  3607.     return map.size;
  3608.     exception
  3609.     when constraint_error =>       -- null dereference
  3610.         raise uninitialized_mapping;
  3611.     end size;
  3612.  
  3613.     function is_bound(map: mapping;
  3614.                       key: key_type)
  3615.     return boolean is
  3616.     tmpc: component;
  3617.     begin
  3618.     tmpc.key := key;   -- don't need a value, equality just tests keys
  3619.     return IsInList(map.buckets(hash(key)), tmpc);
  3620.     exception
  3621.         when constraint_error =>     -- null dereference
  3622.         raise uninitialized_mapping;
  3623.     end is_bound;
  3624.     
  3625.     function fetch(map: mapping;
  3626.                    key: key_type)
  3627.     return value_type is
  3628.     buck: list;
  3629.     begin
  3630.     buck := map.buckets(hash(key));
  3631.  
  3632.     while not IsEmpty(buck) loop
  3633.             if equal(key, FirstValue(buck).key) then
  3634.         return FirstValue(buck).val;
  3635.         end if;
  3636.         buck := tail(buck);
  3637.     end loop;
  3638.     raise not_bound;
  3639.     
  3640.     exception
  3641.     when constraint_error =>       -- null dereference
  3642.         raise uninitialized_mapping;
  3643.     end fetch;
  3644.  
  3645.  
  3646.   -- Iterators:
  3647.   
  3648.     function make_keys_iter(map: mapping)
  3649.         return keys_iter is
  3650.     begin
  3651.     return keys_iter(make_general_iter(map));
  3652.     end make_keys_iter;
  3653.  
  3654.     function more(iter: keys_iter)
  3655.         return boolean is
  3656.     begin
  3657.     return more(general_iter(iter));
  3658.     end more;
  3659.  
  3660.     procedure next(iter: in out keys_iter;
  3661.                    key:  out    key_type) is
  3662.     begin
  3663.     key := FirstValue(iter.position).key;
  3664.     advance(general_iter(iter));
  3665.     exception
  3666.         when EmptyList =>
  3667.         raise no_more;
  3668.     end next;
  3669.  
  3670.     function make_values_iter(map: mapping)
  3671.     return values_iter is
  3672.     begin
  3673.     return values_iter(make_general_iter(map));
  3674.     end make_values_iter;
  3675.  
  3676.     function more(iter: values_iter)
  3677.     return boolean is
  3678.     begin
  3679.     return more(general_iter(iter));
  3680.     end more;
  3681.     
  3682.     procedure next(iter: in out values_iter;
  3683.            val:  out    value_type) is
  3684.     begin
  3685.     val := FirstValue(iter.position).val;
  3686.     advance(general_iter(iter));
  3687.     exception
  3688.         when EmptyList =>
  3689.         raise no_more;
  3690.     end next;
  3691.     
  3692.     function make_bindings_iter(map: mapping)
  3693.     return bindings_iter is
  3694.     begin
  3695.         return bindings_iter(make_general_iter(map));
  3696.     end make_bindings_iter;
  3697.   
  3698.     function more(iter: bindings_iter)
  3699.     return boolean is
  3700.     begin
  3701.     return more(general_iter(iter));
  3702.     end more;
  3703.     
  3704.     procedure next(iter: in out bindings_iter;
  3705.            key:  out    key_type;
  3706.            val:  out    value_type) is
  3707.     comp: component;
  3708.     begin
  3709.     comp := FirstValue(iter.position);
  3710.     key := comp.key;
  3711.     val := comp.val;
  3712.     advance(general_iter(iter));
  3713.     exception
  3714.         when EmptyList =>
  3715.         raise no_more;
  3716.     end next;
  3717.     
  3718.     
  3719.   -- Heap management:
  3720.  
  3721.     procedure destroy(m: in out mapping) is
  3722.     begin
  3723.         for i in bucket_range loop
  3724.             destroy(m.buckets(i));
  3725.         end loop;
  3726.         free(m);
  3727.     exception
  3728.         when constraint_error =>    -- m is null
  3729.         return;
  3730.     end destroy;
  3731.  
  3732.  
  3733. -- Utilities:
  3734.     
  3735.     function make_general_iter(map: mapping)
  3736.     return general_iter is
  3737.     iter: general_iter;
  3738.     begin
  3739.     if map = null then raise uninitialized_mapping; end if;
  3740.     
  3741.     for idx in bucket_range loop
  3742.         if not IsEmpty(map.buckets(idx)) then
  3743.         iter.map := map;
  3744.         iter.current := idx;
  3745.         iter.position := map.buckets(idx);
  3746.         return iter;
  3747.         end if;
  3748.     end loop;
  3749.     
  3750.     iter.position := create;   -- no elements, makes next(iter) false.
  3751.     return iter;
  3752.     end make_general_iter;
  3753.     
  3754.     function more(iter: general_iter)
  3755.     return boolean is
  3756.     begin
  3757.     return not IsEmpty(iter.position);
  3758.     end more;
  3759.     
  3760.     procedure advance(iter: in out general_iter) is
  3761.     begin
  3762.     iter.position := tail(iter.position);
  3763.         if IsEmpty(iter.position) and then iter.current /= bucket_range'last then
  3764.         for idx in iter.current + 1..bucket_range'last loop
  3765.         if not IsEmpty(iter.map.buckets(idx)) then
  3766.             iter.current := idx;
  3767.             iter.position := iter.map.buckets(idx);
  3768.             return;
  3769.         end if;
  3770.         end loop;
  3771.         end if;        
  3772.         -- At this point, IsEmpty(iter.position) => not more(iter)
  3773.     end advance;
  3774.     
  3775. end hashed_mapping_pkg;
  3776.  
  3777. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3778. --DAG.SPC
  3779. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3780. -- $Source: /nosc/work/abstractions/dag/RCS/dag.spc,v $
  3781. -- $Revision: 1.12 $ -- $Date: 85/02/04 12:58:36 $ -- $Author: ron $
  3782.  
  3783. -- $Source: /nosc/work/abstractions/dag/RCS/dag.spc,v $
  3784. -- $Revision: 1.12 $ -- $Date: 85/02/04 12:58:36 $ -- $Author: ron $
  3785.  
  3786. with set_pkg,             --| Used in the implementation.  (private)
  3787.      lists,               --| Used in the implementation.  (private)
  3788.      hashed_mapping_pkg,  --| Used in the implementation.  (private)
  3789.      text_io;             --| Used in interface to put_image.
  3790.  
  3791.      pragma elaborate(set_pkg);
  3792.      pragma elaborate(lists);
  3793.      pragma elaborate(hashed_mapping_pkg);
  3794.  
  3795. generic
  3796.     type label is private;
  3797.       --| Labels of nodes.  
  3798.  
  3799.     with function equal(l1, l2: label) return boolean is "=";
  3800.       --| equal is required to form an equality relation on label.
  3801.  
  3802.     type value is private;
  3803.       --| Values of nodes.  The assignment operation is assumed to be
  3804.       --| available, i.e., value is not limited.
  3805.       
  3806.  -- The following formals allow a faster implementation:
  3807.       
  3808.     type bucket_range is range <>;
  3809.  
  3810.      --| Defines the number of hash buckets, one for each member of
  3811.      --| bucket_range.
  3812.        
  3813.     with function hash(l: label) return bucket_range;
  3814.      
  3815.      --| Required property: equal(l1, l2) => hash(l1) = hash(l2).
  3816.      --| Best results if hash produces a uniform distribution
  3817.      --| over bucket_range.
  3818.      
  3819.  
  3820. package dag_pkg is
  3821.  
  3822. --| Overview:
  3823. --| This package provides the dag abstract data type.  A dag is a directed
  3824. --| acyclic graph.  A directed graph is a set of nodes and a set of
  3825. --| directed edges connecting pairs of nodes.  A directed graph, g, is
  3826. --| acyclic iff for each node, n, in g, there is no sequence of edges in g
  3827. --| that leads to n.  This package maintains acyclicity.
  3828. --|
  3829. --| The nodes consist of labels and their associated values.  Both types
  3830. --| are generic formals.  There are no explicit bounds on the size
  3831. --| of dags, as they are implemented on the heap.  All standard graph
  3832. --| operations are provided.
  3833. --|
  3834. --| In the description of this package, we will denote a dag, g, by the
  3835. --| pair, <labels, edges>.  For a given label, l, value(l) is the value
  3836. --| that is associated with the node labelled l.  An edge, from nodes
  3837. --| with labels l1 and l2, is written as (l1, l2).  Dot selection notation
  3838. --| is used to refer to the components of a dag, e.g., g.labels and
  3839. --| g.edges.
  3840. --|
  3841. --| The following is a complete list of operations, written in the order
  3842. --| in which they appear in the spec.  Overloaded subprograms are followed
  3843. --| by (n), where n is the number of subprograms of that name.
  3844. --|
  3845. --| Constructors:
  3846. --|        create
  3847. --|        add_node, add_edge
  3848. --|        set_value
  3849. --|        copy
  3850. --| Query Operations:
  3851. --|        is_empty
  3852. --|        is_root, is_leaf
  3853. --|        is_successor, is_descendent
  3854. --|        get_value
  3855. --|        root_count, node_count, edge_count, pred_count, succ_count
  3856. --|        put_image
  3857. --| Iterators:
  3858. --|        make_nodes_iter, more, next (2)
  3859. --|        make_edges_iter, more, next
  3860. --|        make_roots_iter, more, next (2)
  3861. --|        make_leaves_iter, more, next (2)
  3862. --|        make_preds_iter, more, next (2)
  3863. --|        make_succs_iter, more, next (2)
  3864. --|        make_preorder_iter (2), more, next (2)
  3865. --|        make_postorder_iter (2), more, next (2)
  3866. --| Heap Managment:
  3867. --|        destroy_dag
  3868. --|        destroy_dag_and_labels
  3869. --|        destroy_dag_and_values
  3870. --|        destroy_dag_and_nodes
  3871.  
  3872. --| Notes:
  3873. --| Programmer: Ron Kownacki
  3874.  
  3875.  
  3876.     type dag is private;    --| The dag abstract data type.
  3877.  
  3878.  
  3879.   -- Exceptions:
  3880.  
  3881.     no_more: exception;       --| Raised on incorrect use of an iterator.
  3882.  
  3883.     illegal_node: exception;  --| Raised when a node is not in a dag,
  3884.                               --| or when it is and shouldn't be.
  3885.  
  3886.     duplicate_edge: exception; --| Rasised by add_ege on attempt to
  3887.                                --| add an edge that is already there.
  3888.  
  3889.     makes_cycle: exception;   --| Raised if new edge would cause a cycle.
  3890.  
  3891.     uninitialized_dag: exception;
  3892.         --| Raised on use of an uninitialized dag by most operations.
  3893.  
  3894.  
  3895.   -- Iterators:
  3896.  
  3897.     type nodes_iter is private;       --| Nodes in arbitrary order.
  3898.     type edges_iter is private;       --| Edges in arbitrary order.
  3899.     type roots_iter is private;       --| Roots in arbitrary order.
  3900.     type leaves_iter is private;      --| Leaves in arbitrary order.
  3901.     type preds_iter is private;       --| Nodes leading to a node.
  3902.     type succs_iter is private;       --| Nodes following a node.
  3903.     type preorder_iter is private;    --| Nodes in preorder traversal.
  3904.     type postorder_iter is private;   --| Nodes in postorder traversal.
  3905.  
  3906.  
  3907.   -- Constructors:
  3908.  
  3909.     function create
  3910.         return dag;
  3911.  
  3912.       --| Effects:
  3913.       --| Return <{}, {}>.
  3914.  
  3915.     procedure add_node(g: in out dag;
  3916.                        l: in     label;
  3917.                        v: in     value);
  3918.  
  3919.       --| Raises: illegal_node, uninitialized_dag
  3920.       --| Effects:
  3921.       --| Set g to <insert(g.labels, l), g.edges>.  Set value(l) to v.
  3922.       --| Raises illegal_node if a node labelled l is already in g.
  3923.       --| Raises uninitialized_dag iff g has not been initialized.
  3924.  
  3925.     procedure add_edge(g:  in out dag;
  3926.                        l1: in     label;
  3927.                        l2: in     label);
  3928.  
  3929.       --| Raises: makes_cycle, illegal_node, duplicate_edge, uninitialized_dag
  3930.       --| Effects:
  3931.       --| Set g to <g.labels, insert(g.edges, (l1, l2))> unless (l1, l2)
  3932.       --| would would cause a cycle in g.  If a cycle would be caused,
  3933.       --| raises makes_cycle and leaves g unchanged.  Raise illegal_node
  3934.       --| if l1 or l2 is not a member of g.labels.
  3935.       --| Raises duplicate_edge if (l1, l2) is already in g.edges.
  3936.       --| Raises uninitialized_dag iff g has not been initialized.
  3937.  
  3938.     procedure set_value(g: in out dag;
  3939.                         l: in     label;
  3940.                         v: in     value);
  3941.  
  3942.       --| Raises: illegal_node, uninitialized_dag
  3943.       --| Effects:
  3944.       --| Set the value(l) to v.  Raise illegal_node if l is not a member
  3945.       --| of g.labels.
  3946.       --| Raises uninitialized_dag iff g has not been initialized.
  3947.  
  3948.     function copy(g: dag)
  3949.     return dag;
  3950.   
  3951.       --| Raises: uninitialized_dag
  3952.       --| Effects:
  3953.       --| Returns a copy of d.  Subsequent changes to d will not be
  3954.       --| visible through the application of operations to the copy of d.
  3955.       --| Assignment or parameter passing without copying will result
  3956.       --| in a single dag value being shared among objects.
  3957.       --| Raises uninitialized_dag iff d has not been initialized.
  3958.       --| The assignment operation is used to transfer the values of
  3959.       --| the label and value typed components of d; consequently,
  3960.       --| changes in these values may be observable through both dags if
  3961.       --| these types are access types, or if they contain access type
  3962.       --| components.
  3963.       --| Notes: 
  3964.       --| This operation is implemented inefficiently; the entire dag is
  3965.       --| rebuilt using basically the same method employed to build it 
  3966.       --| originally.  It is mostly useful for testing.  If you find that this
  3967.       --| function is necessary for your application, see me and I'll work on 
  3968.       --| it.  Otherwise, it will stay as it is; there's a substantial amount 
  3969.       --| of effort involved in doing it correctly.
  3970.  
  3971.   -- Query Operations:
  3972.  
  3973.     function is_empty(g: dag)
  3974.         return boolean;
  3975.  
  3976.       --| Raises: uninitialized_dag
  3977.       --| Effects:
  3978.       --| Return g.labels = {}.
  3979.       --| Raises uninitialized_dag iff g has not been initialized.
  3980.  
  3981.     function is_root(g:  dag;
  3982.                l:  label)
  3983.     return boolean;
  3984.   
  3985.       --| Raises: illegal_node, uninitialized_dag
  3986.       --| Effects:
  3987.       --| Return true if there is no edge, (l1, l2), in g.edges, such that
  3988.       --| equal(l, l2).
  3989.       --| Raises illegal_node if l1 not a member of g.labels.
  3990.       --| Raises uninitialized_dag iff g has not been initialized.
  3991.   
  3992.     function is_leaf(g:  dag;
  3993.              l: label)
  3994.     return boolean;
  3995.   
  3996.       --| Raises: illegal_node, uninitialized_dag
  3997.       --| Return true if there is no edge, (l1, l2), in g.edges, such that
  3998.       --| equal(l, l1).
  3999.       --| Raises illegal_node if l not a member of g.labels.
  4000.       --| Raises uninitialized_dag iff g has not been initialized.
  4001.   
  4002.     function is_successor(g:  dag;
  4003.               l1: label;
  4004.               l2: label)
  4005.     return boolean;
  4006.   
  4007.       --| Raises: illegal_node, uninitialized_dag
  4008.       --| Effects:
  4009.       --| Return true if (l1, l2) is in g.edges.
  4010.       --| Raises illegal_node if l1 not a member of g.labels.
  4011.       --| Raises uninitialized_dag iff g has not been initialized.
  4012.   
  4013.     function is_descendent(g:  dag;
  4014.                l1: label;
  4015.                l2: label)
  4016.     return boolean;
  4017.     
  4018.       --| Raises: illegal_node, uninitialized_dag
  4019.       --| Effects:
  4020.       --| Return true if there is a sequence of edges, in g.edges,
  4021.       --| beginning at l1 and ending at l2.
  4022.       --| Raises illegal_node if either l1 or l2 is not in g.labels.
  4023.       --| Raises uninitialized_dag iff g has not been initialized.
  4024.     
  4025.     function get_value(g: dag;
  4026.                        l: label)
  4027.         return value;
  4028.  
  4029.       --| Raises: illegal_node, uninitialized_dag
  4030.       --| Effects:
  4031.       --| Return value(l).  Raise illegal_node if l is not a member of
  4032.       --| g.labels.
  4033.       --| Raises illegal_node if l not a member of g.labels.
  4034.       --| Raises uninitialized_dag iff g has not been initialized.
  4035.  
  4036.     function root_count(g: dag)
  4037.         return natural;
  4038.  
  4039.       --| Raises: uninitialized_dag
  4040.       --| Effects:
  4041.       --| Return the number of root nodes in g.
  4042.       --| Raises uninitialized_dag iff g has not been initialized.
  4043.  
  4044.     function node_count(g: dag)
  4045.         return natural;
  4046.  
  4047.       --| Raises: uninitialized_dag
  4048.       --| Effects:
  4049.       --| Return |g.labels|.
  4050.       --| Raises uninitialized_dag iff g has not been initialized.
  4051.  
  4052.     function edge_count(g: dag)
  4053.         return natural;
  4054.  
  4055.       --| Raises: uninitialized_dag
  4056.       --| Effects:
  4057.       --| Return |g.edges|.
  4058.       --| Raises uninitialized_dag iff g has not been initialized.
  4059.  
  4060.     function pred_count(g: dag;
  4061.                 l: label)
  4062.         return natural;
  4063.  
  4064.       --| Raises: illegal_node, uninitialized_dag
  4065.       --| Effects:
  4066.       --| Return the number of edges, (l1, l2), in g.edges, such that 
  4067.       --| equal(l, l2).
  4068.       --| Raises illegal_node if l not a member of g.labels.
  4069.       --| Raises uninitialized_dag iff g has not been initialized.
  4070.  
  4071.     function succ_count(g: dag;
  4072.                 l: label)
  4073.         return natural;
  4074.  
  4075.       --| Raises: illegal_node, uninitialized_dag
  4076.       --| Effects:
  4077.       --| Return the number of edges, (l1, l2), in g.edges, such that 
  4078.       --| equal(l, l).
  4079.       --| Raises illegal_node if l not a member of g.labels.
  4080.       --| Raises uninitialized_dag iff g has not been initialized.
  4081.  
  4082.  
  4083.     generic
  4084.         with function label_image(l: label) return string;
  4085.                --| Literal form of a label.
  4086.  
  4087.     procedure put_image(g: dag; 
  4088.                         f: text_io.file_type); 
  4089.  
  4090.       --| Raises: uninitialized_dag, io_exceptions.layout_error, 
  4091.       --|         io_exceptions.mode_error, io_exceptions.status_error
  4092.       --| Effects: 
  4093.       --| Outputs a literal form of g onto file_type f.  The format is one
  4094.       --| line per node in g, each line appearing as:
  4095.       --| l: l1 l2 ... ln, 
  4096.       --| where the l's are the label_images of the labels of nodes in g.
  4097.       --| The li denote the immediate successors of l in g.
  4098.       --| Useful for debugging abstractions that use this package.
  4099.       --| Raises uninitialized_dag iff g has not been initialized.
  4100.       --| Raises other exceptions according to the rules detailed in 
  4101.       --| LRM 14.3.5 for put and put_line of strings.
  4102.  
  4103.  
  4104.   -- Iterators:
  4105.  
  4106.     function make_nodes_iter(g: dag)
  4107.         return nodes_iter;
  4108.  
  4109.       --| Raises: uninitialized_dag
  4110.       --| Effects:
  4111.       --| Create and return a nodes iterator based on g.  This object can
  4112.       --| then be used in conjunction with the more function and the
  4113.       --| next procedures to iterate over the members of g.labels, and
  4114.       --| optionally, their associated values.
  4115.       --| Raises uninitialized_dag iff g has not been initialized.
  4116.  
  4117.     function more(iter: nodes_iter)
  4118.         return boolean;
  4119.  
  4120.       --| Effects:
  4121.       --| Return true iff the nodes iterator has not been exhausted.
  4122.  
  4123.     procedure next(iter: in out nodes_iter;
  4124.                    l:    out    label);
  4125.  
  4126.       --| Raises: no_more
  4127.       --| Effects:
  4128.       --| Let iter be based on the dag, g.  Successive calls of next
  4129.       --| will return the members of g.labels in some arbitrary order.
  4130.       --| After all nodes have been returned, then the procedure will
  4131.       --| raise no_more.
  4132.       --| Requires:
  4133.       --| g must not be changed between the invocations of
  4134.       --| make_nodes_iterator(g) and next.
  4135.  
  4136.     procedure next(iter: in out nodes_iter;
  4137.                    l:    out    label;
  4138.                    v:    out    value);
  4139.  
  4140.       --| Raises: no_more
  4141.       --| Effects:
  4142.       --| Let iter be based on the dag, g.  Successive calls of next
  4143.       --| will return the members of {<l, value(l)> | l in g.labels} in
  4144.       --| some arbitrary order.  After all nodes have been returned, the
  4145.       --| procedure will raise no_more.
  4146.       --| Requires:
  4147.       --| g must not be changed between the invocations of
  4148.       --| make_nodes_iterator(g) and next.
  4149.  
  4150.     function make_edges_iter(g: dag)
  4151.         return edges_iter;
  4152.  
  4153.       --| Raises: uninitialized_dag
  4154.       --| Effects:
  4155.       --| Create and return an edges iterator based on g.  This object
  4156.       --| can then be used in conjunction with the more and next
  4157.       --| procedures to iterate over the edges of g.
  4158.       --| Raises uninitialized_dag iff g has not been initialized.
  4159.  
  4160.     function more(iter: edges_iter)
  4161.         return boolean;
  4162.  
  4163.       --| Effects:
  4164.       --| Return true iff the edges iterator has not been exhausted.
  4165.  
  4166.     procedure next(iter: in out edges_iter;
  4167.                    from: out    label;
  4168.                    to:   out    label);
  4169.  
  4170.       --| Raises: no_more
  4171.       --| Effects:
  4172.       --| Let iter be based on the dag, g.  Successive calls of next
  4173.       --| will return each edge, (from, to), in g.edges, in some arbitrary
  4174.       --| order.  After all edges have been returned, then the procedure
  4175.       --| will raise no_more.
  4176.       --| Requires:
  4177.       --| g must not be changed between the invocations of
  4178.       --| make_edges_iterator(g) and next.
  4179.  
  4180.     function make_roots_iter(g: dag)
  4181.         return roots_iter;
  4182.  
  4183.       --| Raises: uninitialized_dag
  4184.       --| Effects:
  4185.       --| Create and return a roots iterator based on g.  This object
  4186.       --| can then be used in conjunction with the more function and the
  4187.       --| next procedures to iterate over the labels of the root nodes,
  4188.       --| i.e., {l in g.labels | for all (l1, l2) in g.edges, l /= l2},
  4189.       --| and optionally, their associated values.
  4190.       --| Raises uninitialized_dag iff g has not been initialized.
  4191.  
  4192.     function more(iter: roots_iter)
  4193.         return boolean;
  4194.  
  4195.       --| Effects:
  4196.       --| Return true iff the roots iterator has not been exhausted.
  4197.  
  4198.     procedure next(iter: in out roots_iter;
  4199.                    root: out    label);
  4200.  
  4201.       --| Raises: no_more
  4202.       --| Effects:
  4203.       --| Let iter be based on the dag, g.  Successive calls of next
  4204.       --| will return each root label, in g.labels, in some arbitrary
  4205.       --| order.  After all roots have been returned, then the procedure
  4206.       --| will raise no_more.
  4207.       --| Requires:
  4208.       --| g must not be changed between the invocations of
  4209.       --| make_roots_iterator(g) and next.
  4210.  
  4211.     procedure next(iter: in out roots_iter;
  4212.                    root: out    label;
  4213.                    val:  out    value);
  4214.  
  4215.       --| Raises: no_more
  4216.       --| Effects:
  4217.       --| Let iter be based on the dag, g.  Successive calls of next
  4218.       --| will return each pair, <l, value(l)>, where l is the label of a
  4219.       --| root node in g, in some arbitrary order.  After all roots have
  4220.       --| been returned, then the procedure will raise no_more.
  4221.       --| Requires:
  4222.       --| g must not be changed between the invocations of
  4223.       --| make_roots_iterator(g) and next.
  4224.  
  4225.     function make_leaves_iter(g: dag)
  4226.         return leaves_iter;
  4227.  
  4228.       --| Raises: uninitialized_dag
  4229.       --| Effects:
  4230.       --| Create and return a leaves iterator based on g.  This object
  4231.       --| can then be used in conjunction with the more function and the
  4232.       --| next procedures to iterate over the labels of the leaf nodes,
  4233.       --| i.e., {l in g.labels | for all (l1, l2) in g.edges, l /= l1},
  4234.       --| and optionally, their associated values.
  4235.       --| Raises uninitialized_dag iff g has not been initialized.
  4236.  
  4237.     function more(iter: leaves_iter)
  4238.         return boolean;
  4239.  
  4240.       --| Effects:
  4241.       --| Return true iff the leaves iterator has not been exhausted.
  4242.  
  4243.     procedure next(iter: in out leaves_iter;
  4244.                    leaf: out    label);
  4245.  
  4246.       --| Raises: no_more
  4247.       --| Effects:
  4248.       --| Let iter be based on the dag, g.  Successive calls of next
  4249.       --| will return each leaf label, in g.labels, in some arbitrary
  4250.       --| order.  After all leaves have been returned, then the procedure
  4251.       --| will raise no_more.
  4252.       --| Requires:
  4253.       --| g must not be changed between the invocations of
  4254.       --| make_leaves_iterator(g) and next.
  4255.  
  4256.     procedure next(iter: in out leaves_iter;
  4257.                    leaf: out    label;
  4258.                    val:  out    value);
  4259.  
  4260.       --| Raises: no_more
  4261.       --| Effects:
  4262.       --| Let iter be based on the dag, g.  Successive calls of next
  4263.       --| will return each pair, <l, value(l)>, where l is the label of a
  4264.       --| leaf node in g, in some arbitrary order.  After all leaves have
  4265.       --| been returned, then the procedure will raise no_more.
  4266.       --| Requires:
  4267.       --| g must not be changed between the invocations of
  4268.       --| make_leaves_iterator(g) and next.
  4269.  
  4270.     function make_preds_iter(g: dag;
  4271.                              l: label)
  4272.         return preds_iter;
  4273.  
  4274.       --| Raises: illegal_node, uninitialized_dag
  4275.       --| Effects:
  4276.       --| Create and return a predecessors iterator based on g.  This
  4277.       --| object can then be used in conjunction with the more function
  4278.       --| and next procedures to iterate over the predecessors of l,
  4279.       --| the members of {l1 | (l1, l) is in g.edges}, and optionally,
  4280.       --| their associated values.
  4281.       --| Raises illegal_node iff l not in g.labels.
  4282.       --| Raises uninitialized_dag iff g has not been initialized.
  4283.  
  4284.     function more(iter: preds_iter)
  4285.         return boolean;
  4286.  
  4287.       --| Effects:
  4288.       --| Return true iff the preds iterator has not been exhausted.
  4289.  
  4290.     procedure next(iter: in out preds_iter;
  4291.                    l:    out    label);
  4292.  
  4293.       --| Raises: no_more
  4294.       --| Effects:
  4295.       --| Let iter be based on the dag, g.  Successive calls of next
  4296.       --| will return the predecessors of l, in g, in some arbitrary
  4297.       --| order.  After all have been returned, then the procedure will
  4298.       --| raise no_more.
  4299.       --| Requires:
  4300.       --| g must not be changed between the invocations of
  4301.       --| make_preds_iterator(g) and next.
  4302.  
  4303.     procedure next(iter: in out preds_iter;
  4304.                    l:    out    label;
  4305.                    val:  out    value);
  4306.  
  4307.       --| Raises: no_more
  4308.       --| Effects:
  4309.       --| Let iter be based on the dag, g.  Successive calls of next
  4310.       --| will return each pair, <l1, value(l1)>, where l1 is a
  4311.       --| predecessor of l in g, in some arbitrary order.  After all
  4312.       --| have been returned, then the procedure will raise no_more.
  4313.       --| Requires:
  4314.       --| g must not be changed between the invocations of
  4315.       --| make_preds_iterator(g) and next.
  4316.  
  4317.     function make_succs_iter(g: dag;
  4318.                              l: label)
  4319.         return succs_iter;
  4320.  
  4321.       --| Raises: illegal_node, uninitialized_dag
  4322.       --| Effects:
  4323.       --| Create and return a successors iterator based on g.  This
  4324.       --| object can then be used in conjunction with the more function
  4325.       --| and next procedures to iterate over the successors of l,
  4326.       --| the members of {l1 | (l, l1) is in g.edges}, and optionally,
  4327.       --| their associated values.
  4328.       --| Raises illegal_node iff l not in g.labels.
  4329.       --| Raises uninitialized_dag iff g has not been initialized.
  4330.  
  4331.     function more(iter: succs_iter)
  4332.         return boolean;
  4333.  
  4334.       --| Effects:
  4335.       --| Return true iff the succs iterator has not been exhausted.
  4336.  
  4337.     procedure next(iter: in out succs_iter;
  4338.                    l:    out    label);
  4339.  
  4340.       --| Raises: no_more
  4341.       --| Effects:
  4342.       --| Let iter be based on the dag, g.  Successive calls of next
  4343.       --| will return the successors of l, in g, in some arbitrary
  4344.       --| order.  After all have been returned, then the procedure will
  4345.       --| raise no_more.
  4346.       --| Requires:
  4347.       --| g must not be changed between the invocations of
  4348.       --| make_succs_iterator(g) and next.
  4349.  
  4350.     procedure next(iter: in out succs_iter;
  4351.                    l:    out    label;
  4352.                    val:  out    value);
  4353.  
  4354.       --| Raises: no_more
  4355.       --| Effects:
  4356.       --| Let iter be based on the dag, g.  Successive calls of next
  4357.       --| will return each pair, <l1, value(l1)>, where l1 is a
  4358.       --| successor of l in g, in some arbitrary order.  After all pairs
  4359.       --| have been returned, then the procedure will raise no_more.
  4360.       --| Requires:
  4361.       --| g must not be changed between the invocations of
  4362.       --| make_succs_iterator(g) and next.
  4363.  
  4364.     function make_preorder_iter(g: dag;
  4365.                                 l: label)
  4366.         return preorder_iter;
  4367.  
  4368.       --| Raises: illegal_node, uninitialized_dag
  4369.       --| Effects:
  4370.       --| Create and return an iterator that supports a preorder traversal
  4371.       --| of the nodes in the subgraph of g reachable from the node
  4372.       --| labelled l.  This object can then be used in conjunction with
  4373.       --| the more function and the next procedures to perform the
  4374.       --| traversal.  A preorder traversal has the property that, for any
  4375.       --| nodes, n1 and n2, in g, if there is a path in g from n1 to n2,
  4376.       --| then n1 is visited before n2.
  4377.       --| Raises illegal_node iff l not in g.labels.
  4378.       --| Raises uninitialized_dag iff g has not been initialized.
  4379.  
  4380.     function make_preorder_iter(g: dag)
  4381.         return preorder_iter;
  4382.  
  4383.       --| Raises: uninitialized_dag
  4384.       --| Effects:
  4385.       --| Create and return an iterator that supports a preorder traversal
  4386.       --| of the nodes in g. This object is used with the more function
  4387.       --| and the next procedures to perform the traversal.
  4388.       --| Raises uninitialized_dag iff g has not been initialized.
  4389.  
  4390.     function more(iter: preorder_iter)
  4391.         return boolean;
  4392.  
  4393.       --| Effects:
  4394.       --| Return true iff the preorder iterator has not been exhausted.
  4395.  
  4396.     procedure next(iter: in out preorder_iter;
  4397.                    l:    out    label);
  4398.  
  4399.       --| Raises: no_more
  4400.       --| Effects:
  4401.       --| Let iter be based on the subgraph, g1, of g.  Successive calls
  4402.       --| of next will return, in preorder, the labels of nodes in g1.
  4403.       --| After all such nodes have been returned, then the procedure will
  4404.       --| raise no_more.
  4405.       --| Requires:
  4406.       --| g must not be changed between the invocations of
  4407.       --| make_preorder_iterator(g) and next.
  4408.  
  4409.     procedure next(iter: in out preorder_iter;
  4410.                    l:    out    label;
  4411.                    val:  out    value);
  4412.  
  4413.       --| Raises: no_more
  4414.       --| Effects:
  4415.       --| Let iter be based on the subgraph, g1, of g.  Successive calls
  4416.       --| of next will return, in preorder, the pairs <l, value(l)>, where
  4417.       --| l is a label of a node in g1.  After all such nodes have been
  4418.       --| returned, then the procedure will raise no_more.
  4419.       --| Requires:
  4420.       --| g must not be changed between the invocations of
  4421.       --| make_preorder_iterator(g) and next.
  4422.  
  4423.     function make_postorder_iter(g: dag;
  4424.                                  l: label)
  4425.         return postorder_iter;
  4426.  
  4427.       --| Raises: illegal_node, uninitialized_dag
  4428.       --| Effects:
  4429.       --| Create and return an iterator that supports postorder traversal
  4430.       --| of the nodes in the subgraph of g reachable from the node
  4431.       --| labelled l.  This object can then be used in conjunction with
  4432.       --| the more function and the next procedures to perform the
  4433.       --| traversal.  A postorder traversal has the property that, for any
  4434.       --| nodes, n1 and n2, in g, if there is a path in g from n1 to n2,
  4435.       --| then n2 is visited before n1.
  4436.       --| Raises illegal_node iff l not in g.labels.
  4437.       --| Raises uninitialized_dag iff g has not been initialized.
  4438.  
  4439.     function make_postorder_iter(g: dag)
  4440.         return postorder_iter;
  4441.  
  4442.       --| Raises: uninitialized_dag
  4443.       --| Effects:
  4444.       --| Create and return an iterator that supports postorder traversal
  4445.       --| of the nodes in g. This object is used with the more function
  4446.       --| and the next procedures to perform the traversal.
  4447.       --| Raises uninitialized_dag iff g has not been initialized.
  4448.  
  4449.     function more(iter: postorder_iter)
  4450.         return boolean;
  4451.  
  4452.       --| Effects:
  4453.       --| Return true iff the postorder iterator has not been exhausted.
  4454.  
  4455.     procedure next(iter: in out postorder_iter;
  4456.                    l:    out    label);
  4457.  
  4458.       --| Raises: no_more
  4459.       --| Effects:
  4460.       --| Let iter be based on the subgraph, g1, of g.  Successive calls
  4461.       --| of next will return, in postorder, the labels of nodes in g1.
  4462.       --| After all such nodes have been returned, then the procedure will
  4463.       --| raise no_more.
  4464.       --| Requires:
  4465.       --| g must not be changed between the invocations of
  4466.       --| make_postorder_iterator(g) and next.
  4467.  
  4468.     procedure next(iter: in out postorder_iter;
  4469.                    l:    out    label;
  4470.                    val:  out    value);
  4471.  
  4472.       --| Raises: no_more
  4473.       --| Effects:
  4474.       --| Let iter be based on the subgraph, g1, of g.  Successive calls
  4475.       --| of next will return, in postorder, the pairs <l, value(l)>,
  4476.       --| where l is a label of a node in g1.  After all such nodes have
  4477.       --| been returned, then the procedure will raise no_more.
  4478.       --| Requires:
  4479.       --| g must not be changed between the invocations of
  4480.       --| make_postorder_iterator(g) and next.
  4481.       
  4482.       
  4483.   -- Heap management:
  4484.     
  4485.   procedure destroy_dag(g: in out dag);
  4486.       
  4487.     --| Effects:
  4488.     --| Return space consumed by the dag value associated with object
  4489.     --| g to the heap.  (If g is uninitialized, this operation does
  4490.     --| nothing.)  If other objects share the same dag value, then
  4491.     --| further use of these objects is erroneous.  Components of type
  4492.     --| elem_type, if they are access types, are not garbage collected.
  4493.     --| It is the user's responsibility to dispose of these objects.
  4494.     --| g is left in the uninitialized state.
  4495.       
  4496.     generic
  4497.     with procedure destroy(l: in out label);
  4498.     procedure destroy_dag_and_labels(g: in out dag);
  4499.     
  4500.       --| Effects:
  4501.       --| Same as destroy, except that the label components of g are also
  4502.       --| destroyed using the procedure supplied as the generic actual.
  4503.  
  4504.     generic
  4505.     with procedure destroy(v: in out value);
  4506.     procedure destroy_dag_and_values(g: in out dag);
  4507.     
  4508.       --| Effects:
  4509.       --| Same as destroy, except that the value components of g are also
  4510.       --| destroyed using the procedure supplied as the generic actual.
  4511.  
  4512.     generic
  4513.     with procedure destroy(l: in out label);
  4514.     with procedure destroy(v: in out value);
  4515.     procedure destroy_dag_and_nodes(g: in out dag);
  4516.  
  4517.       --| Effects:
  4518.       --| Same as destroy, except that the nodes of g are also destroyed
  4519.       --| using the two procedures supplied as generic actuals.
  4520.  
  4521.  
  4522. private
  4523.  
  4524.     type info_rec;
  4525.     type info is access info_rec;
  4526.  
  4527.     package info_set_pkg is new set_pkg(info);
  4528.         
  4529.     type info_rec is
  4530.         record
  4531.              id: label;
  4532.              val: value;
  4533.              preds: info_set_pkg.set;
  4534.              succs: info_set_pkg.set;
  4535.              all_preds: info_set_pkg.set;
  4536.              all_succs: info_set_pkg.set;
  4537.         end record;
  4538.  
  4539.       --| Component of dag.  See dag representation invariants,
  4540.       --| abstraction function.
  4541.  
  4542.  
  4543.     package info_list_pkg is new lists(info);
  4544.         
  4545.     
  4546.     --| Component of dag.  See dag representation invariants,
  4547.     --| abstraction function.
  4548.  
  4549.  
  4550.     package label_to_info_map_pkg is
  4551.     new hashed_mapping_pkg(label, equal, bucket_range, hash, info);
  4552.     
  4553.     --| Component of dag.  See dag representation invariants,
  4554.     --| abstraction function.
  4555.  
  4556.     type dag_info is
  4557.         record
  4558.         edges: natural := 0;
  4559.         nodes: natural := 0;
  4560.             roots: info_set_pkg.set;
  4561.             infos: info_list_pkg.list;
  4562.             id_map: label_to_info_map_pkg.mapping;
  4563.         end record;
  4564.     
  4565.     type dag is access dag_info;
  4566.  
  4567.     --| In the following description, we denote the fetch operation in
  4568.     --| label_to_info_map_pkg by writing m(i) for fetch(m, i).
  4569.     --|
  4570.     --| Representation Invariants:
  4571.     --| Let r be an instance of the representation type.
  4572.     --| 1. r /= null, and r.roots, r.infos, r.id_map must all be
  4573.     --|    initialized.
  4574.     --| 2. r.edges always equals the number of calls to add_edge that did
  4575.     --|    not raise an exception.
  4576.     --| 3. r.nodes always equals the number of calls to add_node that did
  4577.     --|    not raise an exception.
  4578.     --| 4. For any label, l, in r.id_map, r.id_map(l) is in r.infos.
  4579.     --|    For any info, i, in r.infos, i.id is in the domain of r.id_map.
  4580.     --|    No info appears more than once in r.infos.
  4581.     --| 5. r.id_map(i.id) = i, for each info, i, in r.infos.
  4582.     --|    r.id_map(l).id = l.
  4583.     --| 6. For each info, i, in r.infos, i.all_preds contains i and
  4584.     --|    i.all_succs contains i.
  4585.     --| 7. For all i in r.infos, i in r.roots iff i.preds = {} and
  4586.     --|    i.all_preds = {i}.
  4587.     --| 8. For all i, i1, i2 in r.infos,
  4588.     --|    a. i.all_preds contains i.preds.
  4589.     --|    b. if i2 in i1.preds, then i1.all_preds contains i2.all_preds.
  4590.     --|    c. i.all_preds contains no elements not required by a and b.
  4591.     --| 9. For all i1, i2, in r.infos,
  4592.     --|    a. i1 in i2.preds iff i2 in i1.succs.
  4593.     --|    b. i1 in i2.all_preds iff i2 in i1.all_succs.
  4594.     --|
  4595.     --| Abstraction Function:
  4596.     --| For a given representation object, r, define A(r) = <N, E> by:
  4597.     --| 1. N = {label i.id, with value i.val | i in r.infos}
  4598.     --| 2. E = {<id1, id2> | there exists i1, i2 in r.infos such that
  4599.     --|                      i1.id = id1, i2.id = id2, and
  4600.     --|                      i is a member of id1.succs)
  4601.  
  4602.     
  4603.   -- Nodes Iterator:
  4604.  
  4605.     type nodes_iter is new info_list_pkg.ListIter;
  4606.  
  4607.       --| Let g be the dag that a nodes_iter, i, is based on.  Initially,
  4608.       --| i = nodes_iter(info_list_pkg.make_elements_iter(g.infos)).
  4609.       --| more(i) = info_list_pkg.more(info_list_elements_iter(i)).
  4610.       --| next(i) = .id, .val fields of
  4611.       --|           info_list_pkg.next(info_list_elements_iter(i)).
  4612.       
  4613.  
  4614.   -- Edges Iterator:
  4615.       
  4616.     type edge is
  4617.         record
  4618.             from, to: label;
  4619.         end record;
  4620.  
  4621.     package edge_list_pkg is new lists(edge);
  4622.         
  4623.     type edges_iter is new edge_list_pkg.list;
  4624.  
  4625.       --| Let g be the dag that an edges_iter, i, is based on.
  4626.       --| Initially, all of the edges in g are stored in the edge_list,
  4627.       --| edge_list(i).
  4628.       --| more(i) = not edge_list_pkg.empty(edge_list(i)).
  4629.       --| next(i) = edge_list_pkg.car(edge_list(i)).
  4630.       --|           next removes the first element of i.
  4631.       
  4632.   -- Roots Iterator:
  4633.  
  4634.     type roots_iter is new info_set_pkg.members_iter;
  4635.     
  4636.       --| Let g be the dag that a roots_iter, i, is based on.
  4637.       --| Initially, i is
  4638.       --| roots_iter(info_set_pkg.make_elements_iter(g.roots)).
  4639.       --| more(i) = info_set_pkg.more(info_set_pkg.members_iter(i)).
  4640.       --| next(i) = id, val fields of
  4641.       --| info_set_pkg.next(info_set_pkg.members_iter(i)).
  4642.  
  4643.   -- Leaves Iterator: 
  4644.  
  4645.     type leaves_iter is new info_list_pkg.list; 
  4646.     
  4647.     --| Let i be a leaves_iter based on the dag, g.  i is a sublist of g.infos.
  4648.     --| Initially, i points to the first info in g.infos that has an empty set
  4649.     --| in the succs field.  If no such info exists, then i is initially empty.
  4650.     --| more(i) = i /= null.
  4651.     --| next(i) = .id, .val fields of FirstValue(i).  next advances i to next
  4652.     --| info that has an empty set for the succs field; if no such info exists,
  4653.     --| then i becomes the empty list.
  4654.  
  4655.   -- Preds Iterator:
  4656.  
  4657.     type preds_iter is new info_set_pkg.members_iter;
  4658.     
  4659.       --| Let g be the dag that a preds_iter, i, is based on.
  4660.       --| Initially, i is
  4661.       --| preds_iter(info_set_pkg.make_elements_iter(g.id_map(l).preds),
  4662.       --| for the label, l.
  4663.       --| more(i) = info_set_pkg.more(info_set_pkg.members_iter(i)).
  4664.       --| next(i) = id, val fields of
  4665.       --| info_set_pkg.next(info_set_pkg.members_iter(i)).
  4666.       
  4667.   -- Succs Iterator:
  4668.     
  4669.     type succs_iter is new info_set_pkg.members_iter;
  4670.     
  4671.       --| Let g be the dag that a succs_iter, i, is based on.
  4672.       --| Initially, i is
  4673.       --| succs_iter(info_set_pkg.make_elements_iter(g.id_map(l).succs),
  4674.       --| for the label, l.
  4675.       --| more(i) = info_set_pkg.more(info_set_pkg.members_iter(i)).
  4676.       --| next(i) = id, val fields of
  4677.       --| info_set_pkg.next(info_set_pkg.members_iter(i)).
  4678.       
  4679.   -- Preorder Traversal Iterator:
  4680.   
  4681.     type preorder_iter is new info_list_pkg.list;
  4682.   
  4683.     --| Let i be a preorder_iter based on the dag, g.  Initially, i is
  4684.     --| a list of info's, each taken from g.infos, ordered so that their
  4685.     --| corresponding nodes form a preorder traversal of g.
  4686.     --| more(i) = i /= null.
  4687.     --| next(i) = .id, .val fields of car(i).  next removes the car.
  4688.  
  4689.   -- Postorder Traversal Iterator:
  4690.     
  4691.     type postorder_iter is new info_list_pkg.list;
  4692.     
  4693.     --| Let i be a postorder_iter based on the dag, g.  Initially, i is
  4694.     --| a list of info's, each taken from g.infos, ordered so that their
  4695.     --| corresponding nodes form a postorder traversal of g.
  4696.     --| more(i) = i /= null.
  4697.     --| next(i) = .id, .val fields of car(i).  next removes the car.
  4698.     
  4699. end dag_pkg;
  4700. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4701. --DAG.BDY
  4702. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4703. -- $Source: /nosc/work/abstractions/dag/RCS/dag.bdy,v $
  4704. -- $Revision: 1.4 $ -- $Date: 85/01/31 16:21:16 $ -- $Author: ron $
  4705.  
  4706. -- $Source: /nosc/work/abstractions/dag/RCS/dag.bdy,v $
  4707. -- $Revision: 1.4 $ -- $Date: 85/01/31 16:21:16 $ -- $Author: ron $
  4708.  
  4709. with unchecked_deallocation;
  4710.  
  4711. package body dag_pkg is
  4712.     
  4713.  
  4714. --| Notes: 
  4715. --| 1. plan to put a count field in the info_rec.  Each new node is
  4716. --| given g.node_count at creation, allowing <= to be written over info,
  4717. --| and leading to a faster implementation of set(info).
  4718. --| 2. put_image has code that allows additional aspects of the
  4719. --| representation to be printed.  This can be commented out for a release.
  4720. --| 3. copy function is inefficient, but difficult (and interesting) to write
  4721. --| in an efficient manner.  Determine if there is demand for this.
  4722.  
  4723.   -- Utilities: 
  4724.  
  4725.     procedure destroy_info is
  4726.         new unchecked_deallocation(info_rec, info);
  4727.  
  4728.  
  4729.   -- Constructors:
  4730.  
  4731.     function create
  4732.         return dag is
  4733.     begin
  4734.         return new dag_info'(edges => 0, 
  4735.                              nodes => 0,
  4736.                              roots => info_set_pkg.create,
  4737.                              infos => info_list_pkg.create,
  4738.                      id_map => label_to_info_map_pkg.create);
  4739.     end create;
  4740.     
  4741.     procedure add_node(g: in out dag;
  4742.                        l: in     label;
  4743.                        v: in     value) is
  4744.         new_info: info;
  4745.     begin
  4746.         -- Create info that will be bound to l in the id_map.
  4747.  
  4748.         new_info := new info_rec; 
  4749.         new_info.id := l;
  4750.         new_info.val := v;                                    
  4751.     new_info.preds := info_set_pkg.create;
  4752.     new_info.succs := info_set_pkg.create;
  4753.     new_info.all_preds := info_set_pkg.create;
  4754.     info_set_pkg.insert(new_info.all_preds, new_info);
  4755.     new_info.all_succs := info_set_pkg.create;
  4756.     info_set_pkg.insert(new_info.all_succs, new_info);
  4757.     
  4758.         -- Bind the info to the label.
  4759.     -- This new node is now a root of g.
  4760.     
  4761.         label_to_info_map_pkg.bind(g.id_map, l, new_info);
  4762.     info_set_pkg.insert(g.roots, new_info);
  4763.  
  4764.     -- Increment the node count and add the new info to the info list.
  4765.     
  4766.     g.nodes := g.nodes + 1;
  4767.         g.infos := info_list_pkg.attach(new_info, g.infos);
  4768.       
  4769.     exception
  4770.     when constraint_error =>
  4771.         raise uninitialized_dag;
  4772.     when label_to_info_map_pkg.already_bound =>      -- Node with this label is already here
  4773.         destroy_info(new_info);
  4774.         raise illegal_node;
  4775.     end add_node;
  4776.  
  4777.     procedure add_edge(g:  in out dag;
  4778.                        l1: in     label;
  4779.                        l2: in     label) is
  4780.         l1_info: info;
  4781.         l1_preds: info_set_pkg.members_iter;
  4782.         pred: info; 
  4783.         l2_info: info;
  4784.         l2_succs: info_set_pkg.members_iter;
  4785.         succ: info; 
  4786.     
  4787.     begin
  4788.     -- Convert labels to info pointers.
  4789.     
  4790.     l1_info := label_to_info_map_pkg.fetch(g.id_map, l1);
  4791.     l2_info := label_to_info_map_pkg.fetch(g.id_map, l2);
  4792.  
  4793.         -- Raise duplicate_edge if this edge is already in g.
  4794.  
  4795.         if info_set_pkg.is_member(l2_info.preds, l1_info) then
  4796.             raise duplicate_edge;
  4797.         end if; 
  4798.       
  4799.     -- Get out if this will cause a cycle.  Otherwise, add the edge,
  4800.     -- increment edge counter and remove the target from the root set.
  4801.       
  4802.     if info_set_pkg.is_member(l1_info.all_preds, l2_info) then
  4803.         raise makes_cycle;
  4804.     end if;
  4805.     info_set_pkg.insert(l1_info.succs, l2_info);
  4806.     info_set_pkg.insert(l2_info.preds, l1_info);
  4807.     g.edges := g.edges + 1;
  4808.     info_set_pkg.delete(g.roots, l2_info);
  4809.     
  4810.     -- Maintain transitive closure for future cycle checking:
  4811.     
  4812.         l1_preds := info_set_pkg.make_members_iter(l1_info.all_preds);
  4813.     while info_set_pkg.more(l1_preds) loop
  4814.             info_set_pkg.next(l1_preds, pred);
  4815.         l2_succs := info_set_pkg.make_members_iter(l2_info.all_succs);
  4816.         while info_set_pkg.more(l2_succs) loop
  4817.         info_set_pkg.next(l2_succs, succ);
  4818.         info_set_pkg.insert(pred.all_succs, succ);
  4819.         info_set_pkg.insert(succ.all_preds, pred);
  4820.         end loop;
  4821.         end loop;
  4822.         
  4823.     exception
  4824.         when constraint_error =>
  4825.             raise uninitialized_dag;
  4826.         when label_to_info_map_pkg.not_bound =>    -- Either l1 or l2 is not the label of a node
  4827.             raise illegal_node;
  4828.     end add_edge;
  4829.  
  4830.     procedure set_value(g: in out dag;
  4831.                         l: in     label;
  4832.                         v: in     value) is
  4833.     begin
  4834.     label_to_info_map_pkg.fetch(g.id_map, l).val := v;
  4835.     exception
  4836.     when label_to_info_map_pkg.not_bound =>         -- l does not label a node.
  4837.         raise illegal_node;
  4838.     when constraint_error =>
  4839.         raise uninitialized_dag;
  4840.     end set_value;
  4841.  
  4842.     function copy(g: dag) 
  4843.     return dag is
  4844.     ni: nodes_iter; l: label; v: value;   -- Iterate over (l, v) pairs
  4845.     ei: edges_iter; l1, l2: label;           -- Iterate over (l1, l2) edges
  4846.     g2: dag; 
  4847.     begin
  4848.     g2 := create; 
  4849.     ni := make_nodes_iter(g); 
  4850.     while more(ni) loop
  4851.         next(ni, l, v); 
  4852.         add_node(g2, l, v); 
  4853.      end loop; 
  4854.     
  4855.     ei := make_edges_iter(g); 
  4856.     while more(ei) loop
  4857.         next(ei, l1, l2); 
  4858.         add_edge(g2, l1, l2); 
  4859.     end loop; 
  4860.  
  4861.       return g2; 
  4862.     end copy; 
  4863.  
  4864.  
  4865.   -- Query Operations:
  4866.  
  4867.     function is_empty(g: dag)
  4868.         return boolean is
  4869.     begin
  4870.     return g.nodes = 0;
  4871.     exception
  4872.         when constraint_error =>
  4873.             raise uninitialized_dag;
  4874.     end is_empty;
  4875.     
  4876.     function is_root(g:  dag;
  4877.                l:  label)
  4878.     return boolean is
  4879.     begin
  4880.     return info_set_pkg.is_empty(label_to_info_map_pkg.fetch(g.id_map, l).preds);
  4881.     exception
  4882.     when constraint_error =>
  4883.         raise uninitialized_dag;
  4884.     when label_to_info_map_pkg.not_bound =>
  4885.         raise illegal_node;
  4886.     end is_root;
  4887.   
  4888.     function is_leaf(g:  dag;
  4889.              l: label)
  4890.     return boolean is
  4891.     begin
  4892.     return info_set_pkg.is_empty(label_to_info_map_pkg.fetch(g.id_map, l).succs);
  4893.     exception
  4894.     when constraint_error =>
  4895.         raise uninitialized_dag;
  4896.     when label_to_info_map_pkg.not_bound =>
  4897.         raise illegal_node;
  4898.     end is_leaf;
  4899.   
  4900.     function is_successor(g:  dag;
  4901.               l1: label;
  4902.               l2: label)
  4903.     return boolean is
  4904.     begin
  4905.     return info_set_pkg.is_member(label_to_info_map_pkg.fetch(g.id_map, l1).succs,
  4906.              label_to_info_map_pkg.fetch(g.id_map, l2));
  4907.     exception
  4908.     when constraint_error =>
  4909.         raise uninitialized_dag;
  4910.     when label_to_info_map_pkg.not_bound =>
  4911.         raise illegal_node;
  4912.     end is_successor;
  4913.     
  4914.     function is_descendent(g:  dag;
  4915.                l1: label;
  4916.                l2: label)
  4917.     return boolean is
  4918.     i1, i2: info;  -- info's assoc with l1, l2, respectively.
  4919.     begin
  4920.     i1 := label_to_info_map_pkg.fetch(g.id_map, l1);
  4921.     i2 := label_to_info_map_pkg.fetch(g.id_map, l2);
  4922.     return info_set_pkg.is_member(i1.all_succs, i2) and then not (i1 = i2);
  4923.       -- Second condition necessary because of rep invariant #6.
  4924.     exception
  4925.     when constraint_error =>
  4926.         raise uninitialized_dag;
  4927.     when label_to_info_map_pkg.not_bound =>
  4928.         raise illegal_node;
  4929.     end is_descendent;
  4930.  
  4931.     function get_value(g: dag;
  4932.                        l: label)
  4933.         return value is
  4934.     begin
  4935.     return label_to_info_map_pkg.fetch(g.id_map, l).val;
  4936.     exception
  4937.         when label_to_info_map_pkg.not_bound =>
  4938.         raise illegal_node;
  4939.         when constraint_error =>
  4940.         raise uninitialized_dag;
  4941.     end get_value;
  4942.  
  4943.     function root_count(g: dag)
  4944.         return natural is
  4945.     begin
  4946.     return info_set_pkg.size(g.roots);
  4947.     exception
  4948.         when constraint_error =>
  4949.             raise uninitialized_dag;
  4950.     end root_count;
  4951.     
  4952.     function node_count(g: dag)
  4953.         return natural is
  4954.     begin
  4955.     return g.nodes;
  4956.     exception
  4957.         when constraint_error =>
  4958.             raise uninitialized_dag;
  4959.     end node_count;
  4960.  
  4961.     function edge_count(g: dag)
  4962.         return natural is
  4963.     begin
  4964.     return g.edges;
  4965.     exception
  4966.         when constraint_error =>
  4967.             raise uninitialized_dag;
  4968.     end edge_count;
  4969.  
  4970.     function pred_count(g: dag;
  4971.                 l: label)
  4972.         return natural is
  4973.     begin
  4974.     return info_set_pkg.size(label_to_info_map_pkg.fetch(g.id_map, l).preds);
  4975.     exception
  4976.     when constraint_error =>
  4977.         raise uninitialized_dag;
  4978.     when label_to_info_map_pkg.not_bound =>
  4979.         raise illegal_node;
  4980.     end pred_count;
  4981.  
  4982.     function succ_count(g: dag;
  4983.                 l: label)
  4984.         return natural is
  4985.     begin
  4986.     return info_set_pkg.size(label_to_info_map_pkg.fetch(g.id_map, l).succs);
  4987.     exception
  4988.     when constraint_error =>
  4989.         raise uninitialized_dag;
  4990.     when label_to_info_map_pkg.not_bound =>
  4991.         raise illegal_node;
  4992.     end succ_count;
  4993.  
  4994.     procedure put_image(g: dag; 
  4995.                         f: text_io.file_type) is
  4996.         list_iter: info_list_pkg.ListIter;
  4997.         inf: info; 
  4998.  
  4999.         procedure put_header_and_set(header: in     string; 
  5000.                           s:      in     info_set_pkg.set) is
  5001.             set_iter: info_set_pkg.members_iter; 
  5002.             inf: info; 
  5003.         begin
  5004.             text_io.put(f, header); 
  5005.         set_iter := info_set_pkg.make_members_iter(s); 
  5006.         while info_set_pkg.more(set_iter) loop
  5007.                 info_set_pkg.next(set_iter, inf); 
  5008.         text_io.put(f, " " & label_image(inf.id)); 
  5009.         end loop;
  5010.             text_io.put_line(f, ""); 
  5011.     end put_header_and_set; 
  5012.  
  5013.     begin
  5014.     list_iter := info_list_pkg.MakeListIter(g.infos);
  5015.         while info_list_pkg.more(list_iter) loop
  5016.             info_list_pkg.next(list_iter, inf); 
  5017.  
  5018.             -- Temporary debugging version:
  5019.         put_header_and_set(label_image(inf.id) & " (succs):", inf.succs);
  5020.         put_header_and_set(label_image(inf.id) & " (preds):", inf.preds);
  5021.         put_header_and_set(label_image(inf.id) & " (all_succs):", 
  5022.                    inf.all_succs);
  5023.         put_header_and_set(label_image(inf.id) & " (all_preds):", 
  5024.                    inf.all_preds);
  5025.  
  5026.             -- Real version:              
  5027.         -- put_header_and_set(label_image(inf.id) & ":", inf.succs);
  5028.  
  5029.         end loop;
  5030.     
  5031.     exception
  5032.         when constraint_error =>
  5033.         raise uninitialized_dag;
  5034.     end put_image;  
  5035.  
  5036.         
  5037.   -- Iterators:
  5038.  
  5039.     function make_nodes_iter(g: dag)
  5040.         return nodes_iter is
  5041.     begin
  5042.     return nodes_iter(info_list_pkg.MakeListIter(g.infos));
  5043.     exception
  5044.     when constraint_error =>
  5045.         raise uninitialized_dag;
  5046.     end make_nodes_iter;
  5047.  
  5048.     function more(iter: nodes_iter)
  5049.         return boolean is
  5050.     begin
  5051.     return info_list_pkg.more(info_list_pkg.ListIter(iter));
  5052.     end more;
  5053.  
  5054.     procedure next(iter: in out nodes_iter;
  5055.                    l:    out    label) is
  5056.     i: info;
  5057.     begin
  5058.     info_list_pkg.next(info_list_pkg.ListIter(iter), i);
  5059.         l := i.id;
  5060.     exception
  5061.     when info_list_pkg.NoMore =>
  5062.         raise dag_pkg.no_more;
  5063.     end next;
  5064.  
  5065.     procedure next(iter: in out nodes_iter;
  5066.                    l:    out    label;
  5067.                    v:    out    value) is
  5068.     i: info;
  5069.     begin
  5070.     info_list_pkg.next(info_list_pkg.ListIter(iter), i);
  5071.     l := i.id;
  5072.     v := i.val;
  5073.     exception
  5074.     when info_list_pkg.NoMore =>
  5075.         raise dag_pkg.no_more;
  5076.     end next;
  5077.  
  5078.     function make_edges_iter(g: dag)
  5079.         return edges_iter is
  5080.     from: info;
  5081.     to: info;
  5082.     edges: edge_list_pkg.list;
  5083.     info_list_iter: info_list_pkg.ListIter;
  5084.     info_set_iter: info_set_pkg.members_iter;
  5085.     begin
  5086.     edges := edge_list_pkg.create;
  5087.     info_list_iter := info_list_pkg.MakeListIter(g.infos);
  5088.     while info_list_pkg.more(info_list_iter) loop
  5089.         info_list_pkg.next(info_list_iter, from);
  5090.         info_set_iter := info_set_pkg.make_members_iter(from.succs);
  5091.         while info_set_pkg.more(info_set_iter) loop
  5092.         info_set_pkg.next(info_set_iter, to);
  5093.         edge_list_pkg.attach(edges, (from => from.id, to => to.id));
  5094.         end loop;
  5095.     end loop;
  5096.     return edges_iter(edges);
  5097.     
  5098.     exception
  5099.         when constraint_error =>
  5100.         raise uninitialized_dag;
  5101.     end make_edges_iter;
  5102.  
  5103.     function more(iter: edges_iter)
  5104.         return boolean is
  5105.     begin
  5106.     return not edge_list_pkg.IsEmpty(edge_list_pkg.list(iter));
  5107.     end more;
  5108.  
  5109.     procedure next(iter: in out edges_iter;
  5110.                    from: out    label;
  5111.                    to:   out    label) is
  5112.     e: edge;
  5113.     begin
  5114.     e := edge_list_pkg.FirstValue(edge_list_pkg.list(iter));
  5115.     edge_list_pkg.DeleteHead(edge_list_pkg.list(iter));
  5116.     from := e.from;
  5117.     to := e.to;
  5118.     exception
  5119.     when edge_list_pkg.EmptyList =>
  5120.         raise dag_pkg.no_more;
  5121.     end next;
  5122.  
  5123.     function make_roots_iter(g: dag)
  5124.         return roots_iter is
  5125.     begin
  5126.     return roots_iter(info_set_pkg.make_members_iter(g.roots));
  5127.     exception
  5128.     when constraint_error =>
  5129.         raise uninitialized_dag;
  5130.     end make_roots_iter;
  5131.  
  5132.     function more(iter: roots_iter)
  5133.         return boolean is
  5134.     begin
  5135.     return info_set_pkg.more(info_set_pkg.members_iter(iter));
  5136.     end more;
  5137.  
  5138.     procedure next(iter: in out roots_iter;
  5139.                    root: out    label) is
  5140.     inf: info;
  5141.     begin
  5142.     info_set_pkg.next(info_set_pkg.members_iter(iter), inf);
  5143.     root := inf.id;
  5144.     exception
  5145.         when info_set_pkg.no_more =>
  5146.         raise dag_pkg.no_more;
  5147.     end next;
  5148.  
  5149.     procedure next(iter: in out roots_iter;
  5150.                    root: out    label;
  5151.                    val:  out    value) is
  5152.     inf: info;
  5153.     begin
  5154.     info_set_pkg.next(info_set_pkg.members_iter(iter), inf);
  5155.     root := inf.id;
  5156.     val := inf.val;
  5157.     exception
  5158.         when info_set_pkg.no_more =>
  5159.         raise dag_pkg.no_more;
  5160.     end next;
  5161.  
  5162.     function make_leaves_iter(g: dag)
  5163.         return leaves_iter is
  5164.     l: info_list_pkg.list;
  5165.     begin
  5166.     l := g.infos; 
  5167.     loop
  5168.         exit when info_list_pkg.IsEmpty(l); 
  5169.         exit when info_set_pkg.is_empty(info_list_pkg.FirstValue(l).succs);
  5170.         l := info_list_pkg.tail(l); 
  5171.     end loop; 
  5172.     return leaves_iter(l); 
  5173.     exception
  5174.     when constraint_error =>
  5175.         raise uninitialized_dag;
  5176.     end make_leaves_iter;
  5177.  
  5178.     function more(iter: leaves_iter)
  5179.         return boolean is
  5180.     begin
  5181.     return not info_list_pkg.IsEmpty(info_list_pkg.list(iter)); 
  5182.     end more;
  5183.  
  5184.     procedure next(iter: in out leaves_iter;
  5185.                    leaf: out    label) is
  5186.     begin    
  5187.     leaf := info_list_pkg.FirstValue(info_list_pkg.list(iter)).id;
  5188.     loop
  5189.         iter := leaves_iter(info_list_pkg.tail(info_list_pkg.list(iter)));
  5190.         exit when info_list_pkg.IsEmpty(info_list_pkg.list(iter));
  5191.         exit when info_set_pkg.is_empty(info_list_pkg.FirstValue(info_list_pkg.list(iter)).succs);
  5192.     end loop; 
  5193.     exception 
  5194.     when info_list_pkg.EmptyList => 
  5195.         raise no_more; 
  5196.     end next;
  5197.  
  5198.     procedure next(iter: in out leaves_iter;
  5199.                    leaf: out    label;
  5200.                    val:  out    value) is
  5201.     inf: info; 
  5202.     begin    
  5203.     inf := info_list_pkg.FirstValue(info_list_pkg.list(iter));
  5204.     leaf := inf.id; 
  5205.     val := inf.val; 
  5206.     leaf := info_list_pkg.FirstValue(info_list_pkg.list(iter)).id; 
  5207.     loop
  5208.         iter := leaves_iter(info_list_pkg.tail(info_list_pkg.list(iter)));
  5209.         exit when info_list_pkg.IsEmpty(info_list_pkg.list(iter));
  5210.         exit when info_set_pkg.is_empty(info_list_pkg.FirstValue(info_list_pkg.list(iter)).succs);
  5211.     end loop; 
  5212.     exception 
  5213.     when info_list_pkg.EmptyList => 
  5214.         raise no_more; 
  5215.     end next;
  5216.  
  5217.     function make_preds_iter(g: dag; 
  5218.                              l: label)
  5219.         return preds_iter is
  5220.     inf: info;
  5221.     begin
  5222.     return preds_iter(info_set_pkg.make_members_iter(label_to_info_map_pkg.fetch(g.id_map, l).preds));
  5223.     exception
  5224.     when constraint_error =>
  5225.         raise uninitialized_dag;
  5226.     when label_to_info_map_pkg.not_bound =>
  5227.         raise illegal_node;
  5228.     end make_preds_iter;
  5229.  
  5230.     function more(iter: preds_iter)
  5231.         return boolean is
  5232.     begin
  5233.     return info_set_pkg.more(info_set_pkg.members_iter(iter));
  5234.     end more;
  5235.  
  5236.     procedure next(iter: in out preds_iter;
  5237.                    l:    out    label) is
  5238.     inf: info;
  5239.     begin
  5240.     info_set_pkg.next(info_set_pkg.members_iter(iter), inf);
  5241.     l := inf.id;
  5242.     exception
  5243.         when info_set_pkg.no_more =>
  5244.         raise dag_pkg.no_more;
  5245.     end next;
  5246.     
  5247.     procedure next(iter: in out preds_iter;
  5248.            l:    out    label;
  5249.            val:  out    value) is
  5250.     inf: info;
  5251.     begin
  5252.     info_set_pkg.next(info_set_pkg.members_iter(iter), inf);
  5253.     l := inf.id;
  5254.     val := inf.val;
  5255.     exception
  5256.     when info_set_pkg.no_more =>
  5257.         raise dag_pkg.no_more;
  5258.     end next;
  5259.  
  5260.     function make_succs_iter(g: dag; 
  5261.                              l: label)
  5262.         return succs_iter is
  5263.     inf: info;
  5264.     begin
  5265.     return succs_iter(info_set_pkg.make_members_iter(label_to_info_map_pkg.fetch(g.id_map, l).succs));
  5266.     exception
  5267.     when constraint_error =>
  5268.         raise uninitialized_dag;
  5269.     when label_to_info_map_pkg.not_bound =>
  5270.         raise illegal_node;
  5271.     end make_succs_iter;
  5272.  
  5273.     function more(iter: succs_iter)
  5274.         return boolean is
  5275.     begin
  5276.     return info_set_pkg.more(info_set_pkg.members_iter(iter));
  5277.     end more;
  5278.  
  5279.     procedure next(iter: in out succs_iter;
  5280.                    l:    out    label) is
  5281.     inf: info;
  5282.     begin
  5283.     info_set_pkg.next(info_set_pkg.members_iter(iter), inf);
  5284.     l := inf.id;
  5285.     exception
  5286.         when info_set_pkg.no_more =>
  5287.         raise dag_pkg.no_more;
  5288.     end next;
  5289.     
  5290.     procedure next(iter: in out succs_iter;
  5291.            l:    out    label;
  5292.            val:  out    value) is
  5293.     inf: info;
  5294.     begin
  5295.     info_set_pkg.next(info_set_pkg.members_iter(iter), inf);
  5296.     l := inf.id;
  5297.     val := inf.val;
  5298.     exception
  5299.     when info_set_pkg.no_more =>
  5300.         raise dag_pkg.no_more;
  5301.     end next;
  5302.  
  5303.     procedure preorder_traversal(i:              in     info;
  5304.                                  traversal_list: in out info_list_pkg.list;
  5305.                  traversed:      in out info_set_pkg.set) is
  5306.     succs_iter: info_set_pkg.members_iter;
  5307.     succ: info;
  5308.     begin
  5309.     if info_set_pkg.is_member(traversed, i) then return; end if;
  5310.     info_set_pkg.insert(traversed, i);
  5311.     succs_iter := info_set_pkg.make_members_iter(i.succs);
  5312.     while info_set_pkg.more(succs_iter) loop
  5313.         info_set_pkg.next(succs_iter, succ);
  5314.         preorder_traversal(succ, traversal_list, traversed);
  5315.     end loop;
  5316.     traversal_list := info_list_pkg.attach(i, traversal_list);
  5317.     end preorder_traversal;
  5318.     
  5319.     function make_preorder_iter(g: dag;
  5320.                 l: label)
  5321.     return preorder_iter is
  5322.     traversal_list: info_list_pkg.list := info_list_pkg.create;
  5323.     traversed: info_set_pkg.set := info_set_pkg.create;
  5324.     inf: info;
  5325.     begin
  5326.     inf := label_to_info_map_pkg.fetch(g.id_map, l);
  5327.     preorder_traversal(inf, traversal_list, traversed);
  5328.     info_set_pkg.destroy(traversed);
  5329.     return preorder_iter(traversal_list);
  5330.     exception
  5331.     when constraint_error =>
  5332.         raise uninitialized_dag;
  5333.     when label_to_info_map_pkg.not_bound =>
  5334.         raise illegal_node;
  5335.     end make_preorder_iter;
  5336.  
  5337.     function make_preorder_iter(g: dag)
  5338.         return preorder_iter is
  5339.     traversal_list: info_list_pkg.list := info_list_pkg.create;
  5340.     traversed: info_set_pkg.set := info_set_pkg.create;
  5341.     roots_set_iter: info_set_pkg.members_iter;
  5342.     root: info;
  5343.     begin
  5344.     roots_set_iter := info_set_pkg.make_members_iter(g.roots);
  5345.     while info_set_pkg.more(roots_set_iter) loop
  5346.         info_set_pkg.next(roots_set_iter, root);
  5347.         preorder_traversal(root, traversal_list, traversed);
  5348.     end loop;
  5349.     info_set_pkg.destroy(traversed);
  5350.     return preorder_iter(traversal_list);
  5351.     exception
  5352.     when constraint_error =>
  5353.         raise uninitialized_dag;
  5354.     end make_preorder_iter;
  5355.  
  5356.     function more(iter: preorder_iter)
  5357.         return boolean is
  5358.     begin
  5359.     return not info_list_pkg.IsEmpty(info_list_pkg.list(iter));
  5360.     end more;
  5361.  
  5362.     procedure next(iter: in out preorder_iter;
  5363.                    l:    out    label) is
  5364.     i: info;
  5365.     begin
  5366.     i := info_list_pkg.FirstValue(info_list_pkg.list(iter));
  5367.     info_list_pkg.DeleteHead(info_list_pkg.list(iter));
  5368.     l := i.id;
  5369.     exception
  5370.     when info_list_pkg.EmptyList =>
  5371.         raise dag_pkg.no_more;
  5372.     end next;
  5373.  
  5374.     procedure next(iter: in out preorder_iter;
  5375.                    l:    out    label;
  5376.                    val:  out    value) is
  5377.     i: info;
  5378.     begin
  5379.     i := info_list_pkg.FirstValue(info_list_pkg.list(iter));
  5380.     info_list_pkg.DeleteHead(info_list_pkg.list(iter));
  5381.     l := i.id;
  5382.     val := i.val;
  5383.     exception
  5384.     when info_list_pkg.EmptyList =>
  5385.         raise dag_pkg.no_more;
  5386.     end next;
  5387.     
  5388.     procedure postorder_traversal(i:              in     info;
  5389.                                   traversal_list: in out info_list_pkg.list;
  5390.                   traversed:      in out info_set_pkg.set) is
  5391.     succs_iter: info_set_pkg.members_iter;
  5392.     succ: info;
  5393.     begin
  5394.     if info_set_pkg.is_member(traversed, i) then return; end if;
  5395.     succs_iter := info_set_pkg.make_members_iter(i.succs);
  5396.     while info_set_pkg.more(succs_iter) loop
  5397.         info_set_pkg.next(succs_iter, succ);
  5398.         postorder_traversal(succ, traversal_list, traversed);
  5399.     end loop;
  5400.     traversal_list := info_list_pkg.attach(traversal_list, i);
  5401.     info_set_pkg.insert(traversed, i);
  5402.     end postorder_traversal;
  5403.     
  5404.     function make_postorder_iter(g: dag;
  5405.                  l: label)
  5406.     return postorder_iter is
  5407.     traversal_list: info_list_pkg.list := info_list_pkg.create;
  5408.     traversed: info_set_pkg.set := info_set_pkg.create;
  5409.     inf: info;
  5410.     begin
  5411.     inf := label_to_info_map_pkg.fetch(g.id_map, l);
  5412.     postorder_traversal(inf, traversal_list, traversed);
  5413.     info_set_pkg.destroy(traversed);
  5414.     return postorder_iter(traversal_list);
  5415.     exception
  5416.     when constraint_error =>
  5417.         raise uninitialized_dag;
  5418.     when label_to_info_map_pkg.not_bound =>
  5419.         raise illegal_node;
  5420.     end make_postorder_iter;
  5421.  
  5422.     function make_postorder_iter(g: dag)
  5423.         return postorder_iter is
  5424.     traversal_list: info_list_pkg.list := info_list_pkg.create;
  5425.     traversed: info_set_pkg.set := info_set_pkg.create;
  5426.     roots_set_iter: info_set_pkg.members_iter;
  5427.     root: info;
  5428.     begin
  5429.     roots_set_iter := info_set_pkg.make_members_iter(g.roots);
  5430.     while info_set_pkg.more(roots_set_iter) loop
  5431.         info_set_pkg.next(roots_set_iter, root);
  5432.         postorder_traversal(root, traversal_list, traversed);
  5433.     end loop;
  5434.     info_set_pkg.destroy(traversed);
  5435.     return postorder_iter(traversal_list);
  5436.     exception
  5437.     when constraint_error =>
  5438.         raise uninitialized_dag;
  5439.     end make_postorder_iter;
  5440.  
  5441.     function more(iter: postorder_iter)
  5442.         return boolean is
  5443.     begin
  5444.     return not info_list_pkg.IsEmpty(info_list_pkg.list(iter));
  5445.     end more;
  5446.  
  5447.     procedure next(iter: in out postorder_iter;
  5448.                    l:    out    label) is
  5449.     i: info;
  5450.     begin
  5451.     i := info_list_pkg.FirstValue(info_list_pkg.list(iter));
  5452.     info_list_pkg.DeleteHead(info_list_pkg.list(iter));
  5453.     l := i.id;
  5454.     exception
  5455.     when info_list_pkg.EmptyList =>
  5456.         raise dag_pkg.no_more;
  5457.     end next;
  5458.  
  5459.     procedure next(iter: in out postorder_iter;
  5460.                    l:    out    label;
  5461.                    val:  out    value) is
  5462.     i: info;
  5463.     begin
  5464.     i := info_list_pkg.FirstValue(info_list_pkg.list(iter));
  5465.     info_list_pkg.DeleteHead(info_list_pkg.list(iter));
  5466.     l := i.id;
  5467.     val := i.val;
  5468.     exception
  5469.     when info_list_pkg.EmptyList =>
  5470.         raise dag_pkg.no_more;
  5471.     end next;
  5472.  
  5473.     
  5474.   -- Heap Management:
  5475.   
  5476.   
  5477.     procedure null_destroy_label(l: in out label) is
  5478.     begin null; end null_destroy_label;
  5479.       
  5480.     procedure null_destroy_value(v: in out value) is
  5481.     begin null; end null_destroy_value;
  5482.       
  5483.     procedure destroy_dag(g: in out dag) is
  5484.     procedure implement_destroy is new
  5485.         destroy_dag_and_nodes(null_destroy_label, null_destroy_value);
  5486.     begin
  5487.         implement_destroy(g);
  5488.     end destroy_dag;
  5489.     
  5490.     procedure destroy_dag_and_labels(g: in out dag) is
  5491.     procedure implement_destroy is new
  5492.         destroy_dag_and_nodes(destroy, null_destroy_value);
  5493.     begin
  5494.     implement_destroy(g);
  5495.     end destroy_dag_and_labels;
  5496.     
  5497.     procedure destroy_dag_and_values(g: in out dag) is
  5498.     procedure implement_destroy is new
  5499.         destroy_dag_and_nodes(null_destroy_label, destroy);
  5500.     begin
  5501.     implement_destroy(g);
  5502.     end destroy_dag_and_values;
  5503.     
  5504.     procedure destroy_dag_and_nodes(g: in out dag) is
  5505.     info_iter: info_list_pkg.ListIter;
  5506.     i: info;
  5507.     
  5508.     procedure free_dag is
  5509.         new unchecked_deallocation(dag_info, dag);
  5510.         
  5511.     procedure free_info is
  5512.         new unchecked_deallocation(info_rec, info);
  5513.         
  5514.         procedure destroy_info(i: in out info) is
  5515.         begin
  5516.             destroy(i.id);
  5517.             destroy(i.val);
  5518.             info_set_pkg.destroy(i.preds);
  5519.             info_set_pkg.destroy(i.succs);
  5520.             info_set_pkg.destroy(i.all_preds);
  5521.             info_set_pkg.destroy(i.all_succs);
  5522.             free_info(i);
  5523.         end destroy_info;
  5524.     
  5525.     begin
  5526.     info_set_pkg.destroy(g.roots);
  5527.     label_to_info_map_pkg.destroy(g.id_map);
  5528.       
  5529.     info_iter := info_list_pkg.MakeListIter(g.infos);
  5530.     while info_list_pkg.more(info_iter) loop
  5531.         info_list_pkg.next(info_iter, i);
  5532.         destroy_info(i);
  5533.     end loop;
  5534.     info_list_pkg.destroy(g.infos);
  5535.       
  5536.     free_dag(g);
  5537.  
  5538.     exception
  5539.     when constraint_error =>         -- uninitialized dag
  5540.         return;
  5541.     end destroy_dag_and_nodes;
  5542.     
  5543. end dag_pkg;
  5544. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5545. --DARRAY.SPC
  5546. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5547. -- $Source: /nosc/work/abstractions/darray/RCS/darray.spc,v $
  5548. -- $Revision: 1.1 $ -- $Date: 85/01/10 17:49:30 $ -- $Author: ron $
  5549.  
  5550. -- $Source: /nosc/work/abstractions/darray/RCS/darray.spc,v $
  5551. -- $Revision: 1.1 $ -- $Date: 85/01/10 17:49:30 $ -- $Author: ron $
  5552.  
  5553. generic
  5554.     type elem_type is private;
  5555.         --| Component element type.  
  5556.  
  5557.     with function equal(e1, e2: elem_type)
  5558.         return boolean is "=";   --| An equality relation on elem_type.
  5559.  
  5560. package darray_pkg is
  5561.  
  5562. --| Overview:
  5563. --| This package provides the dynamic array (darray) abstract data type.
  5564. --| A darray has completely dynamic bounds, which change during runtime as
  5565. --| elements are added to/removed from the top/bottom. darrays are similar
  5566. --| to deques, differing only in that operations for indexing into the
  5567. --| structure are also provided.  A darray is indexed by integers that
  5568. --| fall within the current bounds.  The component type, elem_type, of a
  5569. --| darray is a generic formal parameter of this package, along with a
  5570. --| function, equal, that is assumed to form an equality relation over
  5571. --| over elem_type.
  5572. --|
  5573. --| The notation, <first, elts>, will be used to denote a darray.
  5574. --| first is the current low bound of the darray.  elts is the sequence
  5575. --| of elements contained in the darray.  For a given darray, d, the
  5576. --| dot selection mechanism is used to refer to these components, e.g.,
  5577. --| d.first and d.elts.  & is used for sequence concatenation, and also
  5578. --| for prepending/postpending a single element to a sequence.  |s| is
  5579. --| the number of elements in a sequence, s, and () is the null sequence.
  5580. --| Standard Ada array indexing notation is adopted for sequences.
  5581. --|
  5582. --| The following is a complete list of operations, written in the order
  5583. --| in which they appear in the spec:
  5584. --|
  5585. --| Constructors:
  5586. --|        create
  5587. --|        array_to_darray
  5588. --|        set_first
  5589. --|        add_low, add_high
  5590. --|        remove_low, remove_high
  5591. --|        store
  5592. --|        copy, copy_deep (generic)
  5593. --|        
  5594. --| Query Operations:
  5595. --|        fetch
  5596. --|        low, high
  5597. --|        first, last
  5598. --|        is_empty
  5599. --|        length
  5600. --|        equal
  5601. --|        
  5602. --| Iterators:
  5603. --|        make_elements_iter, more, next
  5604. --|
  5605. --| Heap Management:
  5606. --|        destroy
  5607. --|        
  5608.  
  5609. --| Notes:
  5610. --| Programmer: Ron Kownacki
  5611.  
  5612.   -- Primary Types:
  5613.  
  5614.     type darray is limited private;    --| The darray abstract data type.
  5615.  
  5616.     type array_type is array (integer range <>) of elem_type;
  5617.         --| darray/array_type conversion operations are provided.
  5618.  
  5619.  
  5620.   -- Storage Management Constants and Types:  (see create procedure)
  5621.  
  5622.     default_predict: constant positive := 100;
  5623.  
  5624.     default_high: constant positive := 50;
  5625.  
  5626.     default_expand: constant positive := 100;
  5627.  
  5628.  
  5629.   -- Exceptions:
  5630.  
  5631.     no_more: exception;        --| Raised on incorrect use of an iterator.
  5632.  
  5633.     out_of_bounds: exception;  --| Raised on index out of current bounds.
  5634.  
  5635.     uninitialized_darray: exception;
  5636.         --| Raised on use of uninitialized darray by most operations.
  5637.  
  5638.  
  5639.  -- Iterators:
  5640.  
  5641.     type elements_iter is private;     --| Component elements iterator.
  5642.  
  5643.  
  5644.   -- Constructors:
  5645.  
  5646.     procedure create(first:          in     integer := 1;
  5647.                      predict:        in     positive := default_predict;
  5648.                      high_percent:   in     positive := default_high;
  5649.                      expand_percent: in     positive := default_expand;
  5650.                      d:              in out darray);
  5651.  
  5652.       --| Effects:
  5653.       --| Sets d to <first, ()>.  If d has previously been initialized,
  5654.       --| then a destroy(d) is first performed.  The predict parameter
  5655.       --| specifies the initial space allocated.  (predict  = #elements).
  5656.       --| The high_percent parameter is the caller's expectation of the
  5657.       --| percentage of add_highs, out of total adds, to the darray.  For
  5658.       --| example, a caller would specify 100 if it was known that no
  5659.       --| add_lows would be performed.  The expand_percent parameter
  5660.       --| specifies the amount of additional space, as a percentage of
  5661.       --| currently allocated space, that is to be allocated whenever an
  5662.       --| expansion becomes necessary.  For example, 100 doubles the
  5663.       --| allocated space.
  5664.   
  5665.     procedure array_to_darray(a:              in     array_type;
  5666.                               first:          in     integer := 1;
  5667.                   predict:        in     positive;
  5668.                               high_percent:   in     positive
  5669.                                                        := default_high;
  5670.                               expand_percent: in     positive
  5671.                                                        := default_expand;
  5672.                               d:              in out darray);
  5673.  
  5674.       --| Raises: out_of_bounds
  5675.       --| Effects:
  5676.       --| Sets d to <first, a(a'first..a'last)>.  If d has previously
  5677.       --| been initialized, then an implicit destroy(d) is performed.
  5678.       --| The high_percent and expand_percent parameters are defined
  5679.       --| as for create.  Raises out_of_bounds iff predict < a'length.
  5680.  
  5681.     procedure set_first(d:     in out darray;
  5682.                         first: in     integer);
  5683.  
  5684.       --| Raises: uninitialized_darray
  5685.       --| Effects:
  5686.       --| Sets d.first to first.
  5687.       --| Raises uninitialized_darray if d has not been initialized.
  5688.  
  5689.     procedure add_low(d: in out darray;
  5690.                       e: in     elem_type);
  5691.  
  5692.       --| Raises: uninitialized_darray
  5693.       --| Effects:
  5694.       --| Sets d to <d.first - 1, e & d.elts>.
  5695.       --| Raises uninitialized_darray if d has not been initialized.
  5696.  
  5697.     procedure add_high(d: in out darray;
  5698.                        e: in     elem_type);
  5699.  
  5700.       --| Raises: uninitialized_darray
  5701.       --| Effects:
  5702.       --| Sets d.elts to d.elts & e.
  5703.       --| Raises uninitialized_darray if d has not been initialized.
  5704.  
  5705.     procedure remove_low(d: in out darray);
  5706.  
  5707.       --| Raises: out_of_bounds, uninitialized_darray
  5708.       --| Effects:
  5709.       --| Sets d to <d.first + 1, d.elts(d.first + 1 .. last(d))>.
  5710.       --| Raises out_of_bounds iff is_empty(d).
  5711.       --| Raises uninitialized_darray if d has not been initialized.
  5712.  
  5713.     procedure remove_high(d: in out darray);
  5714.  
  5715.       --| Raises: out_of_bounds, uninitialized_darray
  5716.       --| Effects:
  5717.       --| Sets d.elts to d.elts(d.first..last(d) - 1).
  5718.       --| Raises out_of_bounds iff is_empty(d).
  5719.       --| Raises uninitialized_darray if d has not been initialized.
  5720.  
  5721.     procedure store(d: in out darray;
  5722.                    i:  in     integer;
  5723.                    e:  in     elem_type);
  5724.  
  5725.       --| Raises: out_of_bounds, uninitialized_darray
  5726.       --| Effects:
  5727.       --| Replaces d.elts(i) with e.  Raises out_of_bounds iff
  5728.       --| either is_empty(d) or i is not in d.first..last(d).
  5729.       --| Raises uninitialized_darray if d has not been initialized.
  5730.  
  5731.     function copy(d: darray)
  5732.     return darray;
  5733.   
  5734.       --| Raises: uninitialized_darray
  5735.       --| Effects:
  5736.       --| Returns a copy of d.  Subsequent changes to the structure of d
  5737.       --| will not be visible through the application of operations to
  5738.       --| the copy of d, and vice versa.  Assignment or parameter passing
  5739.       --| without using copy (or copy_deep, described below) will result
  5740.       --| in a single darray value being shared among objects.
  5741.       --| Raises uninitialized_darray if d has not been initialized.
  5742.       --| The assignment operation is used to transfer the values of
  5743.       --| the elem_type component objects of d; consequently, changes
  5744.       --| in these values may be observable through both darrays if
  5745.       --| elem_type is an access type, or contains access type
  5746.       --| components.
  5747.       
  5748.     generic
  5749.         with function copy(e: elem_type) return elem_type;
  5750.     
  5751.     function copy_deep(d: darray)
  5752.     return darray;
  5753.  
  5754.       --| Raises: uninitialized_darray
  5755.       --| Effects:
  5756.       --| Returns a copy of d.  Subsequent changes to the structure of d
  5757.       --| will not be visible through the application of operations to
  5758.       --| the copy of d, and vice versa.  Assignment or parameter passing
  5759.       --| without using copy_deep or copy will result in a single
  5760.       --| darray value being shared among objects.
  5761.       --| Raises uninitialized_darray if d has not been initialized.
  5762.       --| The transfer of elem_type component objects is accomplished by
  5763.       --| using the assignment operation in conjunction with the copy
  5764.       --| function.  Consequently, the user can prevent sharing of
  5765.       --| elem_type access components.
  5766.     
  5767.  
  5768.   -- Query Operations:
  5769.  
  5770.     function fetch(d: darray;
  5771.                    i: integer)
  5772.         return elem_type;
  5773.  
  5774.       --| Raises: out_of_bounds, uninitialized_darray
  5775.       --| Effects:
  5776.       --| Returns d.elts(i).  Raises out_of_bounds iff either is_empty(d)
  5777.       --| or i is not in d.first..last(d).
  5778.       --| Raises uninitialized_darray if d has not been initialized.
  5779.  
  5780.     function low(d: in darray)
  5781.         return elem_type;
  5782.  
  5783.       --| Raises: out_of_bounds, uninitialized_darray
  5784.       --| Effects:
  5785.       --| Returns d.elts(d.first).  Raises out_of_bounds iff is_empty(d).
  5786.       --| Raises uninitialized_darray if d has not been initialized.
  5787.  
  5788.     function high(d: in darray)
  5789.         return elem_type;
  5790.  
  5791.       --| Raises: out_of_bounds, uninitialized_darray
  5792.       --| Effects:
  5793.       --| Returns d.elts(last(d)).  Raises out_of_bounds iff is_empty(d).
  5794.       --| Raises uninitialized_darray if d has not been initialized.
  5795.  
  5796.     function first(d: in darray)
  5797.         return integer;
  5798.  
  5799.       --| Raises: uninitialized_darray
  5800.       --| Effects:
  5801.       --| Returns d.first.
  5802.       --| Raises uninitialized_darray if d has not been initialized.
  5803.  
  5804.     function last(d: in darray)
  5805.         return integer;
  5806.  
  5807.       --| Raises: uninitialized_darray
  5808.       --| Effects:
  5809.       --| Returns d.first + |d.elts| - 1.
  5810.       --| Raises uninitialized_darray if d has not been initialized.
  5811.  
  5812.     function is_empty(d: in darray)
  5813.         return boolean;
  5814.  
  5815.       --| Raises: uninitialized_darray
  5816.       --| Effects:
  5817.       --| Returns length(d) = 0, or equivalently, last(d) < d.first.
  5818.       --| Raises uninitialized_darray if d has not been initialized.
  5819.  
  5820.     function length(d: in darray)
  5821.         return natural;
  5822.  
  5823.       --| Raises: uninitialized_darray
  5824.       --| Effects:
  5825.       --| Returns |d.elts|.
  5826.       --| Raises uninitialized_darray if d has not been initialized.
  5827.  
  5828.     function equal(d1, d2: darray)
  5829.         return boolean;
  5830.  
  5831.       --| Raises: uninitialized_darray
  5832.       --| Effects:
  5833.       --| Return (d1.first = d2.first and
  5834.       --|         last(d1) = last(d2) and
  5835.       --|         for each i in d1.first..last(d1),
  5836.       --|             equal(d1.elts(i), d2.elts(i)).
  5837.       --| Raises uninitialized_darray if either d1 or d2 has not been
  5838.       --| initialized.  Note that (d1 = d2) implies that equal(d1, d2)
  5839.       --| will always hold.  "=" is object equality, equal is state
  5840.       --| equality.
  5841.  
  5842.     function darray_to_array(d: darray)
  5843.         return array_type;
  5844.  
  5845.       --| Raises: uninitialized_darray
  5846.       --| Effects:
  5847.       --| Let bounds_range be d.first..d.first + length(d) - 1.  If
  5848.       --| bounds_range is empty, then return an empty array with bounds
  5849.       --| of 1..0.  Otherwise, return bounds_range'(d.elts).
  5850.       --| Raises uninitialized_darray if d has not been initialized.
  5851.  
  5852.  
  5853.   -- Iterators:
  5854.  
  5855.     function make_elements_iter(d: darray)
  5856.         return elements_iter;
  5857.  
  5858.       --| Raises: uninitialized_darray
  5859.       --| Effects:
  5860.       --| Create and return an elements itererator based on d.  This
  5861.       --| object can then be used in conjunction with the more function
  5862.       --| and the next procedure to iterate over the components of d.
  5863.       --| Raises uninitialized_darray if d has not been initialized.
  5864.  
  5865.     function more(iter: elements_iter)
  5866.         return boolean;
  5867.  
  5868.       --| Effects:
  5869.       --| Return true iff the elements iterator has not been exhausted.
  5870.  
  5871.     procedure next(iter: in out elements_iter;
  5872.                    e:       out elem_type);
  5873.  
  5874.       --| Raises: no_more
  5875.       --| Effects:
  5876.       --| Let iter be based on the darray, d.  Successive calls of next
  5877.       --| will return, in e, successive elements of d.elts.  Each call
  5878.       --| updates the state of the elements iterator.  After all elements
  5879.       --| have been returned, an invocation of next will raise no_more.
  5880.       --| Requires:
  5881.       --| d must not be changed between the invocations of
  5882.       --| make_elements_iterator(d) and next.
  5883.  
  5884.  
  5885.   -- Heap Management:
  5886.  
  5887.     procedure destroy(d: in out darray);
  5888.       --| Effects:
  5889.       --| Return space consumed by the darray value associated with object
  5890.       --| d to the heap.  (If d is uninitialized, this operation does
  5891.       --| nothing.)  If other objects share the same darray value, then
  5892.       --| further use of these objects is erroneous.  Components of type
  5893.       --| elem_type, if they are access types, are not garbage collected.
  5894.       --| It is the user's responsibility to dispose of these objects.
  5895.       --| d is left in the uninitialized state.
  5896.  
  5897.  
  5898. private
  5899.  
  5900.     type array_ptr is access array_type;
  5901.  
  5902.     type darray_info is
  5903.         record
  5904.             first_idx: positive;
  5905.             last_idx: natural;
  5906.             first: integer;
  5907.             high_percent: positive;
  5908.             expand_percent: positive;
  5909.             arr: array_ptr := null;
  5910.         end record;
  5911.  
  5912.     type darray is access darray_info;
  5913.  
  5914.     --| Let r be an instance of the representation type.
  5915.     --| Representation Invariants:
  5916.     --| 1. r /= null, r.arr /= null (must be initialized to be valid.)
  5917.     --| 2. r.arr'first = 1 and
  5918.     --|    r.arr'last >= 1
  5919.     --| 3. r.first_idx <= r.last_idx or
  5920.     --|    r.first_idx = r.last_idx + 1
  5921.     --| 4. r.first_idx <= r.last_idx =>
  5922.     --|        r.first_idx, r.last_idx in r.arr'range
  5923.     --| 5. r.expand_percent, r.high_percent get values at creation time,
  5924.     --|    and these never change.
  5925.     --|
  5926.     --| Abstraction Function:  (denoted by A(r))
  5927.     --| if r.last_idx < r.first_idx then
  5928.     --|     <r.first, ()>
  5929.     --| else
  5930.     --|     <r.first, (r.arr(r.first_idx),...,r.arr(r.last_idx))>
  5931.     --|
  5932.     --| These properties follow:
  5933.     --| 1. length(A(r)) = r.last_idx - r.first_idx + 1
  5934.     --| 2. last(A(r)) = r.first + r.last_idx - r.first_idx
  5935.     --| 3. fetch(A(r), i) =
  5936.     --|        if (i - r.first + r.first_idx) in r.first_idx..r.last_idx
  5937.     --|            then r.arr(i - r.first + r.first_idx)
  5938.     --|            else undefined.  (out_of_bounds)
  5939.  
  5940.     type elements_iter is
  5941.         record
  5942.             last: integer := 0;
  5943.             current: integer := 1;
  5944.             arr: array_ptr;
  5945.         end record;
  5946.  
  5947.       --| Let d be the darray that an elements_iter, i, is based on.
  5948.       --| Initially, i.current = d.first_idx, i.last = d.last_idx, and
  5949.       --| i.arr = d.arr.
  5950.       --| more(i) = i.current <= i.last.
  5951.       --| next(i) = i.arr(current).  i.current incremented by next.
  5952.       --| Note that if an elements_iter object is not initialized, then
  5953.       --| more is false.
  5954.  
  5955. end darray_pkg;
  5956.  
  5957. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5958. --DARRAY.BDY
  5959. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5960. -- $Source: /nosc/work/abstractions/darray/RCS/darray.bdy,v $
  5961. -- $Revision: 1.2 $ -- $Date: 85/02/01 10:50:50 $ -- $Author: ron $
  5962.  
  5963. -- $Source: /nosc/work/abstractions/darray/RCS/darray.bdy,v $
  5964. -- $Revision: 1.2 $ -- $Date: 85/02/01 10:50:50 $ -- $Author: ron $
  5965.  
  5966. with unchecked_deallocation;
  5967.  
  5968. package body darray_pkg is
  5969.  
  5970.     -- Utilities:
  5971.  
  5972.     procedure free_array_ptr is
  5973.         new unchecked_deallocation(array_type, array_ptr);
  5974.  
  5975.     procedure free_darray is
  5976.     new unchecked_deallocation(darray_info, darray);
  5977.     
  5978.     function down_index(i: integer;
  5979.                         d: darray)
  5980.         return integer;
  5981.  
  5982.       --| Raises: out_of_bounds
  5983.       --| Effects:
  5984.       --| Map from abstraction indices to representation indices.
  5985.       --| Raises out_of_bounds iff either is_empty(d) or i is not in
  5986.       --| d.first..last(d).
  5987.       --| Requires: d must be initialized.
  5988.  
  5989.     procedure initialization_check(d: darray);
  5990.     
  5991.       --| Raises: uninitialized_darray
  5992.       --| Effects:
  5993.       --| Returns normally iff d has been the target of a create, copy,
  5994.       --| or array_to_darray operation, and has not since been destroyed.
  5995.       --| Otherwise, raises uninitialized_darray.
  5996.       --| This procedure will not detect the case where another object
  5997.       --| sharing the same darray value has been destroyed; this is
  5998.       --| erroneous use.
  5999.  
  6000.     procedure expand(d: in out darray);
  6001.     
  6002.       --| Effects:
  6003.       --| Allocates additional space in d.arr.  The old contents of d.arr
  6004.       --| are copied to a slice of the new array.  The expansion amount is
  6005.       --| a percentage (d.expand_percent) of currently allocated space.
  6006.       --| Sets d.first_idx and d.last_idx to appropriate positions in the
  6007.       --| new array; these positions are selected according to the
  6008.       --| expected distribution of add_highs/add_lows (d.high_percent).
  6009.       --| Requires: d must be initialized.
  6010.  
  6011.     procedure contract(d: in out darray);
  6012.     
  6013.       --| Effects:
  6014.       --| Checks whether d.arr consumes too much space in proportion to
  6015.       --| the slice that is being used to hold the darray elements.  If
  6016.       --| so, halves the size of d.arr.  The old contents of d.arr are
  6017.       --| copied to a slice of the new array.  Sets d.first_idx and
  6018.       --| and d.last_idx to appropriate positions in the new array; these
  6019.       --| positions are selected according to the expected distribution of
  6020.       --| add_highs/add_lows (d.high_percent).
  6021.       --| Requires: d must be initialized and nonempty.
  6022.       
  6023.     procedure reallocate(d:          in out darray;
  6024.              new_length: in     positive);
  6025.  
  6026.       --| Raises: out_of_bounds
  6027.       --| Effects:
  6028.       --| Replaces d.arr with a pointer to an array of length new_length,
  6029.       --| fills a slice of this array with the old contents of d.arr, and
  6030.       --| adjusts d.first_idx and d.last_idx appropriately.  Everything is
  6031.       --| done according to d.high_percent.  Used by both expand/contract.
  6032.       --| Raises out_of_bounds iff new_length < length(d).
  6033.       --| Requires: d must be initialized.
  6034.  
  6035.     procedure determine_position(array_length: in  positive;
  6036.                                  slice_length: in  natural;
  6037.                                  high_percent: in  positive;
  6038.                  first_idx:    out positive;
  6039.                  last_idx:     out natural);
  6040.                  
  6041.       --| Raises: out_of_bounds
  6042.       --| Effects:
  6043.       --| Determines the appropriate position of a slice of length
  6044.       --| slice_length in an array with range 1..array_length.  This
  6045.       --| position is calculated according to the high_percent parameter.
  6046.       --| Raises out_of_bounds iff slice_length > array_length.
  6047.       --| Used by create, array_to_darray, reallocate.
  6048.  
  6049.  
  6050.   -- Constructors:
  6051.  
  6052.     procedure create(first:          in     integer := 1;
  6053.                      predict:        in     positive := default_predict;
  6054.                      high_percent:   in     positive := default_high;
  6055.                      expand_percent: in     positive := default_expand;
  6056.                      d:              in out darray) is
  6057.     begin
  6058.         destroy(d);
  6059.     d := new darray_info;
  6060.         determine_position(predict, 0, high_percent,
  6061.                d.first_idx, d.last_idx);
  6062.         d.first := first;
  6063.         d.high_percent := high_percent;
  6064.         d.expand_percent := expand_percent;
  6065.         d.arr := new array_type(1..predict);
  6066.     exception
  6067.         when out_of_bounds =>    -- determine_position fails
  6068.         destroy(d);
  6069.         raise;
  6070.     end create;
  6071.  
  6072.     procedure array_to_darray(a:              in    array_type;
  6073.                               first:          in    integer:= 1;
  6074.                               predict:        in    positive;
  6075.                               high_percent:   in    positive
  6076.                                                        := default_high;
  6077.                               expand_percent: in    positive
  6078.                                                        := default_expand;
  6079.                               d:              in out darray) is
  6080.     begin
  6081.         free_array_ptr(d.arr);
  6082.     d := new darray_info;
  6083.         determine_position(predict, a'length, high_percent,
  6084.                d.first_idx, d.last_idx);
  6085.         d.first := first;
  6086.         d.high_percent := high_percent;
  6087.         d.expand_percent := expand_percent;
  6088.         d.arr := new array_type(1..predict);
  6089.         d.arr.all := a;
  6090.     exception
  6091.         when out_of_bounds =>     -- determine_position fails
  6092.         destroy(d);
  6093.         raise;
  6094.     end array_to_darray;
  6095.  
  6096.     procedure set_first(d:     in out darray;
  6097.                         first: in     integer) is
  6098.     begin
  6099.         initialization_check(d);
  6100.         d.first := first;
  6101.     end set_first;
  6102.  
  6103.     procedure add_low(d: in out darray;
  6104.                       e: in     elem_type) is
  6105.     begin
  6106.         initialization_check(d);
  6107.         d.arr(d.first_idx - 1) := e;
  6108.         d.first_idx := d.first_idx - 1;
  6109.         d.first := d.first - 1;
  6110.     exception
  6111.         when constraint_error =>    -- on array store
  6112.             expand(d);
  6113.             d.arr(d.first_idx - 1) := e;
  6114.             d.first_idx := d.first_idx - 1;
  6115.             d.first := d.first - 1;
  6116.     end add_low;
  6117.  
  6118.     procedure add_high(d: in out darray;
  6119.                        e: in     elem_type) is
  6120.     begin
  6121.         initialization_check(d);
  6122.         d.arr(d.last_idx + 1) := e;
  6123.         d.last_idx := d.last_idx + 1;
  6124.     exception
  6125.         when constraint_error =>    -- on array store
  6126.             expand(d);
  6127.             d.arr(d.last_idx + 1) := e;
  6128.             d.last_idx := d.last_idx + 1;
  6129.     end add_high;
  6130.  
  6131.     procedure remove_low(d: in out darray) is
  6132.     begin
  6133.         initialization_check(d);
  6134.     if d.last_idx < d.first_idx then raise out_of_bounds; end if;
  6135.     
  6136.     d.first_idx := d.first_idx + 1;
  6137.     d.first := d.first + 1;
  6138.     contract(d);
  6139.     end remove_low;
  6140.  
  6141.     procedure remove_high(d: in out darray) is
  6142.     begin
  6143.         initialization_check(d);
  6144.         if d.last_idx < d.first_idx then raise out_of_bounds; end if;
  6145.     
  6146.         d.last_idx := d.last_idx - 1;
  6147.         contract(d);
  6148.     end remove_high;
  6149.  
  6150.     procedure store(d: in out darray;
  6151.                     i: in     integer;
  6152.                     e: in     elem_type) is
  6153.     begin
  6154.         initialization_check(d);
  6155.         d.arr(down_index(i, d)) := e;
  6156.     end store;
  6157.     
  6158.    function copy(d: darray)
  6159.        return darray is
  6160.        d2: darray;
  6161.    begin
  6162.        initialization_check(d);
  6163.        d2 := new darray_info'(first_idx => d.first_idx,
  6164.                   last_idx => d.last_idx,
  6165.                   first => d.first,
  6166.                   high_percent => d.high_percent,
  6167.                   expand_percent => d.expand_percent,
  6168.                   arr => new array_type(1..d.arr'length));
  6169.        d2.arr.all := d.arr.all;
  6170.        return d2;
  6171.     end copy;
  6172.  
  6173.     function copy_deep(d: darray)
  6174.     return darray is
  6175.     d2: darray;
  6176.     i: integer;
  6177.     begin
  6178.     initialization_check(d);
  6179.     d2 := new darray_info'(first_idx => d.first_idx,
  6180.                    last_idx => d.last_idx,
  6181.                    first => d.first,
  6182.                    high_percent => d.high_percent,
  6183.                    expand_percent => d.expand_percent,
  6184.                    arr => new array_type(1..d.arr'length));
  6185.     for i in d.first_idx..d.last_idx loop
  6186.         d2.arr(i) := copy(d.arr(i));
  6187.     end loop;
  6188.     return d2;
  6189.      end copy_deep;
  6190.  
  6191.  
  6192.   -- Query Operations:
  6193.  
  6194.     function fetch(d: darray;
  6195.                    i: integer)
  6196.         return elem_type is
  6197.     begin
  6198.         initialization_check(d);
  6199.         return d.arr(down_index(i, d));
  6200.     end fetch;
  6201.  
  6202.     function low(d: in darray)
  6203.         return elem_type is
  6204.     begin
  6205.         initialization_check(d);
  6206.         return d.arr(down_index(d.first, d));
  6207.     end low;
  6208.  
  6209.     function high(d: in darray)
  6210.         return elem_type is
  6211.     begin
  6212.         if is_empty(d) then      -- is_empty checks for initialization
  6213.             raise out_of_bounds;
  6214.         end if;
  6215.         return d.arr(d.last_idx);
  6216.     end high;
  6217.  
  6218.     function first(d: in darray)
  6219.         return integer is
  6220.     begin
  6221.         initialization_check(d);
  6222.         return d.first;
  6223.     end first;
  6224.  
  6225.     function last(d: in darray)
  6226.         return integer is
  6227.     begin
  6228.         initialization_check(d);
  6229.         return d.first + d.last_idx - d.first_idx;
  6230.     end last;
  6231.  
  6232.     function is_empty(d: in darray)
  6233.         return boolean is
  6234.     begin
  6235.         initialization_check(d);
  6236.         return d.last_idx < d.first_idx;
  6237.     end is_empty;
  6238.  
  6239.     function length(d: in darray)
  6240.         return natural is
  6241.     begin
  6242.         initialization_check(d);
  6243.         return d.last_idx - d.first_idx + 1;
  6244.     end length;
  6245.  
  6246.     function equal(d1, d2: darray)
  6247.         return boolean is
  6248.     i2: integer;
  6249.     begin
  6250.         initialization_check(d1);
  6251.         initialization_check(d2);
  6252.  
  6253.         if d1.first /= d2.first or else length(d1) /= length(d2) then
  6254.             return false;
  6255.         end if;
  6256.  
  6257.     i2 := d2.first_idx;
  6258.     for i1 in d1.first_idx..d1.last_idx loop
  6259.         if not equal(d1.arr(i1), d2.arr(i2)) then
  6260.         return false;
  6261.         end if;
  6262.         i2 := i2 + 1;
  6263.     end loop;
  6264.  
  6265.     return true;
  6266.     end equal;
  6267.  
  6268.     function darray_to_array(d: darray)
  6269.         return array_type is
  6270.         subtype dbounds_array is array_type(d.first..last(d));
  6271.         -- invocation of last performs initialization check.
  6272.     begin
  6273.         return dbounds_array'(d.arr(d.first_idx..d.last_idx));
  6274.     end darray_to_array;
  6275.  
  6276.  
  6277.   -- Iterators:
  6278.  
  6279.     function make_elements_iter(d: darray)
  6280.         return elements_iter is
  6281.     begin
  6282.         initialization_check(d);
  6283.         return (current => d.first_idx,
  6284.                 last => d.last_idx,
  6285.                 arr => d.arr);
  6286.     end make_elements_iter;
  6287.  
  6288.     function more(iter: elements_iter)
  6289.         return boolean is
  6290.     begin
  6291.         return iter.current <= iter.last;
  6292.     end more;
  6293.  
  6294.     procedure next(iter: in out elements_iter;
  6295.                    e:       out elem_type) is
  6296.     begin
  6297.         if not more(iter) then raise no_more; end if;
  6298.  
  6299.         e := iter.arr(iter.current);
  6300.         iter.current := iter.current + 1;
  6301.     end next;
  6302.  
  6303.       
  6304.     -- Heap Management:
  6305.  
  6306.     procedure destroy(d: in out darray) is
  6307.     begin
  6308.         free_array_ptr(d.arr);
  6309.     free_darray(d);
  6310.     exception
  6311.         when constraint_error =>    -- d is null, d.arr is illegal.
  6312.             return;
  6313.     end destroy;
  6314.  
  6315.  
  6316.     -- Utilities:
  6317.  
  6318.     function down_index(i: integer;
  6319.                         d: darray)
  6320.         return integer is
  6321.         down_idx: integer := i - d.first + d.first_idx;
  6322.     begin
  6323.         if d.last_idx < d.first_idx or else                -- empty array
  6324.            not (down_idx in d.first_idx..d.last_idx) then  -- bogus index
  6325.             raise out_of_bounds;
  6326.         end if;
  6327.  
  6328.         return down_idx;
  6329.     end down_index;
  6330.  
  6331.     procedure initialization_check(d: darray) is
  6332.     begin
  6333.         if d = null then raise uninitialized_darray; end if;
  6334.     end initialization_check;
  6335.  
  6336.     procedure expand(d: in out darray) is
  6337.         new_length: integer :=
  6338.         (d.arr'length * (100 + d.expand_percent))/100;
  6339.     begin
  6340.         -- Specified percent, in relation to length, may be too small to
  6341.     -- force any growth.  In this case, force growth.  This is rare.
  6342.     -- The choice to double is arbitrary.
  6343.     
  6344.     if new_length = d.arr'length then
  6345.         new_length := 2 * d.arr'length;
  6346.     end if;
  6347.  
  6348.         reallocate(d, new_length);
  6349.     end expand;
  6350.  
  6351.     procedure contract(d: in out darray) is
  6352.       -- <<A better contraction strategy is needed.  Justification is weak
  6353.       -- for this one.>>
  6354.     begin
  6355.         null;
  6356.     end contract;
  6357.  
  6358.     procedure reallocate(d:          in out darray;
  6359.              new_length: in     positive) is
  6360.                  
  6361.     new_arr: array_ptr;
  6362.     new_first_idx: integer;
  6363.     new_last_idx: integer;
  6364.  
  6365.     begin
  6366.         determine_position(new_length, length(d), d.high_percent,
  6367.                new_first_idx, new_last_idx);
  6368.     new_arr := new array_type(1..new_length);
  6369.     new_arr(new_first_idx..new_last_idx) :=
  6370.         d.arr(d.first_idx..d.last_idx);
  6371.     free_array_ptr(d.arr);
  6372.     d.arr := new_arr;
  6373.     d.first_idx := new_first_idx;
  6374.     d.last_idx := new_last_idx;
  6375.     end reallocate;
  6376.     
  6377.     procedure determine_position(array_length: in  positive;
  6378.                                  slice_length: in  natural;
  6379.                                  high_percent: in  positive;
  6380.                  first_idx:    out positive;
  6381.                  last_idx:     out natural) is
  6382.                    
  6383.         left_over: integer := array_length - slice_length;
  6384.         high_space: integer := (high_percent * left_over)/100;
  6385.         low_space: integer := left_over - high_space;
  6386.     
  6387.     begin
  6388.     if left_over < 0 then raise out_of_bounds; end if;
  6389.     
  6390.         first_idx := low_space + 1;
  6391.         last_idx := low_space + slice_length;
  6392.     end determine_position;
  6393.     
  6394. end darray_pkg;
  6395.  
  6396. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6397. --SLISTS.SPC
  6398. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6399. with String_Pkg;
  6400. with Lists;
  6401.  
  6402. package String_Lists is new Lists(String_Pkg.String_Type, String_Pkg.Equal);
  6403. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6404. --FILEMGR.SPC
  6405. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6406. with String_Pkg;            use String_Pkg;
  6407. with String_Lists;            pragma elaborate(String_Lists);
  6408.  
  6409. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6410. --   WARNING : THIS PACKAGE IS HOST DEPENDENT THUS NOT PORATABLE  --
  6411. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6412.  
  6413. package File_Manager is
  6414.  
  6415. --| The File_Manager package provides procedures to manipulate files
  6416. --| in a file system under a given operating system.
  6417.                                                     pragma Page;
  6418. --| Overview:
  6419. --| The File_Manager provides routines to manipulate closed files.
  6420. --| It provides procedures to rename, copy, move, delete and expand
  6421. --| a name containing wild card characters to a list of filenames.
  6422.  
  6423. --| N/A: Raises, Effects, Requires, Modifies, Error
  6424.                                                     pragma Page;
  6425.             -- Types --
  6426.  
  6427. type Mode_Type is (FULL, NO_VERSION, NO_DIRECTORY, FILE_ONLY);
  6428.  
  6429.             -- Exceptions --
  6430.  
  6431. Delete_Error        : exception;
  6432.                 --| raised when unable to delete a file
  6433. Device_Not_Ready    : exception;
  6434.                 --| raised when device is not ready
  6435. Device_Write_Locked : exception;
  6436.                 --| raised when device is write locked
  6437. Directory_Not_Found : exception;
  6438.                 --| raised when unable to find the directory
  6439. Expand_Error        : exception;
  6440.                 --| raised when name expansion error occurs
  6441. File_Already_Exists : exception;
  6442.                 --| raised when a file already exists
  6443. File_Locked         : exception;
  6444.                 --| raised when file is locked
  6445. File_Name_Error     : exception;
  6446.                 --| raised when the file name is too long
  6447. File_Not_Found      : exception;
  6448.                 --| raised when the file is not found
  6449. Input_File_Error    : exception;
  6450.                 --| raised when unable to read a file to copy
  6451. Output_File_Error   : exception;
  6452.                 --| raised when unable to write a new file
  6453. Parse_Error         : exception;
  6454.                 --| raised when parsing error 
  6455. Privilege_Violation : exception;
  6456.                 --| raised when privilege violation is detected
  6457. Rename_Error        : exception;
  6458.                 --| raised when error is detected in rename operation
  6459.                                                     pragma Page;
  6460.  
  6461.             -- Operations --
  6462.  
  6463. procedure Rename (        --| rename a file in the file system
  6464.     Old_File : in String_Type;    --| name the file presently has
  6465.     New_File : in String_Type    --| new name to give the file
  6466.     );
  6467.  
  6468. --| Raises:
  6469. --| Device_Not_Ready, Directory_Not_Found, File_Not_Found,
  6470. --| Parse_Error, Privilege_Violation, Rename_Error
  6471.  
  6472. --| Requires:
  6473. --| The name of the file to be renamed and a filename of the new
  6474. --| file.
  6475.  
  6476. --| Effects:
  6477. --| It renames a file in the file system with a new name.  The contents
  6478. --| of the file are not changed.
  6479.  
  6480. --| Modifies:
  6481. --| The external filename is changed to a new name.
  6482.  
  6483. --| N/A: Errors
  6484.                                                     pragma Page;
  6485. procedure Rename (        --| rename a file in the file system
  6486.     Old_File : in String_Type;    --| name the file presently has
  6487.     New_File : in string    --| new name to give the file
  6488.     );
  6489.  
  6490. --| Raises:
  6491. --| Device_Not_Ready, Directory_Not_Found, File_Not_Found,
  6492. --| Parse_Error, Privilege_Violation, Rename_Error
  6493.  
  6494. --| Requires:
  6495. --| The name of the file to be renamed and a filename of the new
  6496. --| file.
  6497.  
  6498. --| Effects:
  6499. --| It renames a file in the file system with a new name.  The contents
  6500. --| of the file are not changed.
  6501.  
  6502. --| Modifies:
  6503. --| The external filename is changed to a new name.
  6504.  
  6505. --| N/A: Errors
  6506.                                                     pragma Page;
  6507. procedure Rename (        --| rename a file in the file system
  6508.     Old_File : in string;    --| name the file presently has
  6509.     New_File : in String_Type    --| new name to give the file
  6510.     );
  6511.  
  6512. --| Raises:
  6513. --| Device_Not_Ready, Directory_Not_Found, File_Not_Found,
  6514. --| Parse_Error, Privilege_Violation, Rename_Error
  6515.  
  6516. --| Requires:
  6517. --| The name of the file to be renamed and a filename of the new
  6518. --| file.
  6519.  
  6520. --| Effects:
  6521. --| It renames a file in the file system with a new name.  The contents
  6522. --| of the file are not changed.
  6523.  
  6524. --| Modifies:
  6525. --| The external filename is changed to a new name.
  6526.  
  6527. --| N/A: Errors
  6528.                                                     pragma Page;
  6529. procedure Rename (        --| rename a file in the file system
  6530.     Old_File : in string;    --| name the file presently has
  6531.     New_File : in string    --| new name to give the file
  6532.     );
  6533.  
  6534. --| Raises:
  6535. --| Device_Not_Ready, Directory_Not_Found, File_Not_Found,
  6536. --| Parse_Error, Privilege_Violation, Rename_Error
  6537.  
  6538. --| Requires:
  6539. --| The name of the file to be renamed and a filename of the new
  6540. --| file.
  6541.  
  6542. --| Effects:
  6543. --| It renames a file in the file system with a new name.  The contents
  6544. --| of the file are not changed.
  6545.  
  6546. --| Modifies:
  6547. --| The external filename is changed to a new name.
  6548.  
  6549. --| N/A: Errors
  6550.                                                     pragma Page;
  6551. procedure Delete (        --| deletes the named file
  6552.     File : in String_Type    --| name of the file to be deleted
  6553.     );
  6554.  
  6555. --| Raises:
  6556. --| Delete_Error, Device_Not_Ready, Device_Write_Locked,
  6557. --| Directory_Not_Found, Parse_Error, Privilege_Violation
  6558.  
  6559. --| Requires:
  6560. --| Name of the file to be deleted.
  6561.  
  6562. --| Effects:
  6563. --| Deletes the named file from the file system.
  6564.  
  6565. --| Modifies:
  6566. --| The external file is delete from the file system.
  6567.  
  6568. --| N/A: Errors
  6569.                                                     pragma Page;
  6570. procedure Delete (        --| deletes the named file
  6571.     File : in string        --| name of the file to be deleted
  6572.     );
  6573.  
  6574. --| Raises:
  6575. --| Delete_Error, Device_Not_Ready, Device_Write_Locked,
  6576. --| Directory_Not_Found, Parse_Error, Privilege_Violation
  6577.  
  6578. --| Requires:
  6579. --| Name of the file to be deleted.
  6580.  
  6581. --| Effects:
  6582. --| Deletes the named file from the file system.
  6583.  
  6584. --| Modifies:
  6585. --| The external file is delete from the file system.
  6586.  
  6587. --| N/A: Errors
  6588.                                                     pragma Page;
  6589. procedure Copy (        --| copy one file to another.
  6590.     Input_File  : in String_Type;
  6591.                 --| name of the old file
  6592.     Output_File : in String_Type
  6593.                 --| name of the file to copy it into
  6594.     );
  6595.  
  6596. --| Raises:
  6597. --| Device_Not_Ready, Device_Write_Locked, Directory_Not_Found,
  6598. --| File_Already_Exists, File_Locked, File_Not_Found, Parse_Error,
  6599. --| Input_File_Error, Output_File_Error, Privilege_Violation
  6600.  
  6601. --| Requires:
  6602. --| Name of the file to be copied and a new name of a file to be
  6603. --| created with the same contents.
  6604.  
  6605. --| Effects:
  6606. --| Copies old file to new file.  The contents of the 
  6607. --| new file are identical to the contents of the old file.
  6608.  
  6609. --| Modifies:
  6610. --| A new file with the same contents is created.
  6611.  
  6612. --| N/A: Errors
  6613.                                                     pragma Page;
  6614. procedure Copy (        --| copy one file to another.
  6615.     Input_File  : in String_Type;
  6616.                 --| name of the old file
  6617.     Output_File : in string    --| name of the file to copy it into
  6618.     );
  6619.  
  6620. --| Raises:
  6621. --| Device_Not_Ready, Device_Write_Locked, Directory_Not_Found,
  6622. --| File_Already_Exists, File_Locked, File_Not_Found, Parse_Error,
  6623. --| Input_File_Error, Output_File_Error, Privilege_Violation
  6624.  
  6625. --| Requires:
  6626. --| Name of the file to be copied and a new name of a file to be
  6627. --| created with the same contents.
  6628.  
  6629. --| Effects:
  6630. --| Copies old file to new file.  The contents of the 
  6631. --| new file are identical to the contents of the old file.
  6632.  
  6633. --| Modifies:
  6634. --| A new file with the same contents is created.
  6635.  
  6636. --| N/A: Errors
  6637.                                                     pragma Page;
  6638. procedure Copy (        --| copy one file to another.
  6639.     Input_File  : in string;    --| name of the old file
  6640.     Output_File : in String_Type
  6641.                 --| name of the file to copy it into
  6642.     );
  6643.  
  6644. --| Raises:
  6645. --| Device_Not_Ready, Device_Write_Locked, Directory_Not_Found,
  6646. --| File_Already_Exists, File_Locked, File_Not_Found, Parse_Error,
  6647. --| Input_File_Error, Output_File_Error, Privilege_Violation
  6648.  
  6649. --| Requires:
  6650. --| Name of the file to be copied and a new name of a file to be
  6651. --| created with the same contents.
  6652.  
  6653. --| Effects:
  6654. --| Copies old file to new file.  The contents of the 
  6655. --| new file are identical to the contents of the old file.
  6656.  
  6657. --| Modifies:
  6658. --| A new file with the same contents is created.
  6659.  
  6660. --| N/A: Errors
  6661.                                                     pragma Page;
  6662. procedure Copy (        --| copy one file to another.
  6663.     Input_File  : in string;    --| name of the old file
  6664.     Output_File : in string    --| name of the file to copy it into
  6665.     );
  6666.  
  6667. --| Raises:
  6668. --| Device_Not_Ready, Device_Write_Locked, Directory_Not_Found,
  6669. --| File_Already_Exists, File_Locked, File_Not_Found, Parse_Error,
  6670. --| Input_File_Error, Output_File_Error, Privilege_Violation
  6671.  
  6672. --| Requires:
  6673. --| Name of the file to be copied and a new name of a file to be
  6674. --| created with the same contents.
  6675.  
  6676. --| Effects:
  6677. --| Copies old file to new file.  The contents of the 
  6678. --| new file are identical to the contents of the old file.
  6679.  
  6680. --| Modifies:
  6681. --| A new file with the same contents is created.
  6682.  
  6683. --| N/A: Errors
  6684.                                                     pragma Page;
  6685. procedure Append (        --| Appends a file to another file
  6686.     Input_File  : in String_Type;
  6687.                 --| File to append
  6688.     Append_File : in String_Type
  6689.                 --| File to be appended
  6690.     );
  6691.  
  6692. --| Raises:
  6693.  
  6694. --| Requires:
  6695. --| Name of the file to be appended and a name of a file to append.
  6696.  
  6697. --| Effects:
  6698. --| Appends file to another file. 
  6699.  
  6700. --| Modifies:
  6701.  
  6702. --| N/A: Errors
  6703.                                                     pragma Page;
  6704. procedure Append (        --| Appends a file to another file
  6705.     Input_File  : in String_Type;
  6706.                 --| File to append
  6707.     Append_File : in string    --| File to be appended
  6708.     );
  6709.  
  6710. --| Raises:
  6711.  
  6712. --| Requires:
  6713. --| Name of the file to be appended and a name of a file to append.
  6714.  
  6715. --| Effects:
  6716. --| Appends file to another file. 
  6717.  
  6718. --| Modifies:
  6719.  
  6720. --| N/A: Errors
  6721.                                                     pragma Page;
  6722. procedure Append (        --| Appends a file to another file
  6723.     Input_File  : in string;    --| File to append
  6724.     Append_File : in String_Type
  6725.                 --| File to be appended
  6726.     );
  6727.  
  6728. --| Raises:
  6729.  
  6730. --| Requires:
  6731. --| Name of the file to be appended and a name of a file to append.
  6732.  
  6733. --| Effects:
  6734. --| Appends file to another file. 
  6735.  
  6736. --| Modifies:
  6737.  
  6738. --| N/A: Errors
  6739.                                                     pragma Page;
  6740. procedure Append (        --| Appends a file to another file
  6741.     Input_File  : in string;    --| File to append
  6742.     Append_File : in string    --| File to be appended
  6743.     );
  6744.  
  6745. --| Raises:
  6746.  
  6747. --| Requires:
  6748. --| Name of the file to be appended and a name of a file to append.
  6749.  
  6750. --| Effects:
  6751. --| Appends file to another file. 
  6752.  
  6753. --| Modifies:
  6754.  
  6755. --| N/A: Errors
  6756.                                                     pragma Page;
  6757. function Expand (        --| Expands a name containing wild card
  6758.                 --| to a full filename
  6759.     File : in String_Type;    --| string to be expanded
  6760.     Mode : in Mode_Type := FULL    --| filename expansion mode
  6761.     ) return String_Lists.List;
  6762.  
  6763. --| Raises:
  6764. --| Device_Not_Ready, Directory_Not_Found, Expand_Error,
  6765. --| File_Not_Found, Parse_Error
  6766.  
  6767. --| Requires:
  6768. --| A string of characters with/without system dependent wild card
  6769. --| characters.
  6770.  
  6771. --| Effects:
  6772. --| It expands a string into a list of filenames matching all wild
  6773. --| card characters.
  6774.  
  6775. --| Modifies:
  6776. --| List contains a list of filename matching the given string.
  6777.  
  6778. --| N/A: Errors
  6779.                                                     pragma Page;
  6780. function Expand (        --| Expands a name containing wild card
  6781.                 --| to a full filename
  6782.     File : in string;        --| string to be expanded
  6783.     Mode : in Mode_Type := FULL    --| filename expansion mode
  6784.     ) return String_Lists.List;
  6785.  
  6786. --| Raises:
  6787. --| Device_Not_Ready, Directory_Not_Found, Expand_Error,
  6788. --| File_Not_Found, Parse_Error
  6789.  
  6790. --| Requires:
  6791. --| A string of characters with/without system dependent wild card
  6792. --| characters.
  6793.  
  6794. --| Effects:
  6795. --| It expands a string into a list of filenames matching all wild
  6796. --| card characters.
  6797.  
  6798. --| Modifies:
  6799. --| List contains a list of filename matching the given string.
  6800.  
  6801. --| N/A: Errors
  6802.                                                     pragma Page;
  6803. procedure Destroy (
  6804.     Name_List : in out String_Lists.List
  6805.     );
  6806.  
  6807. --| Raises:
  6808.  
  6809. --| Requires:
  6810. --| A list of filenames whose storate is to be released.
  6811.  
  6812. --| Effects:
  6813. --| All storeage associated with the given list is released.
  6814.  
  6815. --| Modifies:
  6816. --| Name_List
  6817.  
  6818. --| N/A: Errors
  6819.                                                     pragma Page;
  6820. function Strip_Dir (
  6821.     Long_Name : in String_Type
  6822.     ) return String_Type;
  6823.  
  6824. --| Raises:
  6825.  
  6826. --| Requires:
  6827. --| A filename whose name without device/directory is to be returned.
  6828.  
  6829. --| Effects:
  6830. --| Strips the device and directory name off a long file name
  6831.  
  6832. --| Modifies:
  6833.  
  6834. --| N/A: Errors
  6835.  
  6836.  
  6837. end  File_Manager;
  6838.                                                     pragma Page;
  6839. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6840. --FILEMGR.BDY
  6841. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6842. with System;            use System;
  6843. with Starlet;            use Starlet;
  6844. with Condition_Handling;    use Condition_Handling;
  6845. with String_Pkg;        use String_Pkg;
  6846.  
  6847. package body File_Manager is
  6848.  
  6849. subtype File_String is string (1 .. 255);
  6850.  
  6851. procedure Raise_Error (
  6852.     STS : Unsigned_Longword
  6853.     ) is
  6854.  
  6855. begin
  6856.  
  6857.     case STS is
  6858.     when RMS_DNF =>
  6859.         raise Directory_Not_Found;
  6860.     when RMS_DNR =>
  6861.         raise Device_Not_Ready;
  6862.     when RMS_FEX =>
  6863.         raise File_Already_Exists;
  6864.     when RMS_FLK =>
  6865.         raise File_Locked;
  6866.     when RMS_FNF =>
  6867.         raise File_Not_Found;
  6868.     when RMS_PRV =>
  6869.         raise Privilege_Violation;
  6870.     when RMS_WLK =>
  6871.         raise Device_Write_Locked;
  6872.     when others =>
  6873.         return;
  6874.     end case;
  6875.  
  6876. end Raise_Error;
  6877.                                                     pragma Page;
  6878. procedure Set_FAB_NAM (
  6879.     File  : in string;
  6880.     FAB   : in out FAB_Type;
  6881.     NAM   : in out NAM_Type;
  6882.     ES    : in out File_String
  6883.     ) is
  6884.  
  6885.     Status : Cond_Value_Type;
  6886.     From   : integer;
  6887.     To     : integer;
  6888.  
  6889. begin
  6890.  
  6891.     if File'length > 255 then
  6892.     raise File_Name_Error;
  6893.     end if;
  6894.     FAB     := FAB_Type_Init;
  6895.     FAB.FNA := File'address;
  6896.     FAB.FNS := Unsigned_Byte(File'length);
  6897.     FAB.NAM := NAM'address;
  6898.  
  6899.     NAM     := NAM_Type_Init;
  6900.     NAM.ESA := ES'address;
  6901.     NAM.ESS := Unsigned_Byte(ES'length);
  6902.  
  6903.     Starlet.Parse(Status, FAB);
  6904.     if Condition_Handling.Success(Status) then
  6905.     FAB.FOP.NAM := true;
  6906.     return;
  6907.     end if;
  6908.  
  6909.     Raise_Error(FAB.STS);
  6910.     raise Parse_Error;
  6911.  
  6912. end Set_FAB_NAM;
  6913.                                                     pragma Page;
  6914. procedure Copy_Append (    
  6915.     File1 : in string;
  6916.     File2 : in string;
  6917.     CIF   : in boolean
  6918.     ) is
  6919.  
  6920.     FAB1 : FAB_Type;
  6921.     NAM1 : NAM_Type;
  6922.     RAB1 : RAB_Type;
  6923.     ES1  : File_String;
  6924.     FAB2 : FAB_Type;
  6925.     NAM2 : NAM_Type;
  6926.     RAB2 : RAB_Type;
  6927.     ES2  : File_String;
  6928.     Buffer  : string (1 .. 1024);
  6929.     Status  : Cond_Value_Type;
  6930.  
  6931. begin
  6932.  
  6933.     Set_FAB_NAM(File => File1, FAB => FAB1, NAM => NAM1, ES => ES1);
  6934.     FAB1.FAC.GET := true;
  6935.     Starlet.Open(Status, FAB1);
  6936.     if not Condition_Handling.Success(Status) then
  6937.     Raise_Error(FAB1.STS);
  6938.     raise Input_File_Error;
  6939.     end if;
  6940.  
  6941.     RAB1     := RAB_Type_Init;
  6942.     RAB1.FAB := FAB1'address;
  6943.     RAB1.MBF := 2;
  6944.     RAB1.ROP.RAH := true;
  6945.     Starlet.Connect(Status, RAB1);
  6946.     if not Condition_Handling.Success(Status) then
  6947.     raise Input_File_Error;
  6948.     end if;
  6949.     RAB1.UBF := Buffer'address;
  6950.     RAB1.USZ := Unsigned_Word(Buffer'length);
  6951.  
  6952.     Set_FAB_NAM(File => File2, FAB => FAB2, NAM => NAM2, ES => ES2);
  6953.     FAB2.FAC.PUT := true;
  6954.     FAB2.FOP.CTG := true;
  6955.     FAB2.FOP.CIF := CIF;
  6956.     FAB2.RAT.CR  := true;
  6957.     Starlet.Create(Status, FAB2);
  6958.     if not Condition_Handling.Success(Status) then
  6959.     Raise_Error(FAB2.STS);
  6960.     raise Output_File_Error;
  6961.     end if;
  6962.     RAB2 := RAB_Type_Init;
  6963.     RAB2.FAB := FAB2'address;
  6964.     RAB2.MBF := 2;
  6965.     RAB2.ROP.EOF := CIF;
  6966.     RAB2.ROP.WBH := true;
  6967.     Starlet.Connect(Status, RAB2);
  6968.     if not Condition_Handling.Success(Status) then
  6969.     raise Output_File_Error;
  6970.     end if;
  6971.  
  6972.     Read_Write: loop
  6973.     Starlet.Get(Status, RAB1);
  6974.     if Condition_Handling.Success(Status) then
  6975.         RAB2.ROP.TPT := true;
  6976.         RAB2.RBF := RAB1.RBF;
  6977.         RAB2.RSZ := RAB1.RSZ;
  6978.         Starlet.Put(Status, RAB2);
  6979.         if not Condition_Handling.Success(Status) then
  6980.         Raise_Error(RAB2.STS);
  6981.         raise Output_File_Error;
  6982.         end if;
  6983.     else
  6984.         if RAB1.STS = RMS_EOF then
  6985.         exit Read_Write;
  6986.         end if;
  6987.         Raise_Error(RAB1.STS);
  6988.         raise Input_File_Error;
  6989.     end if;
  6990.     end loop Read_Write;
  6991.  
  6992.     Close(Status, FAB1);
  6993.     if not Condition_Handling.Success(Status) then
  6994.     Raise_Error(FAB1.STS);
  6995.     raise Input_File_Error;
  6996.     end if;
  6997.  
  6998.     Close(Status, FAB2);
  6999.     if not Condition_Handling.Success(Status) then
  7000.     Raise_Error(FAB2.STS);
  7001.     raise Output_File_Error;
  7002.     end if;
  7003.  
  7004. end Copy_Append;
  7005.                                                     pragma Page;
  7006.  procedure Rename (
  7007.     Old_File : in String_Type;
  7008.     New_File : in String_Type
  7009.     ) is
  7010.  
  7011. begin
  7012.  
  7013.     Rename(Old_File => String_Pkg.Value(Old_File),
  7014.        New_File => String_Pkg.Value(New_File));
  7015.  
  7016. end Rename;
  7017.                                                     pragma Page;
  7018. procedure Rename (
  7019.     Old_File : in String_Type;
  7020.     New_File : in string
  7021.     ) is
  7022.  
  7023. begin
  7024.  
  7025.     Rename(Old_File => String_Pkg.Value(Old_File),
  7026.        New_File => New_File);
  7027.  
  7028. end Rename;
  7029.                                                     pragma Page;
  7030. procedure Rename (
  7031.     Old_File : in string;
  7032.     New_File : in String_Type
  7033.     ) is
  7034.  
  7035. begin
  7036.  
  7037.     Rename(Old_File => Old_File,
  7038.        New_File => String_Pkg.Value(New_File));
  7039.  
  7040. end Rename;
  7041.                                                     pragma Page;
  7042. procedure Rename (
  7043.     Old_File : in string;
  7044.     New_File : in string
  7045.     ) is
  7046.  
  7047.     Old_FAB : FAB_Type;
  7048.     Old_NAM : NAM_Type;
  7049.     Old_ES  : File_String;
  7050.     Old_RS  : File_String;
  7051.     New_FAB : FAB_Type;
  7052.     New_NAM : NAM_Type;
  7053.     New_ES  : File_String; 
  7054.     New_RS  : File_String; 
  7055.     Status  : Cond_Value_Type;
  7056.  
  7057. begin
  7058.  
  7059.     Set_FAB_NAM(File => Old_File, FAB => Old_FAB, NAM => Old_NAM, ES => Old_ES);
  7060.     Old_NAM.RSA := Old_RS'address; 
  7061.     Old_NAM.RSS := Unsigned_Byte(Old_RS'length);
  7062.  
  7063.     Set_FAB_NAM(File => New_File, FAB => New_FAB, NAM => New_NAM, ES => New_ES);
  7064.     New_NAM.RSA := New_RS'address; 
  7065.     New_NAM.RSS := Unsigned_Byte(New_RS'length);
  7066.  
  7067.     Starlet.Rename(Status, OldFAB => Old_FAB, NewFAB => New_FAB);
  7068.     if Condition_Handling.Success(Status) then
  7069.     return;
  7070.     end if;
  7071.  
  7072.     Raise_Error(Old_FAB.STS);
  7073.     raise Rename_Error;
  7074.  
  7075. end Rename;
  7076.                                                     pragma Page;
  7077. procedure Delete (
  7078.     File : in String_Type
  7079.     ) is
  7080.  
  7081. begin
  7082.  
  7083.     Delete (File => String_Pkg.Value(File));
  7084.  
  7085. end Delete;
  7086.                                                     pragma Page;
  7087. procedure Delete (
  7088.     File : in string
  7089.     ) is
  7090.  
  7091.     FAB    : FAB_Type;
  7092.     NAM    : NAM_Type;
  7093.     ES     : File_String;
  7094.     Status : Cond_Value_Type;
  7095.  
  7096. begin
  7097.  
  7098.     Set_FAB_NAM(File => File, FAB => FAB, NAM => NAM, ES => ES);
  7099.     Starlet.Erase(Status, FAB);
  7100.     if Condition_Handling.Success(Status) then
  7101.     return;
  7102.     end if;
  7103.  
  7104.     Raise_Error(FAB.STS);
  7105.     raise Delete_Error;
  7106.  
  7107. end Delete;
  7108.                                                     pragma Page;
  7109. procedure Copy (
  7110.     Input_File  : in String_Type;
  7111.     Output_File : in String_Type
  7112.     ) is
  7113.  
  7114. begin
  7115.  
  7116.     Copy_Append(File1 => String_Pkg.Value(Input_File),
  7117.         File2 => String_Pkg.Value(Output_File),
  7118.         CIF   => false);
  7119.  
  7120. end Copy;
  7121.                                                     pragma Page;
  7122. procedure Copy (
  7123.     Input_File  : in String_Type;
  7124.     Output_File : in string
  7125.     ) is
  7126.  
  7127. begin
  7128.  
  7129.     Copy_Append(File1 => String_Pkg.Value(Input_File),
  7130.         File2 => Output_File,
  7131.         CIF   => false);
  7132.  
  7133. end Copy;
  7134.                                                     pragma Page;
  7135. procedure Copy (
  7136.     Input_File  : in string;
  7137.     Output_File : in String_Type
  7138.     ) is
  7139.  
  7140. begin
  7141.  
  7142.     Copy_Append(File1 => Input_File,
  7143.         File2 => String_Pkg.Value(Output_File),
  7144.         CIF   => false);
  7145.  
  7146. end Copy;
  7147.                                                     pragma Page;
  7148. procedure Copy (
  7149.     Input_File  : in string;
  7150.     Output_File : in string
  7151.     ) is
  7152.  
  7153. begin
  7154.  
  7155.     Copy_Append(File1 => Input_File,
  7156.         File2 => Output_File,
  7157.         CIF   => false);
  7158.  
  7159. end Copy;
  7160.                                                     pragma Page;
  7161. procedure Append (
  7162.     Input_File  : in String_Type;
  7163.     Append_File : in String_Type
  7164.     ) is
  7165.  
  7166. begin
  7167.  
  7168.     Copy_Append(File1 => String_Pkg.Value(Input_File),
  7169.         File2 => String_Pkg.Value(Append_File),
  7170.         CIF   => true);
  7171.  
  7172. end Append;
  7173.                                                     pragma Page;
  7174. procedure Append (
  7175.     Input_File  : in String_Type;
  7176.     Append_File : in string
  7177.     ) is
  7178.  
  7179. begin
  7180.  
  7181.     Copy_Append(File1 => String_Pkg.Value(Input_File),
  7182.         File2 => Append_File,
  7183.         CIF   => true);
  7184.  
  7185. end Append;
  7186.                                                     pragma Page;
  7187. procedure Append (
  7188.     Input_File  : in string;
  7189.     Append_File : in String_Type
  7190.     ) is
  7191.  
  7192. begin
  7193.  
  7194.     Copy_Append(File1 => Input_File,
  7195.         File2 => String_Pkg.Value(Append_File),
  7196.         CIF   => true);
  7197.  
  7198. end Append;
  7199.                                                     pragma Page;
  7200. procedure Append (
  7201.     Input_File  : in string;
  7202.     Append_File : in string
  7203.     ) is
  7204.  
  7205. begin
  7206.  
  7207.     Copy_Append(File1 => Input_File,
  7208.         File2 => Append_File,
  7209.         CIF   => true);
  7210.  
  7211. end Append;
  7212.                                                     pragma Page;
  7213. function Expand (
  7214.     File : in String_Type;
  7215.     Mode : in Mode_Type := FULL
  7216.     ) return String_Lists.List is
  7217.  
  7218. begin
  7219.  
  7220.     return Expand (File => String_Pkg.Value(File), Mode => Mode);
  7221.  
  7222. end Expand;
  7223.                                                     pragma Page;
  7224. function Expand (
  7225.     File : in string;
  7226.     Mode : in Mode_Type := FULL
  7227.     ) return String_Lists.List is
  7228.  
  7229.     FAB      : FAB_Type;
  7230.     NAM      : NAM_Type;
  7231.     ES       : File_String;
  7232.     RS       : File_String;
  7233.     Status   : Cond_Value_Type;
  7234.     Files    : String_Lists.List;
  7235.     New_List : boolean := true;
  7236.     Index1   : integer := RS'last;
  7237.     Index2   : integer := RS'first;
  7238.  
  7239. begin
  7240.  
  7241.     Set_FAB_NAM(File => File, FAB => FAB, NAM => NAM, ES => ES);
  7242.     FAB.IFI := FAB_IFI_Type_Init;
  7243.     NAM.RSA := RS'address; 
  7244.     NAM.RSS := Unsigned_Byte(RS'length);
  7245.  
  7246.     String_Pkg.Mark;
  7247.     loop
  7248.     Starlet.Search(Status, FAB);
  7249.     if Condition_Handling.Success(Status) then
  7250.         if New_List then
  7251.         Files := String_Lists.Create;
  7252.         New_List := false;
  7253.         end if;
  7254.         case Mode is
  7255.         when NO_DIRECTORY | FILE_ONLY =>
  7256.             for i in 1 .. integer(NAM.RSL) loop
  7257.             if RS(i) = ']' then
  7258.                 Index1 := i + 1;
  7259.                 exit;
  7260.             end if;
  7261.             end loop;
  7262.         when others =>
  7263.             Index1 := RS'first;
  7264.         end case;
  7265.         case Mode is
  7266.         when NO_VERSION | FILE_ONLY =>
  7267.             for i in reverse 1 .. natural(NAM.RSL) loop
  7268.             if RS(i) = ';' then
  7269.                 Index2 := i - 1;
  7270.                 exit;
  7271.             end if;
  7272.             end loop;
  7273.         when others =>
  7274.             Index2 := integer(NAM.RSL);
  7275.         end case;
  7276.         declare
  7277.         File_ID : string(1 .. Index2 - Index1 + 1);
  7278.         begin
  7279.         File_ID(File_ID'first .. File_ID'last) := RS(Index1 .. Index2);
  7280.         String_Lists.Attach(Files, String_Pkg.Make_Persistent(File_ID));
  7281.         end;
  7282.     else
  7283.         if FAB.STS = RMS_NMF then
  7284.         return Files;
  7285.         end if;
  7286.         Raise_Error(FAB.STS);
  7287.         raise Expand_Error;
  7288.     end if;
  7289.     end loop;
  7290.     String_Pkg.Release;
  7291.  
  7292. end Expand;
  7293.                                                     pragma Page;
  7294. procedure Destroy (
  7295.     Name_List : in out String_Lists.List
  7296.     ) is
  7297.  
  7298.     Iterator : String_Lists.ListIter;
  7299.     Name     : String_Type;
  7300.  
  7301. begin
  7302.  
  7303.     Iterator := String_Lists.MakeListIter(Name_List);
  7304.     while (String_Lists.More(Iterator)) loop
  7305.     String_Lists.Next(Iterator, Name);
  7306.     String_Pkg.Flush(Name);
  7307.     end loop;
  7308.     String_Lists.Destroy(Name_List);
  7309.  
  7310. end Destroy;
  7311.                                                     pragma Page;
  7312. function Strip_Dir (
  7313.     Long_Name : in String_Type
  7314.     ) return String_Type is
  7315.  
  7316.     N : natural;
  7317.  
  7318.     begin
  7319.  
  7320.     N := String_Pkg.Match_C (Long_Name, ']', 1);
  7321.     if N = 0 then
  7322.         return Long_Name;
  7323.     else
  7324.         return String_Pkg.Substr
  7325.             (Long_Name, N + 1, String_Pkg.Length(Long_Name) - N);
  7326.     end if;
  7327.  
  7328.     end Strip_Dir;
  7329.  
  7330.  
  7331. end  File_Manager;
  7332.                                                     pragma Page;
  7333. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7334. --HASHFCNS.SPC
  7335. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7336. package hashing_functions_pkg is
  7337.     
  7338.     generic
  7339.     prime_num: in positive; 
  7340.             --| Required to be prime.         
  7341.  
  7342.     function hash_string(s: string) return natural;
  7343.       --| Effects: 
  7344.       --| Produces a uniform distribution over the range 0..prime - 1.
  7345.     
  7346. end hashing_functions_pkg;
  7347. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7348. --HASHFCNS.BDY
  7349. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7350. with unchecked_conversion;
  7351.  
  7352. package body hashing_functions_pkg is
  7353.     
  7354.     function hash_string(s: string) return natural is
  7355.  
  7356.     type word is array(1..32) of boolean; 
  7357.  
  7358.     function word_to_int is new 
  7359.         unchecked_conversion(source => word, target => integer); 
  7360.  
  7361.     chars_per_word: constant := 4; 
  7362.     subtype word_str is string(1..chars_per_word); 
  7363.  
  7364.     function word_str_to_word is new 
  7365.         unchecked_conversion(source => word_str, target => word);
  7366.  
  7367.     words_in_s: natural;
  7368.     left_over: natural;
  7369.    
  7370.     hash_word: word := (word'range => false);
  7371.  
  7372.     hack_word_str: word_str;   --Decbug
  7373.     hack_word: word;       --Decbug
  7374.     result1: integer;       --Decbug
  7375.     result2: natural;        --Decbug
  7376.  
  7377.     begin
  7378.     words_in_s := s'length/chars_per_word;
  7379.     left_over := s'length mod chars_per_word;
  7380.  
  7381. --Decbugs replacement: 
  7382.     for i in 1..words_in_s loop
  7383.         hack_word_str :=  s(s'first + chars_per_word * (i - 1) .. 
  7384.                 s'first + chars_per_word * i - 1);          
  7385.         hack_word := word_str_to_word(hack_word_str);
  7386.         hash_word := hash_word xor hack_word;        
  7387. --        hash_word := 
  7388. --        hash_word xor 
  7389. --        word_str_to_word(s(s'first + chars_per_word * (i - 1) ..
  7390. --                   s'first + chars_per_word * i - 1)); 
  7391.     end loop;
  7392.  
  7393. -- Decbug Replacements: 
  7394.         hack_word_str(1..left_over) := 
  7395.         s(s'first + chars_per_word * words_in_s .. s'last);
  7396.         hack_word := word_str_to_word(hack_word_str);    
  7397.         hash_word(1..left_over) :=         
  7398.         hash_word(1..left_over) xor hack_word(1..left_over); 
  7399.  
  7400. --    hash_word(1..left_over) := 
  7401. --        hash_word(1..left_over) xor
  7402. --        word_str_to_word(s(s'first + chars_per_word * words_in_s..s'last));
  7403.  
  7404.     result1 := word_to_int(hash_word); 
  7405.     result2 := result1 mod prime_num; 
  7406.     return result2; 
  7407.  
  7408. --    return word_to_int(hash_word) mod prime_num;
  7409.     end hash_string; 
  7410.  
  7411. end hashing_functions_pkg; 
  7412. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7413. --VMSLIB.BDY
  7414. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7415. with TEXT_IO;
  7416.  
  7417. ----------------------------------------------------------------    
  7418.  
  7419. package body VMS_Lib is
  7420.  
  7421. ----------------------------------------------------------------    
  7422.  
  7423. procedure Set_Error is
  7424.  
  7425.     FileType : TEXT_IO.FILE_TYPE;
  7426.  
  7427.     begin
  7428.  
  7429.         TEXT_IO.Create(File => FileType, Name => "SYS$ERROR");
  7430.         TEXT_IO.Set_Output(FileType);
  7431.  
  7432.     end Set_Error;
  7433.  
  7434. end VMS_Lib;
  7435.  
  7436. ----------------------------------------------------------------    
  7437. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7438. --HOSTDEP.SPC
  7439. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7440.  
  7441. package Host_Dependencies is
  7442. --| Simple data types and constants involving the Host Machine.
  7443.     
  7444.                     -- Types and Objects --
  7445.  
  7446.     MaxColumn : constant := 250;
  7447.     subtype Source_Column is Natural range 0..MaxColumn;
  7448.     MaxLine : constant := 100000; -- This is completely arbitrary
  7449.     subtype Source_Line is Natural range 0..MaxLine;
  7450.  
  7451.                         -- Operations --
  7452.  
  7453.     function FindTabColumn (       --| returns source column a tab is in
  7454.         InColumn : Source_Column   --| source column before tab
  7455.         ) return Source_Column;
  7456.  
  7457.     --| Effects
  7458.  
  7459.     --| This subprogram implements the tab positioning strategy
  7460.     --| of the Host system.
  7461.  
  7462. end Host_Dependencies;
  7463.  
  7464. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7465. --ERRMSG.SPC
  7466. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7467.  
  7468. ----------------------------------------------------------------------
  7469.  
  7470. with Host_Dependencies;           -- host dependent constants
  7471.  
  7472. package Lexical_Error_Message is  --| handles lexical error messages
  7473.  
  7474. --| Overview
  7475. --|
  7476. --| Contains text, identifiers of text, and output subprograms
  7477. --| for package Lex.
  7478. --|
  7479.  
  7480.     package HD renames Host_Dependencies;
  7481.  
  7482.     --------------------------------------------------------------
  7483.     -- Declarations Global to Package Lexical_Error_Message
  7484.     ------------------------------------------------------------------
  7485.  
  7486.     type Message_Type is (
  7487.         Base_Out_Of_Legal_Range_Use_16,
  7488.         Based_Literal_Delimiter_Mismatch,
  7489.         Character_Can_Not_Start_Token,
  7490.         Character_Is_Non_ASCII,
  7491.         Character_Is_Non_Graphic,
  7492.         Consecutive_Underlines,
  7493.         Digit_Invalid_For_Base,
  7494.         Digit_Needed_After_Radix_Point,
  7495.         Digit_Needed_Before_Radix_Point,
  7496.         Exponent_Missing_Integer_Field,
  7497.         Illegal_Use_Of_Single_Quote,
  7498.         Integer_Literal_Conversion_Exception_Use_1,
  7499.         Leading_Underline,
  7500.         Missing_Second_Based_Literal_Delimiter,
  7501.         Negative_Exponent_Illegal_In_Integer,
  7502.         No_Ending_String_Delimiter,
  7503.         No_Integer_In_Based_Number,
  7504.         Only_Graphic_Characters_In_Strings,
  7505.         Real_Literal_Conversion_Exception_Use_1,
  7506.         Source_Line_Maximum_Exceeded,
  7507.         Source_Line_Too_Long,
  7508.         Space_Must_Separate_Num_And_Ids,
  7509.         Terminal_Underline,
  7510.         Too_Many_Radix_Points);
  7511.  
  7512.     --------------------------------------------------------------
  7513.     -- Subprogram Bodies Global to Package Lexical_Error_Message
  7514.     --------------------------------------------------------------
  7515.  
  7516.     procedure Output_Message(             --| output lexical error message
  7517.         In_Line   : in HD.Source_Line;    --| line number of error.
  7518.         In_Column : in HD.Source_Column;  --| column number of error.
  7519.         In_Message_Id : in Message_Type); --| which message to output.
  7520.  
  7521.     --| Effects
  7522.     --|
  7523.     --| Output error message for lexer.
  7524.     --|
  7525.  
  7526.     ------------------------------------------------------------------
  7527.  
  7528.     procedure Output_Message(             --| output lexical error message
  7529.         In_Line   : in HD.Source_Line;    --| line number of error.
  7530.         In_Column : in HD.Source_Column;  --| column number of error.
  7531.         In_Insertion_Text : in string;    --| text to insert.
  7532.         In_Message_Id : in Message_Type); --| which message to output.
  7533.  
  7534.     --| Effects
  7535.     --|
  7536.     --| Output error message with inserted text.  The text is appended
  7537.     --| to the message if there are no insertion flags.
  7538.  
  7539.     ------------------------------------------------------------------
  7540.  
  7541. end Lexical_Error_Message;
  7542.  
  7543. ----------------------------------------------------------------------
  7544.  
  7545. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7546. --ERRMSG.BDY
  7547. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7548.  
  7549.  
  7550. ------------------------------------------------------------------
  7551.  
  7552. with TEXT_IO;
  7553.  
  7554. package body Lexical_Error_Message is
  7555.  
  7556. ------------------------------------------------------------------
  7557. -- Declarations Local to Package Lexical_Error_Message
  7558. ------------------------------------------------------------------
  7559.  
  7560.     Insertion_Flag : character := '@';
  7561.  
  7562.     subtype Message_Text_Range is positive range 1..64;
  7563.  
  7564.     Message_Text : constant array (Message_Type) of
  7565.         string (Message_Text_Range) := (
  7566.     -- 1234567890123456789012345678901234567890123456789012345678901234
  7567.     -- Base_Out_Of_Legal_Range_Use_16   =>
  7568.       "This base " &
  7569.            Insertion_Flag  -- insert a String
  7570.            & " is not in the range 2 to 16. Assuming base 16.      ",
  7571.     -- Based_Literal_Delimiter_Mismatch =>
  7572.       "Based_literal delimiters must be the same.                      ",
  7573.     -- Character_Can_Not_Start_Token    =>
  7574.       "This character " &
  7575.             Insertion_Flag  -- insert a character
  7576.             & " can not start a token.                         ",
  7577.     -- Character_Is_Non_ASCII  =>
  7578.       "This value x@VALUE@x is not an ASCII character.                 ",
  7579.         --|? should display the value, but this message is unlikely.
  7580.         --|? see Lex.bdy
  7581.     -- Character_Is_Non_Graphic=>
  7582.       "This character with decimal value" &
  7583.                       Insertion_Flag
  7584.                                           -- insert the decimal value
  7585.                       & " is not a graphic_character.  ",
  7586.     -- Consecutive_Underlines  =>
  7587.       "Consecutive underlines are not allowed.                         ",
  7588.     -- Digit_Invalid_For_Base  =>
  7589.       "This digit " &
  7590.            Insertion_Flag  -- insert a Character
  7591.         & " is out of range for the base specified.            ",
  7592.     -- Digit_Needed_After_Radix_Point   =>
  7593.       "At least one digit must appear after a radix point              ",
  7594.     -- Digit_Needed_Before_Radix_Point  =>
  7595.       "At least one digit must appear before a radix point             ",
  7596.     -- Exponent_Missing_Integer_Field   =>
  7597.       "The exponent is missing its integer field.                      ",
  7598.     -- Illegal_Use_Of_Single_Quote  =>
  7599.       "Single quote is not used for an attribute or character literal. ",
  7600.     -- Integer_Literal_Conversion_Exception_Using_1 =>
  7601.       "Error while evaluating a integer_literal. Using a value of '1'. ",
  7602.     -- Leading_Underline    =>
  7603.       "Initial underlines are not allowed.                             ",
  7604.     -- Missing_Second_Based_Literal_Delimiter   =>
  7605.       "Second based_literal delimiter is missing.                      ",
  7606.     -- Negative_Exponent_Illegal_In_Integer =>
  7607.       "A negative exponent is illegal in an integer literal.           ",
  7608.     -- No_Ending_String_Delimiter   =>
  7609.       "String is improperly terminated by the end of the line.         ",
  7610.     -- No_Integer_In_Based_Number   =>
  7611.       "A based number must have a value.                               ",
  7612.     -- Only_Graphic_Characters_In_Strings   =>
  7613.       "This non-graphic character with decimal value" &
  7614.                             Insertion_Flag
  7615.                                                -- insert the decimal value
  7616.                           & " found in string. ",
  7617.     -- Real_Literal_Conversion_Exception_Using_1    =>
  7618.       "Error while evaluating a real_literal. Using a value of '1.0'.  ",
  7619.     -- Source_Line_Maximum_Exceeded =>
  7620.       "Maximum allowable source line number of " &
  7621.                            Insertion_Flag
  7622.                                                -- insert an Integer'IMAGE
  7623.                                              & " exceeded.             ",
  7624.     -- Source_Line_Too_Long =>
  7625.       "Source line number " &
  7626.                 Insertion_Flag  -- insert an Integer'IMAGE
  7627.             & " is too long.                               ",
  7628.     -- Space_Must_Separate_Num_And_Ids      =>
  7629.       "A space must separate numeric_literals and identifiers.         ",
  7630.     -- Terminal_Underline   =>
  7631.       "Terminal underlines are not allowed.                            ",
  7632.     -- Too_Many_Radix_Points        =>
  7633.       "A real_literal may have only one radix point.                   ");
  7634.  
  7635.     ------------------------------------------------------------------
  7636.     -- Subprogram Bodies Global to Package Lexical_Error_Message
  7637.     ------------------------------------------------------------------
  7638.  
  7639.     procedure Output_Message(
  7640.     In_Line       : in HD.Source_Line;
  7641.     In_Column     : in HD.Source_Column;
  7642.     In_Message_Id : in Message_Type) is
  7643.  
  7644.     begin
  7645.  
  7646.         -- output error message including line and column number
  7647.     TEXT_IO.NEW_LINE(TEXT_IO.STANDARD_OUTPUT);
  7648.     TEXT_IO.PUT_LINE(
  7649.             FILE => TEXT_IO.STANDARD_OUTPUT,
  7650.         ITEM =>
  7651.          "Lexical Error: Line: "
  7652.         & HD.Source_Line'IMAGE  (In_Line)
  7653.         & " Column: "
  7654.         & HD.Source_Column'IMAGE(In_Column)
  7655.         & " - "
  7656.         & Message_Text(In_Message_Id));
  7657.  
  7658.     end Output_Message;
  7659.  
  7660.     ------------------------------------------------------------------
  7661.  
  7662.     procedure Output_Message(
  7663.     In_Line       : in HD.Source_Line;
  7664.     In_Column     : in HD.Source_Column;
  7665.     In_Insertion_Text : in string; --| text to insert.
  7666.     In_Message_Id : in Message_Type) is
  7667.  
  7668.         --------------------------------------------------------------
  7669.         -- Declarations for SubProgram Output_Message
  7670.         --------------------------------------------------------------
  7671.  
  7672.         Insertion_Index : positive :=
  7673.             (Message_Text_Range'Last + 1);
  7674.         --| if insertion flag is not found,
  7675.         --| then we append the In_Message_Text to the message
  7676.  
  7677.     ------------------------------------------------------------------
  7678.  
  7679.     begin
  7680.  
  7681.     --| Algorithm
  7682.     --|
  7683.     --| Find the insertion point.
  7684.     --| if the Message_Text doesn't have an Insertion_Flag,
  7685.     --| then set the Insertion_Index to the end of the message.
  7686.  
  7687.     for i in Message_Text_Range loop
  7688.         if (Insertion_Flag = Message_Text(In_Message_Id)(i) ) then
  7689.             Insertion_Index := i;
  7690.             exit;
  7691.         end if;
  7692.     end loop;
  7693.  
  7694.     -- output error message with test, line and column number
  7695.     TEXT_IO.NEW_LINE(TEXT_IO.STANDARD_OUTPUT);
  7696.     TEXT_IO.PUT_LINE(
  7697.             FILE => TEXT_IO.STANDARD_OUTPUT,
  7698.         ITEM =>
  7699.           "Lexical Error: Line: "
  7700.         & HD.Source_Line'IMAGE  (In_Line)
  7701.         & " Column: "
  7702.         & HD.Source_Column'IMAGE(In_Column)
  7703.         & " - "
  7704.         & Message_Text(In_Message_Id)(1..(Insertion_Index-1))
  7705.         & In_Insertion_Text
  7706.         & Message_Text(In_Message_Id)
  7707.                     ((Insertion_Index+1)..Message_Text_Range'Last));
  7708.  
  7709.     end Output_Message;
  7710.  
  7711.     ------------------------------------------------------------------
  7712.  
  7713. end Lexical_Error_Message;
  7714.  
  7715. ----------------------------------------------------------------------
  7716.  
  7717. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7718. --HOSTDEP.BDY
  7719. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7720.  
  7721. package body Host_Dependencies is
  7722. --| Simple data types and constants involving the host machine
  7723.  
  7724.                             -- Operations --
  7725.  
  7726.     function FindTabColumn (          -- see subprogram specification
  7727.         InColumn : Source_Column
  7728.         ) return Source_Column is
  7729.  
  7730.     --| Effects
  7731.     --| Tabs are positioned every eight columns starting at column 1.
  7732.  
  7733.     Tab_Width : constant := 8; --| number of columns a tab takes up.
  7734.  
  7735.     begin
  7736.         return (InColumn + ( Tab_Width - ( InColumn mod Tab_Width) ) );
  7737.     end FindTabColumn;
  7738.  
  7739. end Host_Dependencies;
  7740.  
  7741. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7742. --GRMCONST.SPC
  7743. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7744.  
  7745.  
  7746. package Grammar_Constants is
  7747.  
  7748.  
  7749.       type ParserInteger is range 0..400000; -- arbitrary upper bound
  7750.           --| range of possible values for parser's integer values
  7751.         
  7752.     function setGrammarSymbolCount return ParserInteger;
  7753.     
  7754.     function setActionCount return ParserInteger;
  7755.     
  7756.     function setStateCountPlusOne return ParserInteger;
  7757.     
  7758.     function setLeftHandSideCount return ParserInteger;
  7759.     
  7760.     function setRightHandSideCount return ParserInteger;
  7761.     
  7762. end Grammar_Constants;
  7763.  
  7764. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7765. --PTBLS.SPC
  7766. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7767. ----------------------------------------------------------------------
  7768. with Host_Dependencies;      -- host dependent constants for the compiler.
  7769. with Grammar_Constants;      -- constants generated by parser generator
  7770. use Grammar_Constants;
  7771.  
  7772. package ParseTables is          --| Table output of parse tables generator
  7773.  
  7774. --| Overview
  7775. --|
  7776. --| This package contains the constants and tables generated by running
  7777. --| the LALR(1) parse tables generator on the Ada Grammar.
  7778. --| It also contains subprograms to access values in the more complex
  7779. --| tables, that could have their structures tuned later.
  7780. --|
  7781.  
  7782. --| Tuning
  7783. --|
  7784. --| --------------------------------------------------------------
  7785. --|
  7786. --| The Parser Generator has two options that effect the speed of
  7787. --| compilation:
  7788. --|
  7789. --| NODEFAULT : Eliminates the default reductions.
  7790. --| This also would improve error recovery.
  7791. --| Note that the table DefaultMap is still produced, though it
  7792. --| will never be referenced.
  7793. --| Thus, there need be no change to the code
  7794. --| in ParserUtilities.GetAction .
  7795. --|
  7796. --| LF : This changes the load factor used to pack and size the
  7797. --| ActionTables. It can range between 0 and 100.
  7798. --| A low LF means fewer collisions and faster parsing.
  7799. --| A high LF means more collisions and slower parsing.
  7800. --| ----------------------------------------------------------------
  7801. --|
  7802. --| The types GrammarSymbolRecord and FollowSymbolRecord
  7803. --| have a lot of unused space. The space/time tradeoff of
  7804. --| converting these into discriminated records or another
  7805. --| alternative representation, could be investigated.
  7806. --| This investigation should take the elaboration time
  7807. --| of the initializing aggregates into account.
  7808. --|
  7809. --| ----------------------------------------------------------------
  7810. --|
  7811. --| The Action Tables might be made made smaller by a restructuring of
  7812. --| the grammar.
  7813. --| For example: Have a rule for the token sequence:
  7814. --|
  7815. --| BEGIN seq_Of_Statements [EXCP..]
  7816. --|
  7817. --| ----------------------------------------------------------------
  7818. --|
  7819. --| The ParserGenerator might be modified along with
  7820. --| ParseTables.GetAction to produce smaller tables.
  7821. --| See:
  7822. --|
  7823. --| "Combined Actions to Reduce LR-Parsertables"
  7824. --| by K.Groneing. SIGPLAN Notices, Volume 19, Number 3, March 1984.
  7825. --|
  7826. --| ----------------------------------------------------------------
  7827. --|
  7828.  
  7829. --| Notes
  7830. --|
  7831. --| Abbreviations Used
  7832. --|
  7833. --| Rep : Representation
  7834. --|
  7835.  
  7836. --| RUN-TIME INPUT OF NYU LALR GENERATED TABLES AND CONSTANTS
  7837. --|
  7838. --|
  7839. --| followed by the current correct value of the
  7840. --| constant supplied by the NYU LALR Parser Generator:
  7841. --|
  7842. --| GrammarSymbolCount
  7843. --| LeftHandSideCount
  7844. --| RightHandSideCount
  7845. --| ActionTableOneLength
  7846. --| ActionTableTwoLength
  7847. --| DefaultMapLength
  7848. --| InSymbolMapLength
  7849. --| FollowMapLength
  7850. --| StateCountPlusOne
  7851. --| GrammarSymbolCountPlusOne
  7852. --| ActionCount
  7853. --| ActionTableSize
  7854. --|
  7855. --| in each of the eight declarations:
  7856. --|
  7857. --| GrammarSymbolTable
  7858. --| LeftHandSide
  7859. --| RightHandSide
  7860. --| ActionTableOne
  7861. --| ActionTableTwo
  7862. --| DefaultMap
  7863. --| InSymbolMap
  7864. --| FollowSymbolMap
  7865. --|
  7866.  
  7867.     package GC renames Grammar_Constants;
  7868.  
  7869.     ------------------------------------------------------------------
  7870.     -- Common Declarations for Action_Token_Map
  7871.     ------------------------------------------------------------------
  7872.  
  7873.     Max_Action_Token_Count : constant := 48;
  7874.         --| This constant may need to be made larger if the grammar
  7875.         --| ever gets too large.
  7876.         --| It could be automatically generated.
  7877.  
  7878.  
  7879.     ------------------------------------------------------------------
  7880.     -- Common Declarations for Shift_State_Map
  7881.     ------------------------------------------------------------------
  7882.  
  7883.     Max_Shift_State_Count : constant := 90;
  7884.         --| This constant may need to be made larger if the grammar
  7885.         --| ever gets too large.
  7886.         --| It could be automatically generated.
  7887.         
  7888.     
  7889.     
  7890.     subtype ParserStringRangePlusZeroCommon is natural
  7891.             range 0..Host_Dependencies.MaxColumn;
  7892.         --| Parser's string should never be greater than a source line
  7893.         --| worth of text.
  7894.     
  7895.     subtype GrammarSymbolRepRangePlusZeroCommon is
  7896.             ParserStringRangePlusZeroCommon range 0..57;
  7897.  
  7898.     subtype FollowSymbolRangeCommon is GC.ParserInteger range 1..50;
  7899.  
  7900.     ------------------------------------------------------------------
  7901.     -- Declarations Global to Package ParseTables
  7902.     ------------------------------------------------------------------
  7903.  
  7904.     subtype PositiveParserInteger is GC.ParserInteger range
  7905.         1..GC.ParserInteger'last ;
  7906.  
  7907.     subtype ParserStringRangePlusZero is
  7908.         ParserStringRangePlusZeroCommon;
  7909.         --| Parser's string should never be greater than a source line
  7910.         --| worth of text.
  7911.  
  7912. ----------------------------------------------------------------------
  7913. -- The first constant used to  the Parse Tables
  7914. ----------------------------------------------------------------------
  7915.  
  7916. GrammarSymbolCount : constant GC.ParserInteger :=
  7917.     GC.setGrammarSymbolCount ;
  7918.     --| Number of terminals and nonterminals in the Ada grammar
  7919.     --| rules input to the parse tables generator
  7920.  
  7921.     subtype GrammarSymbolRange is
  7922.         GC.ParserInteger range 1..GrammarSymbolCount;
  7923.         --| valid range of values for grammar symbols
  7924.  
  7925.     ------------------------------------------------------------------
  7926.     -- Parser Table Generated Token Values for Terminals
  7927.     ------------------------------------------------------------------
  7928.  
  7929.     -- WARNING: need to be checked after each Parser Generator Run.
  7930.     -- This could be made part of the ParseTables/ErrorParseTables
  7931.     -- generator program(s) at some point.
  7932.  
  7933.     ------------------------------------------------------------------
  7934.     -- Special Empty Terminal
  7935.     ------------------------------------------------------------------
  7936.  
  7937.     Empty_TokenValue    : constant GrammarSymbolRange :=  1;
  7938.  
  7939.     ------------------------------------------------------------------
  7940.     -- Reserved Words
  7941.     ------------------------------------------------------------------
  7942.  
  7943.     AbortTokenValue     : constant GrammarSymbolRange :=  2;
  7944.     AbsTokenValue       : constant GrammarSymbolRange :=  3;
  7945.     AcceptTokenValue    : constant GrammarSymbolRange :=  4;
  7946.     AccessTokenValue    : constant GrammarSymbolRange :=  5;
  7947.     AllTokenValue       : constant GrammarSymbolRange :=  6;
  7948.     AndTokenValue       : constant GrammarSymbolRange :=  7;
  7949.     ArrayTokenValue     : constant GrammarSymbolRange :=  8;
  7950.     AtTokenValue        : constant GrammarSymbolRange :=  9;
  7951.     BeginTokenValue     : constant GrammarSymbolRange := 10;
  7952.     BodyTokenValue      : constant GrammarSymbolRange := 11;
  7953.     CaseTokenValue      : constant GrammarSymbolRange := 12;
  7954.     ConstantTokenValue  : constant GrammarSymbolRange := 13;
  7955.     DeclareTokenValue   : constant GrammarSymbolRange := 14;
  7956.     DelayTokenValue     : constant GrammarSymbolRange := 15;
  7957.     DeltaTokenValue     : constant GrammarSymbolRange := 16;
  7958.     DigitsTokenValue    : constant GrammarSymbolRange := 17;
  7959.     DoTokenValue        : constant GrammarSymbolRange := 18;
  7960.     ElseTokenValue      : constant GrammarSymbolRange := 19;
  7961.     ElsifTokenValue     : constant GrammarSymbolRange := 20;
  7962.     EndTokenValue       : constant GrammarSymbolRange := 21;
  7963.     EntryTokenValue     : constant GrammarSymbolRange := 22;
  7964.     ExceptionTokenValue : constant GrammarSymbolRange := 23;
  7965.     ExitTokenValue      : constant GrammarSymbolRange := 24;
  7966.     ForTokenValue       : constant GrammarSymbolRange := 25;
  7967.     FunctionTokenValue  : constant GrammarSymbolRange := 26;
  7968.     GenericTokenValue   : constant GrammarSymbolRange := 27;
  7969.     GotoTokenValue      : constant GrammarSymbolRange := 28;
  7970.     IfTokenValue        : constant GrammarSymbolRange := 29;
  7971.     InTokenValue        : constant GrammarSymbolRange := 30;
  7972.     IsTokenValue        : constant GrammarSymbolRange := 31;
  7973.     LimitedTokenValue   : constant GrammarSymbolRange := 32;
  7974.     LoopTokenValue      : constant GrammarSymbolRange := 33;
  7975.     ModTokenValue       : constant GrammarSymbolRange := 34;
  7976.     NewTokenValue       : constant GrammarSymbolRange := 35;
  7977.     NotTokenValue       : constant GrammarSymbolRange := 36;
  7978.     NullTokenValue      : constant GrammarSymbolRange := 37;
  7979.     OfTokenValue        : constant GrammarSymbolRange := 38;
  7980.     OrTokenValue        : constant GrammarSymbolRange := 39;
  7981.     OthersTokenValue    : constant GrammarSymbolRange := 40;
  7982.     OutTokenValue       : constant GrammarSymbolRange := 41;
  7983.     PackageTokenValue   : constant GrammarSymbolRange := 42;
  7984.     PragmaTokenValue    : constant GrammarSymbolRange := 43;
  7985.     PrivateTokenValue   : constant GrammarSymbolRange := 44;
  7986.     ProcedureTokenValue : constant GrammarSymbolRange := 45;
  7987.     RaiseTokenValue     : constant GrammarSymbolRange := 46;
  7988.     RangeTokenValue     : constant GrammarSymbolRange := 47;
  7989.     RecordTokenValue    : constant GrammarSymbolRange := 48;
  7990.     RemTokenValue       : constant GrammarSymbolRange := 49;
  7991.     RenamesTokenValue   : constant GrammarSymbolRange := 50;
  7992.     ReturnTokenValue    : constant GrammarSymbolRange := 51;
  7993.     ReverseTokenValue   : constant GrammarSymbolRange := 52;
  7994.     SelectTokenValue    : constant GrammarSymbolRange := 53;
  7995.     SeparateTokenValue  : constant GrammarSymbolRange := 54;
  7996.     SubtypeTokenValue   : constant GrammarSymbolRange := 55;
  7997.     TaskTokenValue      : constant GrammarSymbolRange := 56;
  7998.     TerminateTokenValue : constant GrammarSymbolRange := 57;
  7999.     ThenTokenValue      : constant GrammarSymbolRange := 58;
  8000.     TypeTokenValue      : constant GrammarSymbolRange := 59;
  8001.     UseTokenValue       : constant GrammarSymbolRange := 60;
  8002.     WhenTokenValue      : constant GrammarSymbolRange := 61;
  8003.     WhileTokenValue     : constant GrammarSymbolRange := 62;
  8004.     WithTokenValue      : constant GrammarSymbolRange := 63;
  8005.     XorTokenValue       : constant GrammarSymbolRange := 64;
  8006.     
  8007.     ------------------------------------------------------------------
  8008.     -- Identifier and Literals
  8009.     ------------------------------------------------------------------
  8010.  
  8011.     IdentifierTokenValue : constant GrammarSymbolRange := 65;
  8012.     NumericTokenValue    : constant GrammarSymbolRange := 66;
  8013.     StringTokenValue     : constant GrammarSymbolRange := 67;
  8014.     CharacterTokenValue  : constant GrammarSymbolRange := 68;
  8015.  
  8016.     ------------------------------------------------------------------
  8017.     -- Single Delimiters
  8018.     ------------------------------------------------------------------
  8019.  
  8020.     Ampersand_TokenValue  : constant GrammarSymbolRange := 69;
  8021.     Apostrophe_TokenValue : constant GrammarSymbolRange := 70;
  8022.     LeftParen_TokenValue  : constant GrammarSymbolRange := 71;
  8023.     RightParen_TokenValue : constant GrammarSymbolRange := 72;
  8024.     Star_TokenValue       : constant GrammarSymbolRange := 73;
  8025.     Plus_TokenValue       : constant GrammarSymbolRange := 74;
  8026.     Comma_TokenValue      : constant GrammarSymbolRange := 75;
  8027.     Minus_TokenValue      : constant GrammarSymbolRange := 76;
  8028.     Dot_TokenValue        : constant GrammarSymbolRange := 77;
  8029.     Slash_TokenValue      : constant GrammarSymbolRange := 78;
  8030.     Colon_TokenValue      : constant GrammarSymbolRange := 79;
  8031.     SemiColon_TokenValue  : constant GrammarSymbolRange := 80;
  8032.     LT_TokenValue         : constant GrammarSymbolRange := 81;
  8033.     EQ_TokenValue         : constant GrammarSymbolRange := 82;
  8034.     GT_TokenValue         : constant GrammarSymbolRange := 83;
  8035.     Bar_TokenValue        : constant GrammarSymbolRange := 84;
  8036.     
  8037.  
  8038.     ------------------------------------------------------------------
  8039.     -- Double Delimiters
  8040.     ------------------------------------------------------------------
  8041.  
  8042.     EQGT_TokenValue     : constant GrammarSymbolRange := 85;
  8043.     DotDot_TokenValue   : constant GrammarSymbolRange := 86;
  8044.     StarStar_TokenValue : constant GrammarSymbolRange := 87;
  8045.     ColonEQ_TokenValue  : constant GrammarSymbolRange := 88;
  8046.     SlashEQ_TokenValue  : constant GrammarSymbolRange := 89;
  8047.     GTEQ_TokenValue     : constant GrammarSymbolRange := 90;
  8048.     LTEQ_TokenValue     : constant GrammarSymbolRange := 91;
  8049.     LTLT_TokenValue     : constant GrammarSymbolRange := 92;
  8050.     GTGT_TokenValue     : constant GrammarSymbolRange := 93;
  8051.     LTGT_TokenValue     : constant GrammarSymbolRange := 94;
  8052.     
  8053.     ------------------------------------------------------------------
  8054.     -- Comment Terminal
  8055.     ------------------------------------------------------------------
  8056.  
  8057.     Comment_TokenValue  : constant GrammarSymbolRange := 95;
  8058.  
  8059.     ------------------------------------------------------------------
  8060.     -- Special Terminals
  8061.     ------------------------------------------------------------------
  8062.  
  8063.     EOF_TokenValue      : constant GrammarSymbolRange := 96;
  8064.  
  8065.     ------------------------------------------------------------------
  8066.     -- Special Non-Terminals
  8067.     ------------------------------------------------------------------
  8068.  
  8069.     ACC_TokenValue      : constant GrammarSymbolRange := 97;
  8070.  
  8071.     ------------------------------------------------------------------
  8072.     -- Grammar Symbol Classes
  8073.     ------------------------------------------------------------------
  8074.  
  8075.     subtype TokenRange is GrammarSymbolRange range 1..EOF_TokenValue;
  8076.  
  8077.     subtype TokenRangeLessEOF is
  8078.         GrammarSymbolRange range 1..(EOF_TokenValue - 1);
  8079.  
  8080.     subtype NonTokenRange is
  8081.         GrammarSymbolRange range (EOF_TokenValue + 1)..GrammarSymbolCount;
  8082.     
  8083.     ActionCount : constant GC.ParserInteger :=
  8084.         GC.setActionCount ;
  8085.         --| Number of actions in the parse tables.
  8086.     -- NYU Reference Name: NUM_ACTIONS
  8087.         
  8088.     StateCountPlusOne : constant GC.ParserInteger :=
  8089.         GC.setStateCountPlusOne ;
  8090.         --| Number of states plus one in the parse tables.
  8091.     -- NYU Reference Name: NUM_STATES
  8092.     
  8093.     subtype StateRange is
  8094.         GC.ParserInteger range 1..(StateCountPlusOne - 1);
  8095.  
  8096.     subtype ActionRange is GC.ParserInteger range 0..ActionCount;
  8097.     
  8098.     LeftHandSideCount :
  8099.         constant GC.ParserInteger := GC.setLeftHandSideCount;
  8100.         --| Number of left hand sides in the Ada grammar rules.
  8101.  
  8102.     subtype LeftHandSideRange is
  8103.         GC.ParserInteger range 1..LeftHandSideCount;
  8104.  
  8105.     function Get_LeftHandSide(
  8106.         GrammarRule : LeftHandSideRange) return GrammarSymbolRange;
  8107.     pragma inline (Get_LeftHandSide) ;
  8108.  
  8109.     RightHandSideCount : constant GC.ParserInteger :=
  8110.         GC.setRightHandSideCount ;
  8111.     --| Number of right hand sides in the Ada grammar rules.
  8112.  
  8113.     subtype RightHandSideRange is
  8114.         GC.ParserInteger range 1..RightHandSideCount;
  8115.  
  8116.     function Get_RightHandSide(
  8117.         GrammarRule : RightHandSideRange) return GC.ParserInteger;
  8118.     pragma inline (Get_RightHandSide) ;
  8119.   
  8120.     ------------------------------------------------------------------
  8121.     -- Subprogram Bodies Global to Package ParseTables
  8122.     ------------------------------------------------------------------
  8123.  
  8124.     function GetAction(
  8125.         InStateValue  : in StateRange;
  8126.         InSymbolValue : in GrammarSymbolRange
  8127.         )  return ActionRange;
  8128.     
  8129.     function Get_Grammar_Symbol(    --| return the string representation
  8130.                     --| of the grammar symbol
  8131.     In_Index : in GrammarSymbolRange) return string;
  8132.     
  8133.     --| Effects
  8134.     --|
  8135.     --| This subprogram returns the string representation of the
  8136.     --| GrammarSymbolRange passed in.
  8137.     --|
  8138.     
  8139.     ------------------------------------------------------------------
  8140.     subtype FollowMapRange is NonTokenRange;
  8141.     
  8142.     type FollowSymbolArray is array(PositiveParserInteger range <>)
  8143.                     of GrammarSymbolRange;
  8144.     
  8145.     type FollowSymbolRecord is
  8146.     record
  8147.         follow_symbol_count : TokenRange;
  8148.         follow_symbol       : FollowSymbolArray (TokenRange);
  8149.     end record;
  8150.     ------------------------------------------------------------------
  8151.     
  8152.     function Get_Follow_Map(        --| return the array of follow symbols
  8153.                     --| of the grammar symbol passed in
  8154.     In_Index : in FollowMapRange) return FollowSymbolRecord;
  8155.     
  8156.  
  8157.     --| Effects
  8158.     --|
  8159.     --| This subprogram returns the array of follow symbols for the
  8160.     --| grammar symbol passed in.
  8161.     --|
  8162.     
  8163.     ------------------------------------------------------------------
  8164.     -- The following declarations are for Error Recovery.
  8165.     ------------------------------------------------------------------
  8166.     ------------------------------------------------------------------
  8167.     -- Action_Token_Map
  8168.     ------------------------------------------------------------------
  8169.     
  8170.     subtype Action_Token_Range is
  8171.         GC.ParserInteger range 1..Max_Action_Token_Count;
  8172.     
  8173.     subtype Action_Token_Range_Plus_Zero is
  8174.         GC.ParserInteger range 0..Max_Action_Token_Count;
  8175.     --| for the set_size (which could be null!)
  8176.     
  8177.     type Action_Token_Array is array (PositiveParserInteger range <>)
  8178.     of TokenRangeLessEOF;
  8179.     
  8180.     type Action_Token_Record is
  8181.     record
  8182.         set_size : Action_Token_Range_Plus_Zero;
  8183.         set      : Action_Token_Array (Action_Token_Range);
  8184.     end record;
  8185.     
  8186.     ------------------------------------------------------------------
  8187.     -- Shift_State_Map
  8188.     ------------------------------------------------------------------
  8189.     
  8190.     subtype Shift_State_Range is
  8191.         GC.ParserInteger range 1..Max_Shift_State_Count;
  8192.     
  8193.     subtype Shift_State_Range_Plus_Zero is
  8194.         GC.ParserInteger range 0..Max_Shift_State_Count;
  8195.     --| for the set_size (which could be null!)
  8196.     
  8197.     type Shift_State_Array is array (PositiveParserInteger range <>)
  8198.     of StateRange;
  8199.     
  8200.     type Shift_State_Record is
  8201.     record
  8202.         set_size : Shift_State_Range_Plus_Zero;
  8203.         set      : Shift_State_Array (Shift_State_Range);
  8204.     end record;
  8205.     
  8206.     ------------------------------------------------------------------
  8207.  
  8208.     function Get_Action_Token_Map(  --| return the array of action tokens
  8209.                     --| for the state passed in.
  8210.     In_Index : in StateRange
  8211.                     --| the state to return action tokens
  8212.                     --| for.
  8213.     ) return Action_Token_Record;
  8214.  
  8215.     ------------------------------------------------------------------
  8216.     
  8217.     function Get_Shift_State_Map(   --| return the array of shift states
  8218.                     --| for the grammar symbol passed in.
  8219.     In_Index : in GrammarSymbolRange
  8220.                     --| grammar symbol to return shifts
  8221.                     --| for.
  8222.     ) return Shift_State_Record;
  8223.     
  8224.     -- The following variables contain statistics information
  8225.     -- collected during the parse:
  8226.     ParserDecisionCount : Natural := 0 ; --| Total number of times that
  8227.                                          --| GetAction was called.
  8228.     MaxCollisions       : Natural := 0 ; --| Of all the calls to GetAction
  8229.       --| The one which resulted in the greatest number of collisions
  8230.     TotalCollisions     : Natural := 0 ;
  8231.       --| Total number of collisions which occurred during parsing.
  8232.  
  8233. end ParseTables;
  8234.  
  8235.  
  8236. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8237. --LEXIDVAL.SPC
  8238. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8239.  
  8240. ----------------------------------------------------------------------
  8241.  
  8242. with ParseTables;               -- tables from parser generator
  8243.  
  8244. package Lex_Identifier_Token_Value is
  8245.     --| Classify identifiers and reserved words and determine which
  8246.     --| identifiers are in package STANDARD.
  8247.  
  8248.     ------------------------------------------------------------------
  8249.     -- Subprogram Bodies Global to
  8250.     -- Package Lex_Identifier_Token_Value
  8251.     ------------------------------------------------------------------
  8252.  
  8253.     procedure Find(
  8254.     --| returns token value and whether identifier is in package STANDARD.
  8255.  
  8256.         In_Identifier   : in string;   --| text of identifier to identify
  8257.  
  8258.         Out_Token_Value : out ParseTables.TokenRange);
  8259.         --| TokenValue of this identifier
  8260.  
  8261.     --| Effects
  8262.     --|
  8263.     --| This subprogram determines if the identifier is
  8264.     --| a reserved word or a plain identifier.
  8265.     --|
  8266.     --| The answer is indicated by returning the appropriate TokenValue.
  8267.     --|
  8268.  
  8269.     ------------------------------------------------------------------
  8270.  
  8271. end Lex_Identifier_Token_Value;
  8272.  
  8273. ----------------------------------------------------------------------
  8274.  
  8275. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8276. --LEXIDVAL.BDY
  8277. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8278.  
  8279.  
  8280. ----------------------------------------------------------------------
  8281.  
  8282. with Grammar_Constants;           -- constants from the parser generator
  8283. use Grammar_Constants;
  8284.     --| to gain visibility on ParserInteger's operations
  8285.  
  8286. package body Lex_Identifier_Token_Value is
  8287.  
  8288. --| Overview
  8289. --|
  8290. --| This perfect hash algorithm taken from
  8291. --|  "A Perfect Hash Function for Ada Reserved Words"
  8292. --|  by David Wolverton, published in Ada Letters Jul-Aug 1984
  8293. --|
  8294.     use ParseTables;
  8295.     package PT renames ParseTables;
  8296.  
  8297.     ------------------------------------------------------------------
  8298.     -- Declarations Local to Package Lex_Identifier_Token_Value
  8299.     ------------------------------------------------------------------
  8300.  
  8301.     subtype HashRange is integer ;
  8302.     subtype HashIdentifierSubrange is HashRange range 0..70 ;
  8303.  
  8304.     type XlateArray is array(character) of HashRange ;
  8305.     Xlate : constant XlateArray := XlateArray'(
  8306.         'A' => 0,    'B' => 49,   'C' => 0,   'D' => -7,   'E' => -20,
  8307.         'F' => 18,   'G' => -2,   'H' =>-38,  'I' => 33,   'J' =>  0,
  8308.         'K' => -9,   'L' =>  9,   'M' => 29,   'N' => -9,   'O' =>  6,
  8309.         'P' => 26,   'Q' =>  0,   'R' =>  8,   'S' =>  1,   'T' =>  1,
  8310.         'U' => -9,   'V' =>  0,   'W' => 56,   'X' =>-28,   'Y' => 11,
  8311.         'Z' =>  0, others => 0) ;
  8312.  
  8313.     type HashTableArray is array( HashIdentifierSubrange)
  8314.         of ParseTables.TokenRange ;
  8315.     --| Mapping from hash value into the token values.
  8316.  
  8317.     HashTable : constant HashTableArray := HashTableArray'(
  8318.         40 => 2,   -- ABORT
  8319.         6 => 3,    -- ABS
  8320.         37 => 4,   -- ACCEPT
  8321.         43 => 5,   -- ACCESS
  8322.         34 => 6,   -- ALL
  8323.         22 => 7,   -- AND
  8324.         16 => 8,   -- ARRAY
  8325.         3 => 9,    -- AT
  8326.         61 => 10,  -- BEGIN
  8327.         70 => 11,  -- BODY
  8328.         20 => 12,  -- CASE
  8329.         35 => 13,  -- CONSTANT
  8330.         14 => 14,  -- DECLARE
  8331.         9 => 15,   -- DELAY
  8332.         36 => 16,  -- DELTA
  8333.         38 => 17,  -- DIGITS
  8334.         7 => 18,   -- DO
  8335.         0 => 19,   -- ELSE
  8336.         19 => 20,  -- ELSIF
  8337.         2 => 21,   -- END
  8338.         30 => 22,  -- ENTRY
  8339.         8 => 23,   -- EXCEPTION
  8340.         1 => 24,   -- EXIT
  8341.         57 => 25,  -- FOR
  8342.         45 => 26,  -- FUNCTION
  8343.         21 => 27,  -- GENERIC
  8344.         46 => 28,  -- GOTO
  8345.         69 => 29,  -- IF
  8346.         42 => 30,  -- IN
  8347.         52 => 31,  -- IS
  8348.         17 => 32,  -- LIMITED
  8349.         67 => 33,  -- LOOP
  8350.         53 => 34,  -- MOD
  8351.         58 => 35,  -- NEW
  8352.         23 => 36,  -- NOT
  8353.         26 => 37,  -- NULL
  8354.         54 => 38,  -- OF
  8355.         44 => 39,  -- OR
  8356.         47 => 40,  -- OTHERS
  8357.         50 => 41,  -- OUT
  8358.         25 => 42,  -- PACKAGE
  8359.         56 => 43,  -- PRAGMA
  8360.         51 => 44,  -- PRIVATE
  8361.         49 => 45,  -- PROCEDURE
  8362.         29 => 46,  -- RAISE
  8363.         5 => 47,   -- RANGE
  8364.         41 => 48,  -- RECORD
  8365.         48 => 49,  -- REM
  8366.         24 => 50,  -- RENAMES
  8367.         39 => 51,  -- RETURN
  8368.         31 => 52,  -- REVERSE
  8369.         12 => 53,  -- SELECT
  8370.         27 => 54,  -- SEPARATE
  8371.         18 => 55,  -- SUBTYPE
  8372.         32 => 56,  -- TASK
  8373.         28 => 57,  -- TERMINATE
  8374.         4 => 58,   -- THEN
  8375.         15 => 59,  -- TYPE
  8376.         10 => 60,  -- USE
  8377.         59 => 61,  -- WHEN
  8378.         63 => 62,  -- WHILE
  8379.         60 => 63,  -- WITH
  8380.         11 => 64,  -- XOR
  8381.         others => PT.IdentifierTokenValue
  8382.     ) ;
  8383.  
  8384.     --| These are used to convert lower to upper case.
  8385.     convert : array(character) of character ;
  8386.     difference : constant := character'pos('a') - character'pos('A');
  8387.  
  8388.     ------------------------------------------------------------------
  8389.     -- Subprogram Specifications Local to
  8390.     -- Package Lex_Identifier_Token_Value
  8391.     ------------------------------------------------------------------
  8392.  
  8393.     function NormalizeToUpperCase ( --| normalize SYMREP to upper case
  8394.     In_String: in String) return String;
  8395.  
  8396.     ------------------------------------------------------------------
  8397.     -- Subprogram Bodies Global to Package Lex_Identifier_Token_Value
  8398.     ------------------------------------------------------------------
  8399.  
  8400.     procedure Find(
  8401.         In_Identifier   : in string;
  8402.         Out_Token_Value : out ParseTables.TokenRange) is
  8403.  
  8404.         subtype id_string is string(In_Identifier'Range);
  8405.  
  8406.         In_Identifier_Normalized : id_string;
  8407.  
  8408.         Length : HashRange := In_Identifier_Normalized'length ;
  8409.         --| Length of string
  8410.  
  8411.         First : HashRange := In_Identifier_Normalized'first ;
  8412.         --| Lower bound
  8413.  
  8414.         FirstChar, LastChar : character ;
  8415.         --| First and last characters
  8416.  
  8417.         SecondToLastChar : character ;
  8418.         --| Second to last character
  8419.  
  8420.         SecondToLast : HashRange;
  8421.         --| Alphabetic position of 2nd to last char.
  8422.  
  8423.         HashValue : HashRange ;
  8424.         --| Perfect hash value.
  8425.  
  8426.         TokenValue : ParseTables.GrammarSymbolRange ;
  8427.  
  8428.     begin
  8429.         In_Identifier_Normalized := NormalizeToUpperCase(In_Identifier);
  8430.  
  8431.         -- Assume In_Identifier is a plain identifier.
  8432.         Out_Token_Value   := PT.IdentifierTokenValue;
  8433.  
  8434.         if (Length <= 1) or else (Length >= 10) then
  8435.             -- Couldn't be a reserved word.
  8436.             return;
  8437.         else
  8438.             FirstChar := In_Identifier_Normalized(First) ;
  8439.             LastChar := In_Identifier_Normalized( (First+Length) -1 ) ;
  8440.             SecondToLastChar := In_Identifier_Normalized(
  8441.                 (First+Length) -2 ) ;
  8442.             SecondToLast := character'pos(SecondToLastChar)
  8443.                 - character'pos('A') ;
  8444.             HashValue := XLate(FirstChar) + XLate(LastChar) +
  8445.                 2*SecondToLast + Length ;
  8446.         end if;
  8447.  
  8448.         if HashValue in HashIdentifierSubrange then
  8449.             -- index and see if it matches a reserved word value.
  8450.             -- if so, then compare the string to the reserved word text.
  8451.             TokenValue := ParseTables.GrammarSymbolRange(
  8452.         HashTable(HashValue)) ; -- conversion
  8453.             if TokenValue /= PT.IdentifierTokenValue then
  8454.                 if (In_Identifier_Normalized =
  8455.             PT.Get_Grammar_Symbol(TokenValue) ) then
  8456.                     Out_Token_Value := PT.TokenRange(TokenValue) ;
  8457.                                      -- conversion
  8458.                 end if;
  8459.             end if;
  8460.         end if;
  8461.     end Find;
  8462.  
  8463.     ------------------------------------------------------------------
  8464.     -- Subprogram Bodies Local to
  8465.     -- Package Lex_Identifier_Token_Value
  8466.     ------------------------------------------------------------------
  8467.  
  8468.     function NormalizeToUpperCase(  --| normalize SYMREP to upper case
  8469.     In_String: in String) return String is
  8470.  
  8471.         OutString : string (In_String'range);
  8472.  
  8473.     begin
  8474.         for i in In_String'range loop
  8475.             OutString(i) := convert(In_String(i));
  8476.         end loop;
  8477.         return OutString;
  8478.     end NormalizeToUpperCase;
  8479.  
  8480.     ------------------------------------------------------------------
  8481.  
  8482.     begin
  8483.  
  8484.     --| Initialize the conversion array for lower to upper case conversion
  8485.     for i in character loop
  8486.         case i is
  8487.             when 'a' .. 'z' =>
  8488.         convert(i) := character'val(character'pos(i)
  8489.                     - difference);
  8490.             when others =>
  8491.         convert(i) := i;
  8492.         end case;
  8493.     end loop;
  8494.  
  8495.     ------------------------------------------------------------------
  8496.  
  8497. end Lex_Identifier_Token_Value;
  8498.  
  8499. ----------------------------------------------------------------------
  8500.  
  8501. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8502. --PDECLS.SPC
  8503. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8504.  
  8505. -----------------------------------------------------------------------
  8506.  
  8507. with Host_Dependencies;    -- host dependent constants
  8508. with ParseTables;          -- constants and state tables
  8509. use ParseTables;
  8510.  
  8511. with Grammar_Constants;
  8512. use Grammar_Constants;
  8513.  
  8514. package ParserDeclarations is   --| Objects used by the Parser
  8515.  
  8516. --| Notes
  8517.  
  8518. --| Abbreviations used in this compilation unit:
  8519. --|
  8520. --| gram : grammar
  8521. --| sym  : symbol
  8522. --| val  : value
  8523. --|
  8524.  
  8525.     package HD renames Host_Dependencies;
  8526.     package PT renames ParseTables;
  8527.     package GC renames Grammar_Constants;
  8528.  
  8529.                         -- Exceptions --
  8530.  
  8531.     MemoryOverflow : exception;  --| raised if Parser runs out of
  8532.                                  --| newable memory.
  8533.     Parser_Error   : exception;  --| raised if an error occurs during
  8534.                                  --| parsing.
  8535.  
  8536.     --| The double delimiters were named with a combination of the name of
  8537.     --| each component symbol.
  8538.  
  8539.     Arrow_TokenValue          : GrammarSymbolRange
  8540.         renames EQGT_TokenValue;
  8541.     Exponentiation_TokenValue : GrammarSymbolRange
  8542.         renames StarStar_TokenValue;
  8543.     Assignment_TokenValue     : GrammarSymbolRange
  8544.         renames ColonEQ_TokenValue;
  8545.     NotEquals_TokenValue      : GrammarSymbolRange
  8546.         renames SlashEQ_TokenValue;
  8547.     StartLabel_TokenValue     : GrammarSymbolRange
  8548.         renames LTLT_TokenValue;
  8549.     EndLabel_TokenValue       : GrammarSymbolRange
  8550.         renames GTGT_TokenValue;
  8551.     Box_TokenValue            : GrammarSymbolRange
  8552.         renames LTGT_TokenValue;
  8553.  
  8554.     ------------------------------------------------------------------
  8555.     -- Grammar Symbol Classes
  8556.     ------------------------------------------------------------------
  8557.  
  8558.     subtype ReservedWordRange is GrammarSymbolRange
  8559.     range AbortTokenValue .. XorTokenValue;
  8560.  
  8561.     subtype SingleDelimiterRange is GrammarSymbolRange
  8562.     range Ampersand_TokenValue .. Bar_TokenValue;
  8563.  
  8564.     subtype DoubleDelimiterRange is GrammarSymbolRange
  8565.     range Arrow_TokenValue .. Box_TokenValue;
  8566.  
  8567.     ------------------------------------------------------------------
  8568.     -- ParseTables.GetAction return values
  8569.     ------------------------------------------------------------------
  8570.  
  8571.     subtype Error_Action_Range is    --| ActionRange that indicates
  8572.         ActionRange range 0..0;      --| the error range
  8573.  
  8574.     subtype Shift_Action_Range is    --| ActionRange that indicates
  8575.                                      --| a shift action.
  8576.         ActionRange range 1..(StateCountPlusOne - 1);
  8577.  
  8578.     subtype Accept_Action_Range is   --| ActionRange that indicates
  8579.                                      --| the accept action.
  8580.         ActionRange range StateCountPlusOne..StateCountPlusOne;
  8581.  
  8582.     subtype Reduce_Action_Range is   --| ActionRange that indicates
  8583.                                      --| a reduce action.
  8584.         ActionRange range (StateCountPlusOne + 1)..ActionCount;
  8585.  
  8586.     ------------------------------------------------------------------
  8587.     -- Queue and Stack Management
  8588.     ------------------------------------------------------------------
  8589.  
  8590.     subtype StateParseStacksIndex is --| range of index values for
  8591.         GC.ParserInteger range 0..200;  --| StateStack and ParseStack
  8592.  
  8593.     subtype StateParseStacksRange is --| array index values for
  8594.                                      --| StateStack and ParseStack
  8595.         StateParseStacksIndex range 1..StateParseStacksIndex'Last;
  8596.  
  8597.     Look_Ahead_Limit : positive := 5;--| Look ahead limit for parser
  8598.  
  8599.     ------------------------------------------------------------------
  8600.     -- StateStack Element
  8601.     ------------------------------------------------------------------
  8602.  
  8603.     subtype StateStackElement is StateRange;
  8604.  
  8605.     type Source_Text is access String;
  8606.  
  8607.     Null_Source_Text : constant Source_Text
  8608.         := null;
  8609.  
  8610.     ------------------------------------------------------------------
  8611.     -- ParseStack and Grammar Symbol Elements
  8612.     ------------------------------------------------------------------
  8613.  
  8614.     type Token is
  8615.         record
  8616.         text            : Source_Text;
  8617.         srcpos_line     : HD.Source_Line;
  8618.         srcpos_column   : HD.Source_Column;
  8619.         end record;
  8620.  
  8621.     type ParseStackElement is
  8622.         record
  8623.         gram_sym_val  : GrammarSymbolRange;
  8624.         --| used by parser to identify kind of grammar symbol
  8625.         lexed_token : Token;
  8626.         --| lexed tokens not yet reduced (eliminated)
  8627.         --| by ReduceActions.
  8628.         end record;
  8629.  
  8630.     ------------------------------------------------------------------
  8631.  
  8632.     CurToken : ParseStackElement;
  8633.         --| return from Lex.GetNextSourceToken
  8634.         --| Token used in subprogram Parse to determine
  8635.         --| next action from.
  8636.         --| Also used in ReduceActionsUtilities to determine last
  8637.         --| compilation unit in a compilation.
  8638.  
  8639.     ------------------------------------------------------------------
  8640.     -- Subprogram Bodies Global to Package ParserDeclarations
  8641.     ------------------------------------------------------------------
  8642.  
  8643.     function Get_Source_Text(       --| get a string from a Source_Text
  8644.                     --| object
  8645.         In_Source_Text :            --| the object to get the string from
  8646.             in Source_Text
  8647.     ) return string;
  8648.  
  8649.     --| Effects
  8650.  
  8651.     --| This subprogram gets a string from a Source_Text object.
  8652.     --| It exists to concentrate the interface to Source_Text objects.
  8653.  
  8654.     ------------------------------------------------------------------
  8655.  
  8656.     procedure Put_Source_Text(     --| put a string into a Source_Text
  8657.                    --| object
  8658.         In_String : in string;     --| the string to store
  8659.         In_Out_Source_Text :       --| the object to store the string in
  8660.             in out Source_Text);
  8661.  
  8662.  
  8663.     --| Effects
  8664.  
  8665.     --| This subprogram stores a string in a Source_Text object.
  8666.     --| It exists to concentrate the interface to Source_Text objects.
  8667.  
  8668.     ------------------------------------------------------------------
  8669.  
  8670.     function Dump_Parse_Stack_Element(  --| return the data in a
  8671.                                         --| ParseStackElement or
  8672.                                         --| TokenQueueElement as a string
  8673.         In_PSE : in ParseStackElement   --| the Element to display.
  8674.     ) return string;
  8675.  
  8676.     --| Effects
  8677.  
  8678.     --| This subprogram returns the data in a ParseStackElement or its
  8679.     --| sub-type a TokenQueueElement as a string.
  8680.  
  8681.     --| Notes
  8682.  
  8683.     --| Abbreviations used in this compilation unit
  8684.     --|
  8685.     --| PSE : ParseStackElement
  8686.     --|
  8687.     --| Only the lexed_token variant is currently fully displayed.
  8688.     --| The other variants would have to make use of an IDL
  8689.     --| writer.
  8690.  
  8691.     ------------------------------------------------------------------
  8692.  
  8693. end ParserDeclarations;
  8694.  
  8695. ----------------------------------------------------------------------
  8696.  
  8697. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8698. --PDECLS.BDY
  8699. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8700.  
  8701. ----------------------------------------------------------------------
  8702.  
  8703. package body ParserDeclarations is
  8704.  
  8705.     subtype Dump_String_Range_Plus_Zero is
  8706.         STANDARD.NATURAL range 0 .. 4000;
  8707.  
  8708.     Dump_String        : string (1..Dump_String_Range_Plus_Zero'Last);
  8709.  
  8710.     Dump_String_Length : Dump_String_Range_Plus_Zero;
  8711.     -- must be set to zero before each use.
  8712.  
  8713.     ------------------------------------------------------------------
  8714.     -- Subprograms Local to Package ParserDeclarations
  8715.     ------------------------------------------------------------------
  8716.  
  8717.     procedure Append_To_Dump_String (   --| Add In_String to Dump_String
  8718.         In_String : in string           --| String to append
  8719.     );
  8720.  
  8721.     --| Effects
  8722.  
  8723.     --| This subprogram appends In_String to the package Body global
  8724.     --| Dump_String.
  8725.  
  8726.     --| Modifies
  8727.     --|
  8728.     --| Dump_String
  8729.     --| Dump_String_Length
  8730.  
  8731.     ------------------------------------------------------------------
  8732.     -- Subprogram Bodies Global to Package ParserDeclarations
  8733.     -- (declared in package specification).
  8734.     ------------------------------------------------------------------
  8735.  
  8736.     function Get_Source_Text(
  8737.         In_Source_Text : in Source_Text
  8738.     ) return string is
  8739.  
  8740.     begin
  8741.  
  8742.         if (In_Source_Text = Null_Source_Text) then
  8743.             return "" ;
  8744.         else
  8745.             return In_Source_Text.all ;
  8746.         end if;
  8747.  
  8748.     end Get_Source_Text;
  8749.  
  8750.     ------------------------------------------------------------------
  8751.  
  8752.     procedure Put_Source_Text(
  8753.         In_String          : in     string ;
  8754.         In_Out_Source_Text : in out Source_Text
  8755.     ) is
  8756.  
  8757.     begin
  8758.  
  8759.         In_Out_Source_Text := new string'(In_String);
  8760.  
  8761.     end Put_Source_Text;
  8762.  
  8763.     ------------------------------------------------------------------
  8764.  
  8765.     function Dump_Parse_Stack_Element(
  8766.         In_PSE : in ParseStackElement
  8767.     ) return string is
  8768.  
  8769.     --| Notes
  8770.  
  8771.     --| Abbreviations used in this compilation unit
  8772.     --|
  8773.     --| PSE : ParseStackElement
  8774.     --|
  8775.  
  8776.     begin
  8777.  
  8778.         Dump_String_Length := 0;
  8779.  
  8780.         -- Output data common to all ParseStackElements
  8781.         Append_To_Dump_String
  8782.             ("Element Kind:  "
  8783.             & PT.Get_Grammar_Symbol(In_PSE.gram_sym_val)
  8784.             & " "       -- give extra space to help highlight delimiters
  8785.             );
  8786.  
  8787.         -- Output data common to all lexed_tokens
  8788.         Append_To_Dump_String
  8789.             (" Token - Line: "
  8790.             & HD.Source_Line'IMAGE  (In_PSE.lexed_token.srcpos_line)
  8791.             &       " Column: "
  8792.             & HD.Source_Column'IMAGE(In_PSE.lexed_token.srcpos_column)
  8793.             );
  8794.  
  8795.         Append_To_Dump_String
  8796.             ( " Text: %"
  8797.             & Get_Source_Text(In_PSE.lexed_token.text)
  8798.         & "%"
  8799.             );
  8800.  
  8801.  
  8802.         -- Finally, finish up the message
  8803.         Append_To_Dump_String("");
  8804.  
  8805.         return Dump_String(1..Dump_String_Length);
  8806.  
  8807.     end Dump_Parse_Stack_Element;
  8808.  
  8809.     ------------------------------------------------------------------
  8810.     -- Subprogram Bodies Local to Package ParserDeclarations
  8811.     ------------------------------------------------------------------
  8812.  
  8813.     procedure Append_To_Dump_String(
  8814.         In_String : in string       --| String to append
  8815.     ) is
  8816.  
  8817.     begin
  8818.  
  8819.         Dump_String((Dump_String_Length + 1) ..
  8820.             (Dump_String_Length + In_String'Last)) := In_String;
  8821.  
  8822.         Dump_String_Length := Dump_String_Length + In_String'Length;
  8823.  
  8824.     end Append_To_Dump_String;
  8825.  
  8826.     ------------------------------------------------------------------
  8827.  
  8828. end ParserDeclarations;
  8829.  
  8830. ----------------------------------------------------------------------
  8831.  
  8832. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8833. --LEX.SPC
  8834. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8835.  
  8836. ----------------------------------------------------------------------
  8837.  
  8838. with ParserDeclarations;        -- declarations for the Parser
  8839. with Host_Dependencies;         -- Host dependents constants
  8840.  
  8841. package Lex is                  --| perform lexical analysis
  8842.  
  8843. --| Overview
  8844. --|
  8845. --| This package is used to identify tokens in the source file and
  8846. --| return them to subprogram Parser.
  8847. --|
  8848. --| The useful reference is Chapter 2 of the Ada (Trade Mark) LRM.
  8849.  
  8850. --| Effects
  8851. --|
  8852. --| The subprograms in package Lex are used to sequentially read
  8853. --| a source file and identify lexical units (tokens) in the file.
  8854. --| Comments and error messages are saved for use by the lister.
  8855.  
  8856.     package HD renames Host_Dependencies;
  8857.     package PD renames ParserDeclarations;
  8858.     -- other package renames are in the package body
  8859.  
  8860.     ------------------------------------------------------------------
  8861.     -- Subprogram Declarations Global to Package Lex
  8862.     ------------------------------------------------------------------
  8863.  
  8864.     procedure Initialization;     --| Initializes the lexer
  8865.  
  8866.     --| Effects
  8867.     --|
  8868.     --| This subprogram initializes the lexer.
  8869.  
  8870.     ------------------------------------------------------------------
  8871.  
  8872.    function GetNextNonCommentToken  --| returns next non-comment token
  8873.                                     --| in source file.
  8874.        return PD.ParseStackElement;
  8875.  
  8876.     --| Effects
  8877.     --|
  8878.     --| This subprogram scans the source file for the next token not
  8879.     --| including comment tokens.
  8880.  
  8881.     --| Requires
  8882.     --|
  8883.     --| This subprogram requires an opened source file,
  8884.     --| and the state information internal to the package body.
  8885.  
  8886.     ------------------------------------------------------------------
  8887.  
  8888.     function GetNextSourceToken  --| returns next token in source file.
  8889.         return PD.ParseStackElement;
  8890.  
  8891.     --| Effects
  8892.     --|
  8893.     --| This subprogram scans the source file for the next token.
  8894.     --| The tokens returned include any comment literal tokens.
  8895.  
  8896.     --| Requires
  8897.     --|
  8898.     --| This subprogram requires an opened source file,
  8899.     --| and the state information internal to the package body.
  8900.  
  8901.     ------------------------------------------------------------------
  8902.  
  8903.     function Show_Current_Line
  8904.     return HD.Source_Line;
  8905.  
  8906.     --| Effects
  8907.     --|
  8908.     --| Returns the current line number being processed
  8909.  
  8910.     ------------------------------------------------------------------
  8911.  
  8912.     procedure Write_Line;
  8913.  
  8914.     --| Effects
  8915.     --|
  8916.     --| Write a line to an appropriate file 
  8917.  
  8918.     ------------------------------------------------------------------
  8919.  
  8920. end Lex;
  8921.  
  8922. ----------------------------------------------------------------------
  8923.  
  8924. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8925. --PARSESTK.SPC
  8926. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8927. -- $Source: /nosc/work/parser/RCS/ParseStk.spc,v $
  8928. -- $Revision: 4.0 $ -- $Date: 85/02/19 11:33:03 $ -- $Author: carol $
  8929.  
  8930. ----------------------------------------------------------------------
  8931.  
  8932. with ParserDeclarations;        -- declarations for the Parser
  8933. use ParserDeclarations;
  8934.  
  8935. package ParseStack is           --| Elements awaiting parsing
  8936.  
  8937. --| Overview
  8938. --|
  8939. --| The ParseStack used by the parser.
  8940. --|
  8941. --| This data structure has the following sets of operations:
  8942. --|
  8943. --| 1) A set that add and delete elements.  This set can
  8944. --| raise the exceptions: UnderFlow and OverFlow.
  8945. --| The set includes:
  8946. --|
  8947. --|     Pop
  8948. --|     Push
  8949. --|     Reduce
  8950. --|
  8951. --| 2) A function that returns the number of elements in the
  8952. --| data structure. This set raises no exceptions.
  8953. --| The set includes:
  8954. --|
  8955. --|     Length
  8956.  
  8957. --|
  8958. --| Notes
  8959. --|
  8960. --|     Under some implementations the exception
  8961. --| ParserDeclarations.MemoryOverflow could be raised.
  8962. --|
  8963.  
  8964.     package PD renames ParserDeclarations;
  8965.  
  8966.     ------------------------------------------------------------------
  8967.     -- Declarations Global to Package ParseStack
  8968.     ------------------------------------------------------------------
  8969.  
  8970.     OverFlow  : exception;
  8971.         --| raised if no more space in stack.
  8972.     UnderFlow : exception;
  8973.         --| raised if no more elements in stack.
  8974.  
  8975.     ------------------------------------------------------------------
  8976.  
  8977.     procedure Push(         --| Adds new top element to stack
  8978.         Element: in PD.ParseStackElement); --| element to add
  8979.  
  8980.     --| Raises
  8981.     --|
  8982.     --| OverFlow - no more space in stack.
  8983.  
  8984.     --| Effects
  8985.     --|
  8986.     --| This subprogram adds an element to the top of the stack.
  8987.     --|
  8988.     
  8989.     ------------------------------------------------------------------
  8990.     
  8991.     function Pop                 --| Removes top element in stack
  8992.         return PD.ParseStackElement;
  8993.  
  8994.     --| Raises
  8995.     --|
  8996.     --| UnderFlow - no more elements in stack.
  8997.  
  8998.     --| Effects
  8999.     --|
  9000.     --| This subprogram obtains the element at the top of the stack.
  9001.     --|
  9002.     
  9003.     ------------------------------------------------------------------
  9004.     
  9005.     function Length                 --| Returns the number of
  9006.                                     --| elements in the stack
  9007.         return PD.StateParseStacksIndex;
  9008.  
  9009.     --| Effects
  9010.     --|
  9011.     --| This subprogram returns the number of elements in the stack.
  9012.     --|
  9013.     
  9014.     ----------------------------------------------------------------------
  9015.     
  9016.     procedure Reduce(           --| Pops and discards top n elements on
  9017.                                 --| the stack.
  9018.         TopN : in PD.StateParseStacksIndex);
  9019.         --| Number of elements to pop.
  9020.  
  9021.     --| Raises
  9022.     --|
  9023.     --| Underflow - no more elements in stack.
  9024.  
  9025.     --| Effects
  9026.     --|
  9027.     --| Pops and discards top N elements on the stack.
  9028.     --| If TopN is greater than the number of elements in the stack,
  9029.     --| Underflow is raised.
  9030.     --| This subprogram is used by the parser to reduce the stack during
  9031.     --| a reduce action.
  9032.     --| This stack reduction could be done with a for loop and
  9033.     --| the Pop subprogram at a considerable cost in execution time.
  9034.     --|
  9035.     
  9036.     ----------------------------------------------------------------------
  9037.     
  9038. end ParseStack;
  9039.     
  9040. ----------------------------------------------------------------------
  9041. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9042. --STATESTK.SPC
  9043. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9044. -- $Source: /nosc/work/parser/RCS/StateStk.spc,v $
  9045. -- $Revision: 4.0 $ -- $Date: 85/02/19 11:43:44 $ -- $Author: carol $
  9046.  
  9047. ----------------------------------------------------------------------
  9048.  
  9049. with ParserDeclarations;  -- declarations for the Parser
  9050. use ParserDeclarations;
  9051.  
  9052. package StateStack is     --| Elements awaiting parsing
  9053.  
  9054. --| Overview
  9055. --|
  9056. --| The StateStack used by the parser.
  9057. --|
  9058. --| This data structure has the following sets of operations:
  9059. --|
  9060. --| 1) A set that add and delete elements.
  9061. --| This set can raise the exceptions Underflow and Overflow.
  9062. --| The set includes:
  9063. --|
  9064. --|     Pop
  9065. --|     Push
  9066. --|     Reduce
  9067. --|
  9068. --| 2) A function that returns the number of elements in the
  9069. --| data structure.
  9070. --| This set raises no exceptions.
  9071. --| The set includes:
  9072. --|
  9073. --|     Length
  9074. --|
  9075. --| 3) A copy operations, to return the top of the stack.
  9076. --| The exception, UnderFlow,
  9077. --| is utilized to indicate the end of a sequential examination.
  9078. --| The set includes:
  9079. --|
  9080. --|     CopyTop
  9081. --|     InitCopy
  9082. --|     CopyNext
  9083.  
  9084. --| Notes
  9085. --|
  9086. --|     Under some implementations the exception
  9087. --| ParserDeclarations.MemoryOverflow could be raised.
  9088. --|
  9089.  
  9090.     ------------------------------------------------------------------
  9091.     -- Declarations Global to Package StateStack
  9092.     ------------------------------------------------------------------
  9093.  
  9094.     OverFlow  : exception;
  9095.     --| raised if no more space in stack.
  9096.     UnderFlow : exception;
  9097.     --| raised if no more elements in stack.
  9098.  
  9099.     ------------------------------------------------------------------
  9100.  
  9101.     procedure Push(                     --| Adds new top element to stack
  9102.         Element: in StateStackElement); --| element to add
  9103.  
  9104.     --|
  9105.     --| Raises
  9106.     --|
  9107.     --| OverFlow - no more space in stack.
  9108.  
  9109.     --| Effects
  9110.     --|
  9111.     --| This subprogram adds an element to the top of the stack.
  9112.     --|
  9113.  
  9114.     ------------------------------------------------------------------
  9115.  
  9116.     function Pop return StateStackElement;--| Removes top element in stack
  9117.  
  9118.     --| Raises
  9119.     --|
  9120.     --| UnderFlow - no more elements in stack.
  9121.  
  9122.     --| Effects
  9123.     --|
  9124.     --| This subprogram pops the element at the top of the stack.
  9125.     --|
  9126.  
  9127.     ------------------------------------------------------------------
  9128.  
  9129.     function CopyTop return StateStackElement;
  9130.     --| Copy top element in stack
  9131.  
  9132.     --| Raises
  9133.     --|
  9134.     --| UnderFlow - no more elements in stack.
  9135.     --|
  9136.  
  9137.     --| Effects
  9138.     --|
  9139.     --| Returns the top of the stack.
  9140.  
  9141.     ------------------------------------------------------------------
  9142.  
  9143.     function CopyNext return StateStackElement;
  9144.     --| Copy element after previous one copied
  9145.  
  9146.     --| Raises
  9147.     --|
  9148.     --| UnderFlow - no more elements in stack.
  9149.  
  9150.     --| Effects
  9151.     --|
  9152.     --| This subprogram is used in conjunction with
  9153.     --| CopyTop or Init Copy to sequentially examine the stack.
  9154.     --|
  9155.  
  9156.     ------------------------------------------------------------------
  9157.  
  9158.     function Length return StateParseStacksIndex;
  9159.    --| Returns the number of elements in the stack
  9160.  
  9161.     --| Effects
  9162.     --|
  9163.     --| This subprogram returns the number of elements in the stack.
  9164.     --|
  9165.  
  9166.     ------------------------------------------------------------------
  9167.  
  9168.     procedure InitCopy;           --| Initialize sequential examination of
  9169.                                   --| the data structure
  9170.  
  9171.     --| Effects
  9172.     --|
  9173.     --| Initializes the copy function,
  9174.     --| so that subsequent calls to CopyNext will sequentially examine
  9175.     --| the elements in the data structure.
  9176.     --|
  9177.  
  9178.     ------------------------------------------------------------------
  9179.  
  9180.     function CopyThisOne (  --| returns element given by parm 'which_one'
  9181.     which_one:  StateParseStacksRange) return StateStackElement;
  9182.  
  9183.     --| Overview
  9184.     --|
  9185.     --| Returns the state stack element indicated by the parameter
  9186.     --| 'which_one'.  This operation is needed by LocalStateStack
  9187.     --| because, in essence, the state stack is being copied in two
  9188.     --| nested loops and the Next_To_Copy counter can therefore only
  9189.     --| be used for one of the series of copies.
  9190.  
  9191.     ------------------------------------------------------------------
  9192.  
  9193.     procedure Reduce(           --| Pops and discards top n elements on
  9194.                                 --| the stack.
  9195.     TopN : StateParseStacksIndex);    --| Number of elements to pop.
  9196.  
  9197.     --| Raises:
  9198.     --|
  9199.     --| Underflow - no more elements in stack.
  9200.  
  9201.     --| Effects
  9202.     --|
  9203.     --| Pops and discards TopN elements on the stack.
  9204.     --| If TopN is greater than the number of elements in the stack,
  9205.     --| Underflow is raised.
  9206.     --| This subprogram is used by the parser to reduce the stack during
  9207.     --| a reduce action.
  9208.     --| This stack reduction could be done with a for
  9209.     --| loop and the Pop subprogram at a considerable cost in execution
  9210.     --| time.
  9211.     --|
  9212.  
  9213.     ------------------------------------------------------------------
  9214.  
  9215. end StateStack;
  9216.  
  9217. ----------------------------------------------------------------------
  9218. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9219. --PARSE.SPC
  9220. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9221. -- $Source: /nosc/work/parser/RCS/Parse.spc,v $
  9222. -- $Revision: 4.0 $ -- $Date: 85/02/19 11:48:41 $ -- $Author: carol $
  9223.  
  9224. ----------------------------------------------------------------------
  9225.  
  9226. with ParserDeclarations;        -- declarations for the Parser
  9227. use ParserDeclarations;
  9228.  
  9229. package Parser is
  9230.  
  9231.     --| Notes
  9232.     --| 
  9233.     --| WARNING:
  9234.     --| 
  9235.     --| Some of the code for this package is in the grammar source that is
  9236.     --| input to the parse table generator. One of the ouputs of the
  9237.     --| parse table generator is the source for the body of the procedure
  9238.     --| Apply_Actions used in this package. This procedure provides case
  9239.     --| statements to select the number of the rule to be used.
  9240.     --| This procedure is declared as separate subunits in the
  9241.     --| body of this package. It is strongly recommended that
  9242.     --| the code of these functions be kept integrated with the grammar
  9243.     --| for the following reasons.
  9244.     --|
  9245.     --| 1) to keep the case select numbers consistent with the reduce
  9246.     --| action numbers in the parse tables.
  9247.     --| 
  9248.     --| 2) to associate each grammar rule with the code for its actions.
  9249.     --| 
  9250.  
  9251.     package PD renames ParserDeclarations;
  9252.  
  9253.     ------------------------------------------------------------------
  9254.  
  9255.     procedure Apply_Actions(
  9256.         Rule_Number : in PT.LeftHandSideRange);
  9257.  
  9258.     ------------------------------------------------------------------
  9259.     
  9260.     function Parse                  --| NYU LALR style parser
  9261.         return PD.ParseStackElement;
  9262.     
  9263.     --| Raises
  9264.     --|
  9265.     --| ParserDeclarations.MemoryOverflow
  9266.     --|
  9267.     
  9268.     --| Effects
  9269.     --|
  9270.     --| This parser takes input from a Lexer and parses it according
  9271.     --| to a set of grammar rules that have been converted into a set of
  9272.     --| ParseTables by the NYU LALR Parser Generator.
  9273.     
  9274.     --| Requires
  9275.     --|
  9276.     --| The parser expects the Lexer and other units it uses to be
  9277.     --| initialized.
  9278.     --|
  9279.     --| The units that stay the same for different grammars are:
  9280.     --|
  9281.     --| Parser.Parse (this subprogram)
  9282.     --| ParseStack
  9283.     --|
  9284.     --| The units that need to be changed for different grammars are:
  9285.     --|
  9286.     --| Parser.Apply_Actions
  9287.     --| Lex
  9288.     --| ParserDeclarations
  9289.     --| ParseTables
  9290.     --|
  9291.     
  9292.     --| Modifies
  9293.     --|
  9294.     --| The following are modified:
  9295.     --|
  9296.     --| ParseStack
  9297.     --|
  9298.     
  9299.     ------------------------------------------------------------------
  9300.  
  9301. end Parser;
  9302.  
  9303. ----------------------------------------------------------------------
  9304. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9305. --PARSE.BDY
  9306. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9307. -- $Source: /nosc/work/parser/RCS/Parse.bdy,v $
  9308. -- $Revision: 4.0 $ -- $Date: 85/02/19 12:00:03 $ -- $Author: carol $
  9309.  
  9310. ----------------------------------------------------------------------
  9311.  
  9312. with Lex;                       -- the lexical analyzer
  9313. with ParseStack;                -- elements awaiting parsing
  9314. with StateStack;                -- stack of parse states
  9315. with ParseTables;               -- state tables generated by parser
  9316.                                 -- generator
  9317. use ParseTables;
  9318.  
  9319. with Grammar_Constants;         -- constants generated by parser generator
  9320. use Grammar_Constants;
  9321.  
  9322. package body Parser is
  9323.  
  9324.     ------------------------------------------------------------------
  9325.  
  9326.     procedure Apply_Actions(
  9327.         Rule_Number : in PT.LeftHandSideRange) is separate;
  9328.  
  9329.     ------------------------------------------------------------------
  9330.  
  9331.     function Parse return PD.ParseStackElement is
  9332.  
  9333.     --| Overview
  9334.     --|
  9335.     --| The appropriate reference is:
  9336.     --|
  9337.     --| Using the NYU LALR Parser Generator. Philippe Charles and
  9338.     --| Gerald Fisher. Courant Institute, New York University, 251 Mercer
  9339.     --| Street, New York, N.Y.  10012. Unpublished paper. 1981.
  9340.     --|
  9341.  
  9342.     --|
  9343.     --| Notes
  9344.     --|
  9345.     --| Abbreviations Used:
  9346.     --|
  9347.     --| Cur : Current - used as prefix
  9348.     --| LH  : LeftHand
  9349.     --| RH  : RightHand
  9350.     --|
  9351.  
  9352.     ------------------------------------------------------------------
  9353.     -- Reduce Action Work Variables
  9354.     ------------------------------------------------------------------
  9355.  
  9356.     Reduce_Action_Number   : PT.LeftHandSideRange;
  9357.         --| reduction to perform
  9358.  
  9359.     Reduce_Action_LH_Value : GrammarSymbolRange;
  9360.         --| grammar symbol number of left hand side of reduction
  9361.  
  9362.     Reduce_Action_RH_Size  : PD.StateParseStacksIndex;
  9363.         --| number of elements in right hand side of reduction
  9364.  
  9365.     ------------------------------------------------------------------
  9366.     -- Other Objects
  9367.     ------------------------------------------------------------------
  9368.  
  9369.     Current_Action      : ActionRange;
  9370.         --| return from PT.GetAction.
  9371.  
  9372.     Start_State         : constant := 1;
  9373.         --| Start state for parser.
  9374.  
  9375.     Last_Element_Popped : PD.ParseStackElement;
  9376.         --| Last element popped from parse stack
  9377.  
  9378.     ------------------------------------------------------------------
  9379.  
  9380.     begin
  9381.  
  9382.     --|
  9383.     --| Algorithm
  9384.     --|
  9385.     --| Function PT.GetAction returns an action value,
  9386.     --| which indicate one of four possible actions:
  9387.     --|
  9388.     --| Error:  action value = 0.
  9389.     --| Shift:  0 < action value < StateCountPlusOne.
  9390.     --| Accept: action value = StateCountPlusOne.
  9391.     --| Reduce: action value > StateCountPlusOne.
  9392.     --|
  9393.     --| The action is processed (as described below).
  9394.     --| This is repeated until no more tokens are obtained.
  9395.     --|
  9396.     --| The basic action processing is:
  9397.     --|
  9398.     --| SHIFT ACTION: the next token is placed on the ParseStack.
  9399.     --|
  9400.     --| REDUCE ACTION: the handle (a grammar rule's right hand side)
  9401.     --| found on the ParseStack is replaced with a
  9402.     --| non-terminal (grammar rule's left hand side) to which
  9403.     --| it has been reduced, and a new state.
  9404.     --|
  9405.     --| ACCEPT ACTION: the ParseStack contains the root
  9406.     --| of the parse tree, and processing is finished for
  9407.     --| If another compilation unit is present, parsing continues.
  9408.     --|
  9409.     --| ERROR ACTION: the exception Parser_Error is raised.
  9410.  
  9411.     ------------------------------------------------------------------
  9412.     
  9413.         -- Initialize Lexical Analyzer
  9414.         Lex.Initialization;
  9415.  
  9416.         PD.CurToken := Lex.GetNextNonCommentToken;
  9417.  
  9418.         StateStack.Push(Start_State);
  9419.  
  9420.         Do_Parse: loop
  9421.  
  9422.             Current_Action := PT.GetAction(
  9423.                 StateStack.CopyTop,
  9424.                 PD.CurToken.gram_sym_val);
  9425.  
  9426.             -- Accept action
  9427.             exit when (Current_Action in PD.Accept_Action_Range);
  9428.         
  9429.             if Current_Action in PD.Shift_Action_Range then
  9430.  
  9431.                 -- Shift token from CurToken to ParseStack.
  9432.                 ParseStack.Push(PD.CurToken);
  9433.  
  9434.                 -- Add new state to top of StateStack
  9435.                 StateStack.Push(Current_Action);
  9436.         
  9437.                 -- Get next token.
  9438.                 PD.CurToken := Lex.GetNextNonCommentToken;
  9439.         
  9440.             elsif Current_Action in PD.Reduce_Action_Range then
  9441.         
  9442.                 Reduce_Action_Number := Current_Action -
  9443.                     StateCountPlusOne;
  9444.  
  9445.                 Reduce_Action_LH_Value  :=
  9446.                     PT.Get_LeftHandSide(Reduce_Action_Number);
  9447.  
  9448.                 Reduce_Action_RH_Size :=
  9449.                     PT.Get_RightHandSide(Reduce_Action_Number);
  9450.  
  9451.                 -- Reduce Parse Stack
  9452.                 ParseStack.Reduce(Reduce_Action_RH_Size);
  9453.  
  9454.                 ParseStack.Push((
  9455.                     gram_sym_val => Reduce_Action_LH_Value,
  9456.                     lexed_token => (
  9457.                         text => PD.Null_Source_Text,
  9458.                         srcpos_line => 0,
  9459.                         srcpos_column => 0)));
  9460.  
  9461.                 -- Reduce State Stack
  9462.                 StateStack.Reduce(Reduce_Action_RH_Size);
  9463.  
  9464.                 StateStack.Push(PT.GetAction(
  9465.                     StateStack.CopyTop,
  9466.                     Reduce_Action_LH_Value));
  9467.  
  9468.                 Apply_Actions(Reduce_Action_Number);
  9469.  
  9470.                 else -- Current_Action is in PD.Error_Action_Range
  9471.                     raise PD.Parser_Error;
  9472.             end if;
  9473.         end loop Do_Parse;
  9474.         return ParseStack.Pop;
  9475.     
  9476.     exception
  9477.         when PD.MemoryOverflow =>
  9478.             -- raised if Parse runs out of newable memory.
  9479.             raise PD.MemoryOverflow;
  9480.     
  9481.     end Parse;
  9482.     
  9483.     ------------------------------------------------------------------
  9484.  
  9485. end Parser;
  9486.  
  9487. ----------------------------------------------------------------------
  9488. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9489. --PARSESTK.BDY
  9490. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9491. -- $Source: /nosc/work/parser/RCS/ParseStk.bdy,v $
  9492. -- $Revision: 4.0 $ -- $Date: 85/02/19 11:34:13 $ -- $Author: carol $
  9493.  
  9494. ----------------------------------------------------------------------
  9495.  
  9496. with ParseTables;               -- state tables generated by parser
  9497.                                 --     generator
  9498. use ParseTables;
  9499.  
  9500. with Grammar_Constants;
  9501. use Grammar_Constants;          -- to have visibility on operations
  9502.                                 -- on type ParserInteger declared there.
  9503. package body ParseStack is
  9504.  
  9505. --| Overview
  9506. --|
  9507. --| The data structure is implemented as an array.
  9508. --|
  9509.  
  9510.     ------------------------------------------------------------------
  9511.     -- Declarations Global to Package Body ParseStack
  9512.     ------------------------------------------------------------------
  9513.  
  9514.     Index       : PD.StateParseStacksIndex := 0;
  9515.         --| top element in stack.
  9516.  
  9517.     Space : array (PD.StateParseStacksRange) of PD.ParseStackElement;
  9518.         --| Storage used to hold stack elements
  9519.  
  9520.     ------------------------------------------------------------------
  9521.     -- Subprogram Bodies Global to Package ParseStack
  9522.         -- (declared in package specification).
  9523.     ------------------------------------------------------------------
  9524.  
  9525.     procedure Push(Element : in PD.ParseStackElement) is
  9526.  
  9527.     begin
  9528.  
  9529.         if (Index >= PD.StateParseStacksRange'Last) then
  9530.             raise OverFlow;
  9531.         end if;
  9532.  
  9533.         Index := Index + 1;
  9534.         Space (Index) := Element;
  9535.  
  9536.     end Push;
  9537.  
  9538.     ------------------------------------------------------------------
  9539.  
  9540.     function Pop return PD.ParseStackElement is
  9541.  
  9542.     begin
  9543.  
  9544.         if (Index < PD.StateParseStacksRange'First) then
  9545.             raise UnderFlow;
  9546.         end if;
  9547.  
  9548.         Index := Index - 1;
  9549.         return Space (Index + 1);
  9550.  
  9551.     end Pop;
  9552.  
  9553.     ------------------------------------------------------------------
  9554.  
  9555.     function Length return PD.StateParseStacksIndex is
  9556.  
  9557.     begin
  9558.  
  9559.         return Index;
  9560.  
  9561.     end Length;
  9562.  
  9563.     ------------------------------------------------------------------
  9564.  
  9565.     procedure Reduce(TopN : in PD.StateParseStacksIndex) is
  9566.  
  9567.     begin
  9568.         if (TopN > Index) then
  9569.             raise UnderFlow;
  9570.         end if;
  9571.  
  9572.         Index := Index - TopN;
  9573.  
  9574.     end Reduce; -- procedure
  9575.  
  9576.     ------------------------------------------------------------------
  9577.  
  9578. end ParseStack;
  9579.  
  9580. ----------------------------------------------------------------------
  9581. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9582. --STATESTK.BDY
  9583. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9584. -- $Source: /nosc/work/parser/RCS/StateStk.bdy,v $
  9585. -- $Revision: 4.0 $ -- $Date: 85/02/19 11:45:59 $ -- $Author: carol $
  9586.  
  9587. ----------------------------------------------------------------------
  9588.  
  9589. with ParseTables;               -- state tables generated
  9590.                                 -- by parser generator
  9591. use ParseTables;
  9592. with Grammar_Constants;         -- constants generated by parser generator
  9593. use Grammar_Constants;          -- to have visiblity on operations
  9594.                                 -- on type ParserInteger.
  9595.  
  9596. package body StateStack is
  9597.  
  9598. --| Overview
  9599. --|
  9600. --| The data structure is implemented as an array.
  9601. --|
  9602.  
  9603. --| Notes
  9604. --|
  9605. --| Abbreviations used in this compilation unit:
  9606. --|
  9607. --| Init : used as prefix for Initialize
  9608. --|
  9609.  
  9610.     ------------------------------------------------------------------
  9611.     -- Declarations Global to Package Body StateStack
  9612.     ------------------------------------------------------------------
  9613.  
  9614.     Index        : StateParseStacksIndex := 0;
  9615.     --| top element in stack.
  9616.     Next_To_Copy : StateParseStacksIndex := 0;
  9617.     --| next element to copy in stack.
  9618.  
  9619.     Space : array (StateParseStacksRange) of StateStackElement;
  9620.     --| Storage used to hold stack elements
  9621.  
  9622.  
  9623.     ------------------------------------------------------------------
  9624.     -- Subprogram Bodies Global to Package StateStack
  9625.         -- (declared in package specification).
  9626.     ------------------------------------------------------------------
  9627.  
  9628.     procedure Push(Element: in StateStackElement) is
  9629.  
  9630.     begin
  9631.  
  9632.         if (Index >= StateParseStacksRange'Last) then
  9633.             raise OverFlow;
  9634.         end if;
  9635.  
  9636.         Index := Index + 1;
  9637.         Space (Index) := Element;
  9638.  
  9639.     end Push;
  9640.  
  9641.     ------------------------------------------------------------------
  9642.  
  9643.     function Pop return StateStackElement is
  9644.  
  9645.     begin
  9646.  
  9647.         if (Index < StateParseStacksRange'First) then
  9648.             raise UnderFlow;
  9649.         end if;
  9650.  
  9651.        Index := Index - 1;
  9652.        return Space (Index + 1);
  9653.  
  9654.     end Pop;
  9655.  
  9656.     ------------------------------------------------------------------
  9657.  
  9658.     function CopyTop return StateStackElement is
  9659.  
  9660.     begin
  9661.  
  9662.         InitCopy;
  9663.         return CopyNext;
  9664.  
  9665.     end CopyTop;
  9666.  
  9667.     ------------------------------------------------------------------
  9668.  
  9669.     function CopyNext return StateStackElement is
  9670.  
  9671.     begin 
  9672.  
  9673.         Next_To_Copy := Next_To_Copy - 1;
  9674.  
  9675.         if (Next_To_Copy < StateParseStacksRange'First) then
  9676.             raise UnderFlow;
  9677.         end if;
  9678.  
  9679.         return Space (Next_To_Copy);
  9680.  
  9681.     end CopyNext;
  9682.  
  9683.     ------------------------------------------------------------------
  9684.  
  9685.     function Length return StateParseStacksIndex is
  9686.  
  9687.     begin
  9688.  
  9689.         return Index;
  9690.  
  9691.     end Length;
  9692.  
  9693.     ------------------------------------------------------------------
  9694.  
  9695.     procedure InitCopy is
  9696.  
  9697.     begin
  9698.  
  9699.         Next_To_Copy := Index + 1;  -- start examination here
  9700.  
  9701.     end InitCopy;
  9702.  
  9703.     ------------------------------------------------------------------
  9704.  
  9705.     function CopyThisOne (    --| returns the which_oneth element
  9706.         which_one:   StateParseStacksRange) return StateStackElement is
  9707.  
  9708.     begin
  9709.  
  9710.         if which_one > Index then
  9711.             raise OverFlow;
  9712.         end if;
  9713.  
  9714.         return (Space (which_one));
  9715.  
  9716.     end CopyThisOne;
  9717.  
  9718.     ------------------------------------------------------------------
  9719.  
  9720.     procedure Reduce (TopN : StateParseStacksIndex) is
  9721.  
  9722.     begin
  9723.  
  9724.         if (TopN > Index) then
  9725.             raise UnderFlow;
  9726.         end if;
  9727.  
  9728.         Index := Index - TopN;
  9729.  
  9730.     end Reduce;
  9731.  
  9732.     ------------------------------------------------------------------
  9733.  
  9734. end StateStack;
  9735.  
  9736. ----------------------------------------------------------------------
  9737. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9738. --PGFILE.SPC
  9739. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9740. with Text_IO;
  9741. with String_Pkg;
  9742.  
  9743. package Paginated_Output is
  9744.  
  9745. --| Create paginated text files with user defined heading,
  9746. --| footing, and page length.
  9747.                                                     pragma Page;
  9748. --| Overview:
  9749.  
  9750. --| The Paginated_Output package is used to create paginated
  9751. --| output files.  When such a file is created, the page length,
  9752. --| page header and footer length are specified. Several
  9753. --| operations are provided for setting/replacing the header or 
  9754. --| the footer text which will appear on each output page.
  9755. --| The following escapes can be used in the header/footer texts:
  9756. --|-
  9757. --|     ~f    the current external file name
  9758. --|     ~p    the current page number
  9759. --|     ~d    the current date (eg. 03/15/85)
  9760. --|     ~c    the current calendar date (eg. March 15, 1985)
  9761. --|     ~t    the current time (eg. 04:53:32)
  9762. --|+
  9763. --| Case is not significant after the tilde (~).  If the tilde
  9764. --| is followed by any other character, only the second character
  9765. --| is printed unless the line ends with a tilde in which case
  9766. --| the line will be terminated one character before the tilde.
  9767. --| 
  9768. --| The header is printed just before the first line of a page
  9769. --| is output, and the footer is printed just after the last line.
  9770. --| Thus, if a paginated file is opened and closed without any calls
  9771. --| to print a line in between, the output is a null file.
  9772. --|
  9773. --| This package knows nothing about (and places no limits on)
  9774. --| the length or contents of each line sent to the output file.  
  9775. --| In particular, if the line contains ASCII control codes
  9776. --| for new line, form feed, and/or vertical tab the output file
  9777. --| will not be properly paginated.  Normal usage is to call
  9778. --| Create_Paginated_File, call Set_Header/Set_Footer, call Put_Line
  9779. --| repeatedly to output a sequence of lines of text, and finally
  9780. --| call Close_Paginated_File to complete the last page and close
  9781. --| the file.
  9782.  
  9783. --| N/A: Effects, Requires, Modifies, Raises
  9784.                                                     pragma Page;
  9785.             -- Exceptions --
  9786.  
  9787. Files_Already_Linked        --| Raised if an attempt is made to
  9788.           : exception;    --| link two linked paginated files 
  9789. File_Already_Open : exception;    --| Raised if create is attempted
  9790.                 --| for an already existing file.
  9791. File_Error        : exception;    --| Raised if unable to open a file
  9792.                 --| other than File_Already_Open
  9793. File_Not_Open     : exception;    --| Raised if close is attempted
  9794.                 --| for an unopened file.
  9795. Invalid_Count     : exception;    --| Raised if a requested count 
  9796.                 --| can not be serviced.
  9797. Invalid_File      : exception;    --| Raised if output is attempted
  9798.                 --| with an invalid file handle.
  9799. Output_Error      : exception;    --| Raised if error is encountered
  9800.                 --| during an output operation.
  9801. Page_Layout_Error : exception;    --| Raised if page specification
  9802.                 --| is invalid.
  9803. Page_Overflow     : exception;    --| Raised if specified reserve
  9804.                 --| value exceeds the page size.
  9805. Text_Overflow     : exception;    --| Raised if header/footer text
  9806.                 --| overflows area.
  9807. Text_Underflow    : exception;    --| Raised if header/footer text
  9808.                 --| underflows area.
  9809.                                                     pragma Page;
  9810.                -- Types --
  9811.  
  9812. subtype Host_File_Name is string;
  9813.                 --| String of valid characters for
  9814.                 --| external file name.
  9815.  
  9816. type Variable_String_Array is    --| Array of variable length strings
  9817.     array (positive range <>) of String_Pkg.String_Type;
  9818.  
  9819. type Paginated_File_Handle is    --| Handle to be passed around in a
  9820.     limited private;        --| program that uses paginated output.
  9821.  
  9822. type Paginated_Output_Mode is (OUTPUT, ERROR);
  9823.                 --| Paginated output mode
  9824.                                                     pragma Page;
  9825.             -- Operations --
  9826.  
  9827. procedure Create_Paginated_File(--| Create a paginated output file
  9828.                 --| and return the file handle.
  9829.     File_Name   : in Host_File_Name   := "";
  9830.                 --| The name of the file to be created.
  9831.     File_Handle : in out Paginated_File_Handle;
  9832.                 --| Handle to be used for subsequent
  9833.                 --| operations
  9834.     Page_Size   : in integer          := 66;
  9835.                 --| The number of lines per page
  9836.     Header_Size : in integer          := 6;
  9837.                 --| The number of header text lines
  9838.     Footer_Size : in integer          := 6;
  9839.                 --| The number of footer text lines
  9840.     Output_Mode : in Paginated_Output_Mode := OUTPUT
  9841.                 --| Output mode
  9842.     ); 
  9843.  
  9844. --| Raises:
  9845. --| File_Already_Open, File_Error, Page_Layout_Error
  9846.  
  9847. --| Requires:
  9848. --| File_Name is an valid external name of the file to be created (If
  9849. --| it is omitted, the current output file is selected).  Page_Size,
  9850. --| Header_Size, and Footer_Size are optional values (if omitted 66,
  9851. --| 6, and 6 are set, respectively) to be used for the page layout
  9852. --| of the file to be created.  Page_Size specifies the total number
  9853. --| of lines per page (including the areas for header and footer).
  9854. --| Header_Size and Footer_Size specify the number of lines to be
  9855. --| reserved for the header and footer areas, respectively.
  9856.  
  9857. --| Effects:
  9858. --| Creates a new paginated file with Page_Size number of lines
  9859. --| per page and Header_Size and Footer_Size number of lines
  9860. --| reserved for header and footer, respectively.  Access to the
  9861. --| paginated file control structure Paginated_File_Handle is
  9862. --| returned for use in subsequent operations.
  9863.  
  9864. --| Errors:
  9865. --| If any of the page layout values are negative, the exception
  9866. --| Page_Layout_Error is raised.  Also if the total number of lines
  9867. --| in the header and footer plus one exceeds Page_Size, the same
  9868. --| exception is raised.  This guarantees that at least one line of
  9869. --| text can appear on each output page.
  9870. --| If the output file with the specified File_Name is already open
  9871. --| File_Already_Open exception is raised.
  9872. --| If the file cannot be opened for any other reason, the exception
  9873. --| File_Error is raise.
  9874.  
  9875. --| N/A: Modifies
  9876.                                                     pragma Page;
  9877. procedure Set_Standard_Paginated_File(
  9878.                 --| Set the standard paginated output file
  9879.                 --| characteristics. 
  9880.     File_Name   : in Host_File_Name;
  9881.                 --| The name of the file to be set.
  9882.     Page_Size   : in integer;    --| The number of lines per page
  9883.     Header_Size : in integer;    --| The number of header text lines
  9884.     Footer_Size : in integer    --| The number of footer text lines
  9885.     ); 
  9886.  
  9887. --| Raises:
  9888. --| File_Already_Open, File_Error, Page_Layout_Error
  9889.  
  9890. --| Requires:
  9891. --| File_Name is an valid external name of the file to be created
  9892. --| Page_Size, Header_Size, and Footer_Size are used for the page layout
  9893. --| of the file.
  9894.  
  9895. --| Effects:
  9896. --| Sets the standard paginated file to the given file name and sets the 
  9897. --| page layout as specified. 
  9898.  
  9899. --| Errors:
  9900. --| If any of the page layout values are negative, the exception
  9901. --| Page_Layout_Error is raised.  Also if the total number of lines
  9902. --| in the header and footer plus one exceeds Page_Size, the same
  9903. --| exception is raised.  This guarantees that at least one line of
  9904. --| text can appear on each output page.
  9905. --| If the output file with the specified File_Name is already open
  9906. --| File_Already_Open exception is raised.
  9907. --| If the file cannot be opened for any other reason, the exception
  9908. --| File_Error is raise.
  9909.  
  9910. --| N/A: Modifies
  9911.                                                     pragma Page;
  9912. procedure Duplicate_Paginated_File(
  9913.                 --| Duplicate an already existing
  9914.                 --| paginated file and return the
  9915.                 --| file handle.
  9916.     Old_Handle : in Paginated_File_Handle;
  9917.                 --| Existing paginated file handle
  9918.     New_Handle : in out Paginated_File_Handle
  9919.                 --| Handle of the new paginated file
  9920.     ); 
  9921.  
  9922. --| Requires:
  9923. --| Old_Handle for the existing paginated file to be duplicated.
  9924. --| The new handle (duplocated from Old_Handle) to be used to refer
  9925. --| to the same paginated file.
  9926.  
  9927. --| Effects:
  9928. --| Handle for the aginated file refered to be Old_Handle will be
  9929. --| duplicated in New_Handle.
  9930.  
  9931. --| N/A: Raises, Modifies, Errors
  9932.                                                     pragma Page;
  9933. procedure Set_Page_Layout(    --| Set the page layout for the 
  9934.                 --| paginated file.
  9935.     Page_Size   : in integer;    --| The number of lines per page
  9936.     Header_Size : in integer;    --| The number of header text lines
  9937.     Footer_Size : in integer    --| The number of footer text lines
  9938.     );
  9939.  
  9940. --| Raises:
  9941. --| Page_Layout_Error
  9942.  
  9943. --| Requires:
  9944. --| Page_Size specifies the total number of lines per page (including the
  9945. --| area for header & footer).
  9946. --| Header_Size and Footer_Size specifies the number of lines to be
  9947. --| reserved for the header and footer area, respectively.
  9948.  
  9949. --| Effects:
  9950. --| A paginated file is set with Page_Size number of lines per
  9951. --| page and Header_Size and Footer_Size number of lines
  9952. --| reserved for header and footer, respectively.
  9953. --| A page eject is performed if not at the top of the page before
  9954. --| the new page layout values are set.
  9955.  
  9956. --| Errors:
  9957. --| If any of the page layout values are negative, the exception
  9958. --| Page_Layout_Error is raised.  Also if the total number of lines
  9959. --| in the header and footer plus one exceeds Page_Size, the exception
  9960. --| Page_Layout_Error is raised.
  9961.  
  9962. --| N/A: Modifies
  9963.                                                     pragma Page;
  9964. procedure Set_Page_Layout(    --| Set the page layout for the 
  9965.                 --| paginated file.
  9966.     File_Handle : in Paginated_File_Handle;
  9967.                 --| The paginated file to be set 
  9968.                 --| with the given page layout
  9969.     Page_Size   : in integer;    --| The number of lines per page
  9970.     Header_Size : in integer;    --| The number of header text lines
  9971.     Footer_Size : in integer    --| The number of footer text lines
  9972.     );
  9973.  
  9974. --| Raises:
  9975. --| Page_Layout_Error
  9976.  
  9977. --| Requires:
  9978. --| File_Handle is the access to the paginated file control structure
  9979. --| returned by Create_Paginated_File.  Page_Size specifies the total
  9980. --| number of lines per page (including the area for header & footer).
  9981. --| Header_Size and Footer_Size specifies the number of lines to be
  9982. --| reserved for the header and footer area, respectively.
  9983.  
  9984. --| Effects:
  9985. --| A paginated file is set with Page_Size number of lines per
  9986. --| page and Header_Size and Footer_Size number of lines
  9987. --| reserved for header and footer, respectively.
  9988. --| A page eject is performed if not at the top of the page before
  9989. --| the new page layout values are set.
  9990.  
  9991. --| Errors:
  9992. --| If any of the page layout values are negative, the exception
  9993. --| Page_Layout_Error is raised.  Also if the total number of lines
  9994. --| in the header and footer plus one exceeds Page_Size, the exception
  9995. --| Page_Layout_Error is raised.
  9996.  
  9997. --| N/A: Modifies
  9998.                                                     pragma Page;
  9999. procedure Link_Paginated_File(    --| Link paginated files into a chain
  10000.     File_Handle1 : in Paginated_File_Handle;
  10001.                 --| Handle to be linked
  10002.     File_Handle2 : in Paginated_File_Handle
  10003.                 --| Handle to be linked
  10004.     );
  10005.  
  10006. --| Raises:
  10007. --| Files_Already_Linked
  10008.  
  10009. --| Requires:
  10010. --| File_Handle1 and File_Handle2, access to the paginated file control
  10011. --| structures.
  10012.  
  10013. --| Effects:
  10014. --| File_Handle1 and File_Handle2 in a chain so in the given order such that
  10015. --| subsequent operations to File_Handle1 are reflected in both files. 
  10016. --| Any operations to File_Handle2 are NOT performed for File_Handle1.
  10017.  
  10018. --| Errors:
  10019. --| If either of the files have been linked, raises Files_Already_Linked.
  10020.  
  10021. --| N/A: Modifies
  10022.                                                     pragma Page;
  10023. procedure Unlink_Paginated_File(
  10024.     File_Handle : in Paginated_File_Handle
  10025.     );
  10026.  
  10027. --| Requires:
  10028. --| File_Handle which accesses a paginated file control structure.
  10029.  
  10030. --| Effects:
  10031. --| Takes File_Handle out of a previously linked chain.
  10032.  
  10033. --| N/A: Raises, Modifies, Errors
  10034.                                                     pragma Page;
  10035. procedure Set_Header(
  10036.     Header_Text : in Variable_String_Array
  10037.     );
  10038.  
  10039. procedure Set_Header(        --| Set the header text on a paginated
  10040.                 --| output file.
  10041.     File_Handle : in Paginated_File_Handle;
  10042.                 --| Paginated file to be set 
  10043.                 --| with the header text
  10044.     Header_Text : in Variable_String_Array
  10045.                 --| Sequence of header lines
  10046.     );
  10047.  
  10048. --| Raises:
  10049. --| Invalid_File, Text_Overflow
  10050.  
  10051. --| Requires:
  10052. --| File_Handle is the access to the paginated file control structure
  10053. --| returned by Create_Paginated_File.  Header_Text is the array
  10054. --| of text to be used for the page header.
  10055.  
  10056. --| Effects:
  10057. --| The header text of File_Handle is set to Header_Text.  Note that
  10058. --| the replaced header text will not be printed until the next
  10059. --| page of the output.
  10060.  
  10061. --| Errors:
  10062. --| If File_Handle is not a valid access to a paginated file control
  10063. --| structure exception Invalid_File is raised.
  10064. --| Specification of a header text array which implies a greater
  10065. --| number of lines than reserved for by Create_Paginated_File or
  10066. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  10067.  
  10068. --| N/A: Modifies
  10069.                                                     pragma Page;
  10070. procedure Set_Header(
  10071.     Header_Line : in integer;
  10072.     Header_Text : in string
  10073.     );
  10074.  
  10075. procedure Set_Header(        --| Replace a line of header text on a
  10076.                 --| paginated output file.
  10077.     File_Handle : in Paginated_File_Handle;
  10078.                 --| Paginated file to be set 
  10079.                 --| with the header text
  10080.     Header_Line : in integer;    --| Line number of header to be replaced
  10081.     Header_Text : in string    --| Header line to replace
  10082.     );
  10083.  
  10084. --| Raises:
  10085. --| Invalid_File, Text_Overflow, Text_Underflow
  10086.  
  10087. --| Requires:
  10088. --| File_Handle is the access to the paginated file control structure
  10089. --| returned by Create_Paginated_File.  Header_Text is the text
  10090. --| to replace the existing header line at Header_Line.
  10091.  
  10092. --| Effects:
  10093. --| The header text of File_Handle at Header_Line is set to Header_Text.
  10094. --| Note that the replaced header text will not be printed until
  10095. --| the next page of the output.
  10096.  
  10097. --| Errors:
  10098. --| If File_Handle is not a valid access to a paginated file control
  10099. --| structure exception Invalid_File is raised.
  10100. --| Specification of Header_Line greater than the number of header
  10101. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10102. --| results in Text_Overflow exception to be raised.
  10103. --| If the specified Header_Line is less than or equal to 0 then
  10104. --| Text_Underflow exception is raised.
  10105.  
  10106. --| N/A: Modifies
  10107.                                                     pragma Page;
  10108. procedure Set_Header(
  10109.     Header_Line : in integer;
  10110.     Header_Text : in String_Pkg.String_Type
  10111.     );
  10112.  
  10113. procedure Set_Header(        --| Replace a line of header text on a
  10114.                 --| paginated output file.
  10115.     File_Handle : in Paginated_File_Handle;
  10116.                 --| Paginated file to be set 
  10117.                 --| with the header text
  10118.     Header_Line : in integer;    --| Line number of header to be replaced
  10119.     Header_Text : in String_Pkg.String_Type
  10120.                 --| Header line to replace
  10121.     );
  10122.  
  10123. --| Raises:
  10124. --| Invalid_File, Text_Overflow, Text_Underflow
  10125.  
  10126. --| Requires:
  10127. --| File_Handle is the access to the paginated file control structure
  10128. --| returned by Create_Paginated_File.  Header_Text is the text
  10129. --| to replace the existing header line at Header_Line.
  10130.  
  10131. --| Effects:
  10132. --| The header text of File_Handle at Header_Line is set to Header_Text.
  10133. --| Note that the replaced header text will not be printed until
  10134. --| the next page of the output.
  10135.  
  10136. --| Errors:
  10137. --| If File_Handle is not a valid access to a paginated file control
  10138. --| structure exception Invalid_File is raised.
  10139. --| Specification of Header_Line greater than the number of header
  10140. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10141. --| results in Text_Overflow exception to be raised.
  10142. --| If the specified Header_Line is less than or equal to 0 then
  10143. --| Text_Underflow exception is raised.
  10144.  
  10145. --| N/A: Modifies
  10146.                                                     pragma Page;
  10147. procedure Set_Odd_Header(
  10148.     Header_Text : in Variable_String_Array
  10149.     );
  10150.  
  10151. procedure Set_Odd_Header(    --| Set the header text for the odd
  10152.                 --| pages of a paginated output file.
  10153.     File_Handle : in Paginated_File_Handle;
  10154.                 --| Paginated file to be set 
  10155.                 --| with the header text
  10156.     Header_Text : in Variable_String_Array
  10157.                 --| Sequence of header lines
  10158.     );
  10159.  
  10160. --| Raises:
  10161. --| Invalid_File, Text_Overflow
  10162.  
  10163. --| Requires:
  10164. --| File_Handle is the access to the paginated file control structure
  10165. --| returned by Create_Paginated_File.  Header_Text is the array
  10166. --| of text to be used for the odd page header.
  10167.  
  10168. --| Effects:
  10169. --| The header text for odd pages of File_Handle is set to Header_Text.
  10170. --| Note that the replaced header text will not be printed until
  10171. --| the next odd page of the output.
  10172.  
  10173. --| Errors:
  10174. --| If File_Handle is not a valid access to a paginated file control
  10175. --| structure exception Invalid_File is raised.
  10176. --| Specification of a header text array which implies a greater
  10177. --| number of lines than reserved for by Create_Paginated_File or
  10178. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  10179.  
  10180. --| N/A: Modifies
  10181.                                                     pragma Page;
  10182. procedure Set_Odd_Header(
  10183.     Header_Line : in integer;
  10184.     Header_Text : in string
  10185.     );
  10186.  
  10187. procedure Set_Odd_Header(    --| Replace a line of header text on
  10188.                 --| the odd pages of a paginated
  10189.                 --| output file.
  10190.     File_Handle : in Paginated_File_Handle;
  10191.                 --| Paginated file to be set 
  10192.                 --| with the header text
  10193.     Header_Line : in integer;    --| Line number of header to be replaced
  10194.     Header_Text : in string    --| Header line to replace
  10195.     );
  10196.  
  10197. --| Raises:
  10198. --| Invalid_File, Text_Overflow, Text_Underflow
  10199.  
  10200. --| Requires:
  10201. --| File_Handle is the access to the paginated file control structure
  10202. --| returned by Create_Paginated_File.  Header_Text is the text
  10203. --| to replace the existing odd page header line at Header_Line.
  10204.  
  10205. --| Effects:
  10206. --| The odd page header text of File_Handle at Header_Line is set
  10207. --| to Header_Text.  Note that the replaced header text will not be
  10208. --| printed until the next odd page of the output.
  10209.  
  10210. --| Errors:
  10211. --| If File_Handle is not a valid access to a paginated file control
  10212. --| structure exception Invalid_File is raised.
  10213. --| Specification of Header_Line greater than the number of header
  10214. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10215. --| results in Text_Overflow exception to be raised.
  10216. --| If the specified Header_Line is less than or equal to 0 then
  10217. --| Text_Underflow exception is raised.
  10218.  
  10219. --| N/A: Modifies
  10220.                                                     pragma Page;
  10221. procedure Set_Odd_Header(
  10222.     Header_Line : in integer;
  10223.     Header_Text : in String_Pkg.String_Type
  10224.     );
  10225.  
  10226. procedure Set_Odd_Header(    --| Replace a line of header text on
  10227.                 --| the odd pages of a paginated
  10228.                 --| output file.
  10229.     File_Handle : in Paginated_File_Handle;
  10230.                 --| Paginated file to be set 
  10231.                 --| with the header text
  10232.     Header_Line : in integer;    --| Line number of header to be replaced
  10233.     Header_Text : in String_Pkg.String_Type
  10234.                 --| Header line to replace
  10235.     );
  10236.  
  10237. --| Raises:
  10238. --| Invalid_File, Text_Overflow, Text_Underflow
  10239.  
  10240. --| Requires:
  10241. --| File_Handle is the access to the paginated file control structure
  10242. --| returned by Create_Paginated_File.  Header_Text is the text
  10243. --| to replace the existing odd page header line at Header_Line.
  10244.  
  10245. --| Effects:
  10246. --| The odd page header text of File_Handle at Header_Line is set
  10247. --| to Header_Text.  Note that the replaced header text will not be
  10248. --| printed until the next odd page of the output.
  10249.  
  10250. --| Errors:
  10251. --| If File_Handle is not a valid access to a paginated file control
  10252. --| structure exception Invalid_File is raised.
  10253. --| Specification of Header_Line greater than the number of header
  10254. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10255. --| results in Text_Overflow exception to be raised.
  10256. --| If the specified Header_Line is less than or equal to 0 then
  10257. --| Text_Underflow exception is raised.
  10258.  
  10259. --| N/A: Modifies
  10260.                                                     pragma Page;
  10261. procedure Set_Even_Header(
  10262.     Header_Text : in Variable_String_Array
  10263.     );
  10264.  
  10265. procedure Set_Even_Header(    --| Set the header text for the even
  10266.                 --| pages of a paginated output file.
  10267.     File_Handle : in Paginated_File_Handle;
  10268.                 --| Paginated file to be set 
  10269.                 --| with the header text
  10270.     Header_Text : in Variable_String_Array
  10271.                 --| Sequence of header lines
  10272.     );
  10273.  
  10274. --| Raises:
  10275. --| Invalid_File, Text_Overflow
  10276.  
  10277. --| Requires:
  10278. --| File_Handle is the access to the paginated file control structure
  10279. --| returned by Create_Paginated_File.  Header_Text is the array
  10280. --| of text to be used for the even page header.
  10281.  
  10282. --| Effects:
  10283. --| The header text for even pages of File_Handle is set to Header_Text.
  10284. --| Note that the replaced header text will not be printed until
  10285. --| the next even page of the output.
  10286.  
  10287. --| Errors:
  10288. --| If File_Handle is not a valid access to a paginated file control
  10289. --| structure exception Invalid_File is raised.
  10290. --| Specification of a header text array which implies a greater
  10291. --| number of lines than reserved for by Create_Paginated_File or
  10292. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  10293.  
  10294. --| N/A: Modifies
  10295.                                                     pragma Page;
  10296. procedure Set_Even_Header(
  10297.     Header_Line : in integer;
  10298.     Header_Text : in string
  10299.     );
  10300.  
  10301. procedure Set_Even_Header(    --| Replace a line of header text on
  10302.                 --| the even pages of a paginated
  10303.                 --| output file.
  10304.     File_Handle : in Paginated_File_Handle;
  10305.                 --| Paginated file to be set 
  10306.                 --| with the header text
  10307.     Header_Line : in integer;    --| Line number of header to be replaced
  10308.     Header_Text : in string    --| Header line to replace
  10309.     );
  10310.  
  10311. --| Raises:
  10312. --| Invalid_File, Text_Overflow, Text_Underflow
  10313.  
  10314. --| Requires:
  10315. --| File_Handle is the access to the paginated file control structure
  10316. --| returned by Create_Paginated_File.  Header_Text is the text
  10317. --| to replace the existing even page header line at Header_Line.
  10318.  
  10319. --| Effects:
  10320. --| The even page header text of File_Handle at Header_Line is set
  10321. --| to Header_Text.  Note that the replaced header text will not be
  10322. --| printed until the next even page of the output.
  10323.  
  10324. --| Errors:
  10325. --| If File_Handle is not a valid access to a paginated file control
  10326. --| structure exception Invalid_File is raised.
  10327. --| Specification of Header_Line greater than the number of header
  10328. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10329. --| results in Text_Overflow exception to be raised.
  10330. --| If the specified Header_Line is less than or equal to 0 then
  10331. --| Text_Underflow exception is raised.
  10332.  
  10333. --| N/A: Modifies
  10334.                                                     pragma Page;
  10335. procedure Set_Even_Header(
  10336.     Header_Line : in integer;
  10337.     Header_Text : in String_Pkg.String_Type
  10338.     );
  10339.  
  10340. procedure Set_Even_Header(    --| Replace a line of header text on
  10341.                 --| the even pages of a paginated
  10342.                 --| output file.
  10343.     File_Handle : in Paginated_File_Handle;
  10344.                 --| Paginated file to be set 
  10345.                 --| with the header text
  10346.     Header_Line : in integer;    --| Line number of header to be replaced
  10347.     Header_Text : in String_Pkg.String_Type
  10348.                 --| Header line to replace
  10349.     );
  10350.  
  10351. --| Raises:
  10352. --| Invalid_File, Text_Overflow, Text_Underflow
  10353.  
  10354. --| Requires:
  10355. --| File_Handle is the access to the paginated file control structure
  10356. --| returned by Create_Paginated_File.  Header_Text is the text
  10357. --| to replace the existing even page header line at Header_Line.
  10358.  
  10359. --| Effects:
  10360. --| The even page header text of File_Handle at Header_Line is set
  10361. --| to Header_Text.  Note that the replaced header text will not be
  10362. --| printed until the next even page of the output.
  10363.  
  10364. --| Errors:
  10365. --| If File_Handle is not a valid access to a paginated file control
  10366. --| structure exception Invalid_File is raised.
  10367. --| Specification of Header_Line greater than the number of header
  10368. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10369. --| results in Text_Overflow exception to be raised.
  10370. --| If the specified Header_Line is less than or equal to 0 then
  10371. --| Text_Underflow exception is raised.
  10372.  
  10373. --| N/A: Modifies
  10374.                                                     pragma Page;
  10375. procedure Set_Footer(
  10376.     Footer_Text : in Variable_String_Array
  10377.     );
  10378.  
  10379. procedure Set_Footer(        --| Set the footer text on a paginated
  10380.                 --| output file.
  10381.     File_Handle : in Paginated_File_Handle;
  10382.                 --| Paginated file to be set 
  10383.                 --| with the footer text
  10384.     Footer_Text : in Variable_String_Array
  10385.                 --| Sequence of lines for the footer
  10386.     );
  10387.  
  10388. --| Raises:
  10389. --| Invalid_File, Text_Overflow
  10390.  
  10391. --| Requires:
  10392. --| File_Handle is the access to the paginated file control structure
  10393. --| returned by Create_Paginated_File.  Footer_Text is the array
  10394. --| of text to be used for the page footer.
  10395.  
  10396. --| Effects:
  10397. --| The footer text of File_Handle is set to Footer_Text.  Note that
  10398. --| the replaced footer text will not be printed until the next
  10399. --| page of the output.
  10400.  
  10401. --| Errors:
  10402. --| If File_Handle is not a valid access to a paginated file control
  10403. --| structure exception Invalid_File is raised.
  10404. --| Specification of a footer text array which implies a greater
  10405. --| number of lines than reserved for by Create_Paginated_File or
  10406. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  10407. --| If the specified Footer_Line is less than or equal to 0 then
  10408. --| Text_Underflow exception is raised.
  10409.  
  10410. --| N/A: Modifies
  10411.                                                     pragma Page;
  10412. procedure Set_Footer(
  10413.     Footer_Line : in integer;
  10414.     Footer_Text : in string
  10415.     );
  10416.  
  10417. procedure Set_Footer(        --| Replace a line of header text on a
  10418.                 --| paginated output file.
  10419.     File_Handle : in Paginated_File_Handle;
  10420.                 --| Paginated file to be set 
  10421.                 --| with the footer text
  10422.     Footer_Line : in integer;    --| Line number of footer to be replaced
  10423.     Footer_Text : in string    --| Footer line to replace
  10424.     );
  10425.  
  10426. --| Raises:
  10427. --| Invalid_File, Text_Overflow, Text_Underflow
  10428.  
  10429. --| Requires:
  10430. --| File_Handle is the access to the paginated file control structure
  10431. --| returned by Create_Paginated_File.  Footer_Text is the text
  10432. --| to replace the existing footer line at Footer_Line.
  10433.  
  10434. --| Effects:
  10435. --| The footer text of File_Handle at Footer_Line is set to Header_Text.
  10436. --| Note that the replaced footer text will not be printed until
  10437. --| the next page of the output.
  10438.  
  10439. --| Errors:
  10440. --| If File_Handle is not a valid access to a paginated file control
  10441. --| structure exception Invalid_File is raised.
  10442. --| Specification of Footer_Line greater than the number of footer
  10443. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10444. --| results in Text_Overflow exception to be raised.
  10445. --| If the specified Footer_Line is less than or equal to 0 then
  10446. --| Text_Underflow exception is raised.
  10447.  
  10448. --| N/A: Modifies
  10449.                                                     pragma Page;
  10450. procedure Set_Footer(
  10451.     Footer_Line : in integer;
  10452.     Footer_Text : in String_Pkg.String_Type
  10453.     );
  10454.  
  10455. procedure Set_Footer(        --| Replace a line of footer text on a
  10456.                 --| paginated output file.
  10457.     File_Handle : in Paginated_File_Handle;
  10458.                 --| Paginated file to be set 
  10459.                 --| with the footer text
  10460.     Footer_Line : in integer;    --| Line number of footer to be replaced
  10461.     Footer_Text : in String_Pkg.String_Type
  10462.                 --| Footer line to replace
  10463.     );
  10464.  
  10465. --| Raises:
  10466. --| Invalid_File, Text_Overflow, Text_Underflow
  10467.  
  10468. --| Requires:
  10469. --| File_Handle is the access to the paginated file control structure
  10470. --| returned by Create_Paginated_File.  Footer_Text is the text
  10471. --| to replace the existing footer line at Footer_Line.
  10472.  
  10473. --| Effects:
  10474. --| The footer text of File_Handle at Footer_Line is set to Header_Text.
  10475. --| Note that the replaced footer text will not be printed until
  10476. --| the next page of the output.
  10477.  
  10478. --| Errors:
  10479. --| If File_Handle is not a valid access to a paginated file control
  10480. --| structure exception Invalid_File is raised.
  10481. --| Specification of Footer_Line greater than the number of footer
  10482. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10483. --| results in Text_Overflow exception to be raised.
  10484. --| If the specified Footer_Line is less than or equal to 0 then
  10485. --| Text_Underflow exception is raised.
  10486.  
  10487. --| N/A: Modifies
  10488.                                                     pragma Page;
  10489. procedure Set_Odd_Footer(
  10490.     Footer_Text : in Variable_String_Array
  10491.     );
  10492.  
  10493. procedure Set_Odd_Footer(    --| Set the footer text for the odd
  10494.                 --| pages of a paginated output file.
  10495.     File_Handle : in Paginated_File_Handle;
  10496.                 --| Paginated file to be set 
  10497.                 --| with the footer text
  10498.     Footer_Text : in Variable_String_Array
  10499.                 --| Sequence of lines for the footer
  10500.     );
  10501.  
  10502. --| Raises:
  10503. --| Invalid_File, Text_Overflow
  10504.  
  10505. --| Requires:
  10506. --| File_Handle is the access to the paginated file control structure
  10507. --| returned by Create_Paginated_File.  Footer_Text is the array
  10508. --| of text to be used for the odd page footer.
  10509.  
  10510. --| Effects:
  10511. --| The footer text for odd pages of File_Handle is set to Footer_Text.
  10512. --| Note that the replaced footer text will not be printed until
  10513. --| the next odd page of the output.
  10514.  
  10515. --| Errors:
  10516. --| If File_Handle is not a valid access to a paginated file control
  10517. --| structure exception Invalid_File is raised.
  10518. --| Specification of a footer text array which implies a greater
  10519. --| number of lines than reserved for by Create_Paginated_File or
  10520. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  10521.  
  10522. --| N/A: Modifies
  10523.                                                     pragma Page;
  10524. procedure Set_Odd_Footer(
  10525.     Footer_Line : in integer;
  10526.     Footer_Text : in string
  10527.     );
  10528.  
  10529. procedure Set_Odd_Footer(    --| Replace a line of footer text on
  10530.                 --| the odd pages of a paginated
  10531.                 --| output file.
  10532.     File_Handle : in Paginated_File_Handle;
  10533.                 --| Paginated file to be set 
  10534.                 --| with the footer text
  10535.     Footer_Line : in integer;    --| Line number of footer to be replaced
  10536.     Footer_Text : in string    --| Footer line to replace
  10537.     );
  10538.  
  10539. --| Raises:
  10540. --| Invalid_File, Text_Overflow, Text_Underflow
  10541.  
  10542. --| Requires:
  10543. --| File_Handle is the access to the paginated file control structure
  10544. --| returned by Create_Paginated_File.  Footer_Text is the text
  10545. --| to replace the existing odd page footer line at Footer_Line.
  10546.  
  10547. --| Effects:
  10548. --| The odd page footer text of File_Handle at Footer_Line is set
  10549. --| to Footer_Text.  Note that the replaced footer text will not be
  10550. --| printed until the next odd page of the output.
  10551.  
  10552. --| Errors:
  10553. --| If File_Handle is not a valid access to a paginated file control
  10554. --| structure exception Invalid_File is raised.
  10555. --| Specification of Footer_Line greater than the number of footer
  10556. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10557. --| results in Text_Overflow exception to be raised.
  10558. --| If the specified Footer_Line is less than or equal to 0 then
  10559. --| Text_Underflow exception is raised.
  10560.  
  10561. --| N/A: Modifies
  10562.                                                     pragma Page;
  10563. procedure Set_Odd_Footer(
  10564.     Footer_Line : in integer;
  10565.     Footer_Text : in String_Pkg.String_Type
  10566.     );
  10567.  
  10568. procedure Set_Odd_Footer(    --| Replace a line of footer text on
  10569.                 --| the odd pages of a paginated
  10570.                 --| output file.
  10571.     File_Handle : in Paginated_File_Handle;
  10572.                 --| Paginated file to be set 
  10573.                 --| with the footer text
  10574.     Footer_Line : in integer;    --| Line number of footer to be replaced
  10575.     Footer_Text : in String_Pkg.String_Type
  10576.                 --| Footer line to replace
  10577.     );
  10578.  
  10579. --| Raises:
  10580. --| Invalid_File, Text_Overflow, Text_Underflow
  10581.  
  10582. --| Requires:
  10583. --| File_Handle is the access to the paginated file control structure
  10584. --| returned by Create_Paginated_File.  Footer_Text is the text
  10585. --| to replace the existing odd page footer line at Footer_Line.
  10586.  
  10587. --| Effects:
  10588. --| The odd page footer text of File_Handle at Footer_Line is set
  10589. --| to Footer_Text.  Note that the replaced footer text will not be
  10590. --| printed until the next odd page of the output.
  10591.  
  10592. --| Errors:
  10593. --| If File_Handle is not a valid access to a paginated file control
  10594. --| structure exception Invalid_File is raised.
  10595. --| Specification of Footer_Line greater than the number of footer
  10596. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10597. --| results in Text_Overflow exception to be raised.
  10598. --| If the specified Footer_Line is less than or equal to 0 then
  10599. --| Text_Underflow exception is raised.
  10600.  
  10601. --| N/A: Modifies
  10602.                                                     pragma Page;
  10603. procedure Set_Even_Footer(
  10604.     Footer_Text : in Variable_String_Array
  10605.     );
  10606.  
  10607. procedure Set_Even_Footer(    --| Set the footer text for the even
  10608.                 --| pages of a paginated output file.
  10609.     File_Handle : in Paginated_File_Handle;
  10610.                 --| Paginated file to be set 
  10611.                 --| with the footer text
  10612.     Footer_Text : in Variable_String_Array
  10613.                 --| Sequence of lines for the footer
  10614.     );
  10615.  
  10616. --| Raises:
  10617. --| Invalid_File, Text_Overflow
  10618.  
  10619. --| Requires:
  10620. --| File_Handle is the access to the paginated file control structure
  10621. --| returned by Create_Paginated_File.  Footer_Text is the array
  10622. --| of text to be used for the even page footer.
  10623.  
  10624. --| Effects:
  10625. --| The footer text for even pages of File_Handle is set to Footer_Text.
  10626. --| Note that the replaced footer text will not be printed until
  10627. --| the next even page of the output.
  10628.  
  10629. --| Errors:
  10630. --| If File_Handle is not a valid access to a paginated file control
  10631. --| structure exception Invalid_File is raised.
  10632. --| Specification of a footer text array which implies a greater
  10633. --| number of lines than reserved for by Create_Paginated_File or
  10634. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  10635.  
  10636. --| N/A: Modifies
  10637.                                                     pragma Page;
  10638. procedure Set_Even_Footer(
  10639.     Footer_Line : in integer;
  10640.     Footer_Text : in string
  10641.     );
  10642.  
  10643. procedure Set_Even_Footer(    --| Replace a line of footer text on
  10644.                 --| the even pages of a paginated
  10645.                 --| output file.
  10646.     File_Handle : in Paginated_File_Handle;
  10647.                 --| Paginated file to be set 
  10648.                 --| with the footer text
  10649.     Footer_Line : in integer;    --| Line number of footer to be replaced
  10650.     Footer_Text : in string    --| Footer line to replace
  10651.     );
  10652.  
  10653. --| Raises:
  10654. --| Invalid_File, Text_Overflow, Text_Underflow
  10655.  
  10656. --| Requires:
  10657. --| File_Handle is the access to the paginated file control structure
  10658. --| returned by Create_Paginated_File.  Footer_Text is the text
  10659. --| to replace the existing even page footer line at Footer_Line.
  10660.  
  10661. --| Effects:
  10662. --| The even page footer text of File_Handle at Footer_Line is set
  10663. --| to Footer_Text.  Note that the replaced footer text will not be
  10664. --| printed until the next even page of the output.
  10665.  
  10666. --| Errors:
  10667. --| If File_Handle is not a valid access to a paginated file control
  10668. --| structure exception Invalid_File is raised.
  10669. --| Specification of Footer_Line greater than the number of footer
  10670. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10671. --| results in Text_Overflow exception to be raised.
  10672. --| If the specified Footer_Line is less than or equal to 0 then
  10673. --| Text_Underflow exception is raised.
  10674.  
  10675. --| N/A: Modifies
  10676.                                                     pragma Page;
  10677. procedure Set_Even_Footer(
  10678.     Footer_Line : in integer;
  10679.     Footer_Text : in String_Pkg.String_Type
  10680.     );
  10681.  
  10682. procedure Set_Even_Footer(    --| Replace a line of footer text on
  10683.                 --| the even pages of a paginated
  10684.                 --| output file.
  10685.     File_Handle : in Paginated_File_Handle;
  10686.                 --| Paginated file to be set 
  10687.                 --| with the footer text
  10688.     Footer_Line : in integer;    --| Line number of footer to be replaced
  10689.     Footer_Text : in String_Pkg.String_Type
  10690.                 --| Footer line to replace
  10691.     );
  10692.  
  10693. --| Raises:
  10694. --| Invalid_File, Text_Overflow, Text_Underflow
  10695.  
  10696. --| Requires:
  10697. --| File_Handle is the access to the paginated file control structure
  10698. --| returned by Create_Paginated_File.  Footer_Text is the text
  10699. --| to replace the existing even page footer line at Footer_Line.
  10700.  
  10701. --| Effects:
  10702. --| The even page footer text of File_Handle at Footer_Line is set
  10703. --| to Footer_Text.  Note that the replaced footer text will not be
  10704. --| printed until the next even page of the output.
  10705.  
  10706. --| Errors:
  10707. --| If File_Handle is not a valid access to a paginated file control
  10708. --| structure exception Invalid_File is raised.
  10709. --| Specification of Footer_Line greater than the number of footer
  10710. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  10711. --| results in Text_Overflow exception to be raised.
  10712. --| If the specified Footer_Line is less than or equal to 0 then
  10713. --| Text_Underflow exception is raised.
  10714.  
  10715. --| N/A: Modifies
  10716.                                                     pragma Page;
  10717. procedure Clear_Header;    
  10718.  
  10719. procedure Clear_Header(        --| Set the header text on a paginated
  10720.                 --| output file to null lines
  10721.     File_Handle : in Paginated_File_Handle
  10722.                 --| Paginated file to be set 
  10723.                 --| with the header text
  10724.     );
  10725.  
  10726. --| Raises:
  10727. --| Invalid_File
  10728.  
  10729. --| Requires:
  10730. --| File_Handle is the access to the paginated file control structure
  10731. --| returned by Create_Paginated_File.
  10732.  
  10733. --| Effects:
  10734. --| The header text of File_Handle is cleared to null lines.
  10735. --| The replaced null header will not be printed until the next
  10736. --| page of the output.
  10737.  
  10738. --| Errors:
  10739. --| If File_Handle is not a valid access to a paginated file control
  10740. --| structure exception Invalid_File is raised.
  10741.  
  10742. --| N/A: Modifies
  10743.                                                     pragma Page;
  10744. procedure Clear_Odd_Header;
  10745.  
  10746. procedure Clear_Odd_Header(    --| Set the header text for the odd
  10747.                 --| pages to null lines
  10748.     File_Handle : in Paginated_File_Handle
  10749.                 --| Paginated file to be set 
  10750.                 --| with the header text
  10751.     );
  10752.  
  10753. --| Raises:
  10754. --| Invalid_File, Text_Overflow
  10755.  
  10756. --| Requires:
  10757. --| File_Handle is the access to the paginated file control structure
  10758. --| returned by Create_Paginated_File.
  10759.  
  10760. --| Effects:
  10761. --| The header text for odd pages of File_Handle is cleared to null.
  10762. --| Note that the replaced null header text will not be printed until
  10763. --| the next odd page of the output.
  10764.  
  10765. --| Errors:
  10766. --| If File_Handle is not a valid access to a paginated file control
  10767. --| structure exception Invalid_File is raised.
  10768.  
  10769. --| N/A: Modifies
  10770.                                                     pragma Page;
  10771. procedure Clear_Even_Header;
  10772.  
  10773. procedure Clear_Even_Header(    --| Set the header text for the even
  10774.                 --| pages to null lines
  10775.     File_Handle : in Paginated_File_Handle
  10776.                 --| Paginated file to be set 
  10777.                 --| with the header text
  10778.     );
  10779.  
  10780. --| Raises:
  10781. --| Invalid_File, Text_Overflow
  10782.  
  10783. --| Requires:
  10784. --| File_Handle is the access to the paginated file control structure
  10785. --| returned by Create_Paginated_File.
  10786.  
  10787. --| Effects:
  10788. --| The header text for even pages of File_Handle is cleared to null.
  10789. --| Note that the replaced null header text will not be printed until
  10790. --| the next even page of the output.
  10791.  
  10792. --| Errors:
  10793. --| If File_Handle is not a valid access to a paginated file control
  10794. --| structure exception Invalid_File is raised.
  10795.  
  10796. --| N/A: Modifies
  10797.                                                     pragma Page;
  10798. procedure Clear_Footer;
  10799.  
  10800. procedure Clear_Footer(        --| Set the footer text on a paginated
  10801.                 --| output file to null lines
  10802.     File_Handle : in Paginated_File_Handle
  10803.                 --| Paginated file to be set 
  10804.                 --| with the footer text
  10805.     );
  10806.  
  10807. --| Raises:
  10808. --| Invalid_File
  10809.  
  10810. --| Requires:
  10811. --| File_Handle is the access to the paginated file control structure
  10812. --| returned by Create_Paginated_File.
  10813.  
  10814. --| Effects:
  10815. --| The footer text of File_Handle is cleared to null lines.
  10816. --| The replaced null footer will not be printed until the next
  10817. --| page of the output.
  10818.  
  10819. --| Errors:
  10820. --| If File_Handle is not a valid access to a paginated file control
  10821. --| structure exception Invalid_File is raised.
  10822.  
  10823. --| N/A: Modifies
  10824.                                                     pragma Page;
  10825. procedure Clear_Odd_Footer;
  10826.  
  10827. procedure Clear_Odd_Footer(    --| Set the footer text for the odd
  10828.                 --| pages to null lines
  10829.     File_Handle : in Paginated_File_Handle
  10830.                 --| Paginated file to be set 
  10831.                 --| with the footer text
  10832.     );
  10833.  
  10834. --| Raises:
  10835. --| Invalid_File, Text_Overflow
  10836.  
  10837. --| Requires:
  10838. --| File_Handle is the access to the paginated file control structure
  10839. --| returned by Create_Paginated_File.
  10840.  
  10841. --| Effects:
  10842. --| The footer text for odd pages of File_Handle is cleared to null.
  10843. --| Note that the replaced null footer text will not be printed until
  10844. --| the next odd page of the output.
  10845.  
  10846. --| Errors:
  10847. --| If File_Handle is not a valid access to a paginated file control
  10848. --| structure exception Invalid_File is raised.
  10849.  
  10850. --| N/A: Modifies
  10851.                                                     pragma Page;
  10852. procedure Clear_Even_Footer;
  10853.  
  10854. procedure Clear_Even_Footer(    --| Set the footer text for the even
  10855.                 --| pages to null lines
  10856.     File_Handle : in Paginated_File_Handle
  10857.                 --| Paginated file to be set 
  10858.                 --| with the footer text
  10859.     );
  10860.  
  10861. --| Raises:
  10862. --| Invalid_File, Text_Overflow
  10863.  
  10864. --| Requires:
  10865. --| File_Handle is the access to the paginated file control structure
  10866. --| returned by Create_Paginated_File.
  10867.  
  10868. --| Effects:
  10869. --| The footer text for even pages of File_Handle is cleared to null.
  10870. --| Note that the replaced null footer text will not be printed until
  10871. --| the next even page of the output.
  10872.  
  10873. --| Errors:
  10874. --| If File_Handle is not a valid access to a paginated file control
  10875. --| structure exception Invalid_File is raised.
  10876.  
  10877. --| N/A: Modifies
  10878.                                                     pragma Page;
  10879. procedure Close_Paginated_File;
  10880.                                                     pragma Page;
  10881. procedure Close_Paginated_File(    --| Complete the last page and close
  10882.                 --| the paginated file.
  10883.     File_Handle : in out Paginated_File_Handle
  10884.                 --| The paginated file to be closed
  10885.     );
  10886.  
  10887. --| Raises:
  10888. --| Invalid_File, File_Not_Open
  10889.  
  10890. --| Requires:
  10891. --| File_Handle is the access to the paginated file control structure
  10892. --| returned by Create_Paginated_File.
  10893.  
  10894. --| Effects:
  10895. --| Completes the last page of output and closes the output file.
  10896.  
  10897. --| Errors:
  10898. --| If File_Handle is not a valid Paginated_File_Handle, the exception
  10899. --| Invalid_File is raised.  If an error occurs in closing the file,
  10900. --| File_Not_Open is raised.
  10901.  
  10902. --| N/A: Modifies
  10903.                                                     pragma Page;
  10904. procedure Put(
  10905.     Text        : in Variable_String_Array
  10906.     );
  10907.  
  10908. procedure Put(            --| Output a line on a paginated file
  10909.     File_Handle : in Paginated_File_Handle;
  10910.                 --| The paginated file to
  10911.                 --| output the text
  10912.     Text        : in Variable_String_Array
  10913.                 --| The text to be output.
  10914.     );
  10915.  
  10916. --| Raises:
  10917. --| Invalid_File, Output_Error
  10918.  
  10919. --| Requires:
  10920. --| File_Handle is the access to the paginated file control structure
  10921. --| returned by Create_Paginated_File.  Text is a string of 
  10922. --| characters to be written to the paginated output file.
  10923.  
  10924. --| Effects:
  10925. --| Outputs Text of text to File_Handle.  If Text is the first string of the
  10926. --| first line to be printed on a page, the page header is printed before
  10927. --| printing the text.  
  10928.  
  10929. --| Errors:
  10930. --| If File_Handle is not a valid, open Paginated_File_Handle,
  10931. --| the exception Invalid_File is raised.  If an error
  10932. --| occurs during output, Output_Error is raised.
  10933.  
  10934. --| N/A: Modifies
  10935.                                                     pragma Page;
  10936. procedure Put(
  10937.     Text        : in String_Pkg.String_Type
  10938.     );
  10939.  
  10940. procedure Put(            --| Output a line on a paginated file
  10941.     File_Handle : in Paginated_File_Handle;
  10942.                 --| The paginated file to
  10943.                 --| output the text
  10944.     Text        : in String_Pkg.String_Type
  10945.                 --| The text to be output.
  10946.     );
  10947.  
  10948. --| Raises:
  10949. --| Invalid_File, Output_Error
  10950.  
  10951. --| Requires:
  10952. --| File_Handle is the access to the paginated file control structure
  10953. --| returned by Create_Paginated_File.  Text is a string of 
  10954. --| characters to be written to the paginated output file.
  10955.  
  10956. --| Effects:
  10957. --| Outputs Text of text to File_Handle.  If Text is the first string of the
  10958. --| first line to be printed on a page, the page header is printed before
  10959. --| printing the text.
  10960.  
  10961. --| Errors:
  10962. --| If File_Handle is not a valid, open Paginated_File_Handle,
  10963. --| the exception Invalid_File is raised.  If an error
  10964. --| occurs during output, Output_Error is raised.
  10965.  
  10966. --| N/A: Modifies
  10967.                                                     pragma Page;
  10968. procedure Put(
  10969.     Text        : in string
  10970.     );
  10971.  
  10972. procedure Put(            --| Output a line on a paginated file
  10973.     File_Handle : in Paginated_File_Handle;
  10974.                 --| The paginated file to
  10975.                 --| output the text
  10976.     Text        : in string    --| The text to be output.
  10977.     );
  10978.  
  10979. --| Raises:
  10980. --| Invalid_File, Output_Error
  10981.  
  10982. --| Requires:
  10983. --| File_Handle is the access to the paginated file control structure
  10984. --| returned by Create_Paginated_File.  Text is a string of 
  10985. --| characters to be written to the paginated output file.
  10986.  
  10987. --| Effects:
  10988. --| Outputs Text of text to File_Handle.  If Text is the first string of the
  10989. --| first line to be printed on a page, the page header is printed before
  10990. --| printing the string.  
  10991.  
  10992. --| Errors:
  10993. --| If File_Handle is not a valid, open Paginated_File_Handle,
  10994. --| the exception Invalid_File is raised.  If an error
  10995. --| occurs during output, Output_Error is raised.
  10996.  
  10997. --| N/A: Modifies
  10998.                                                     pragma Page;
  10999. procedure Put(
  11000.     Text        : in character
  11001.     );
  11002.  
  11003. procedure Put(            --| Output a line on a paginated file
  11004.     File_Handle : in Paginated_File_Handle;
  11005.                 --| The paginated file to
  11006.                 --| output the text
  11007.     Text        : in character    --| The text to be output.
  11008.     );
  11009.  
  11010. --| Raises:
  11011. --| Invalid_File, Output_Error
  11012.  
  11013. --| Requires:
  11014. --| File_Handle is the access to the paginated file control structure
  11015. --| returned by Create_Paginated_File.  Text is a the characters to be
  11016. --| written to the paginated output file.
  11017.  
  11018. --| Effects:
  11019. --| Outputs Text of text to File_Handle.  If Text is the first character of the
  11020. --| first line to be printed on a page, the page header is printed before
  11021. --| printing the string.  
  11022.  
  11023. --| Errors:
  11024. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11025. --| the exception Invalid_File is raised.  If an error
  11026. --| occurs during output, Output_Error is raised.
  11027.  
  11028. --| N/A: Modifies
  11029.                                                     pragma Page;
  11030. procedure Space(
  11031.     Count       : in integer
  11032.     );
  11033.  
  11034. procedure Space(        --| Output a specified number of spaces
  11035.     File_Handle : in Paginated_File_Handle;
  11036.                 --| The paginated file to output the line
  11037.     Count       : in integer    --| Number of spaces
  11038.     );
  11039.  
  11040. --| Raises:
  11041. --| Invalid_File, Output_Error
  11042.  
  11043. --| Requires:
  11044. --| File_Handle is the access to the paginated file control structure
  11045. --| returned by Create_Paginated_File.  Count is the number of horizontal
  11046. --| spaces to be output.
  11047.  
  11048. --| Effects:
  11049. --| Output Count number of blanks to File_Handle.
  11050.  
  11051. --| Errors:
  11052. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11053. --| the exception Invalid_File is raised.  If an error
  11054. --| occurs during output, Output_Error is raised.
  11055.  
  11056. --| N/A: Modifies
  11057.                                                     pragma Page;
  11058. procedure Put_Line(
  11059.     Text_Line   : in Variable_String_Array
  11060.     );
  11061.  
  11062. procedure Put_Line(        --| Output a line on a paginated file
  11063.     File_Handle : in Paginated_File_Handle;
  11064.                 --| The paginated file to output the line
  11065.     Text_Line   : in Variable_String_Array
  11066.                 --| The line to be output.
  11067.     );
  11068.  
  11069. --| Raises:
  11070. --| Invalid_File, Output_Error
  11071.  
  11072. --| Requires:
  11073. --| File_Handle is the access to the paginated file control structure
  11074. --| returned by Create_Paginated_File.  Text_Line is a string of 
  11075. --| characters to be written to the paginated output file.
  11076.  
  11077. --| Effects:
  11078. --| Outputs Text_Line of text to File_Handle.  If Text_Line is the
  11079. --| first line to be printed on a page, the page header is printed
  11080. --| before the line.  If it is the last line on a page, the page
  11081. --| footer followed by a page terminator is written immediately
  11082. --| after the line is written.
  11083.  
  11084. --| Errors:
  11085. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11086. --| the exception Invalid_File is raised.  If an error
  11087. --| occurs during output, Output_Error is raised.
  11088.  
  11089. --| N/A: Modifies
  11090.                                                     pragma Page;
  11091. procedure Put_Line(
  11092.     Text_Line   : in String_Pkg.String_Type
  11093.     );
  11094.  
  11095. procedure Put_Line(        --| Output a line on a paginated file
  11096.     File_Handle : in Paginated_File_Handle;
  11097.                 --| The paginated file to
  11098.                 --| output the line
  11099.     Text_Line   : in String_Pkg.String_Type
  11100.                 --| The line to be output.
  11101.     );
  11102.  
  11103. --| Raises:
  11104. --| Invalid_File, Output_Error
  11105.  
  11106. --| Requires:
  11107. --| File_Handle is the access to the paginated file control structure
  11108. --| returned by Create_Paginated_File.  Text_Line is a string of 
  11109. --| characters to be written to the paginated output file.
  11110.  
  11111. --| Effects:
  11112. --| Outputs Text_Line of text to File_Handle.  If Text_Line is the
  11113. --| first line to be printed on a page, the page header is printed
  11114. --| before the line.  If it is the last line on a page, the page
  11115. --| footer followed by a page terminator is written immediately
  11116. --| after the line is written.
  11117.  
  11118. --| Errors:
  11119. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11120. --| the exception Invalid_File is raised.  If an error
  11121. --| occurs during output, Output_Error is raised.
  11122.  
  11123. --| N/A: Modifies
  11124.                                                     pragma Page;
  11125. procedure Put_Line(
  11126.     Text_Line   : in string
  11127.     );
  11128.  
  11129. procedure Put_Line(        --| Output a line on a paginated file
  11130.     File_Handle : in Paginated_File_Handle;
  11131.                 --| The paginated file to
  11132.                 --| output the line
  11133.     Text_Line   : in string    --| The line to be output.
  11134.     );
  11135.  
  11136. --| Raises:
  11137. --| Invalid_File, Output_Error
  11138.  
  11139. --| Requires:
  11140. --| File_Handle is the access to the paginated file control structure
  11141. --| returned by Create_Paginated_File.  Text_Line is a string of 
  11142. --| characters to be written to the paginated output file.
  11143.  
  11144. --| Effects:
  11145. --| Outputs Text_Line of text to File_Handle.  If Text_Line is the
  11146. --| first line to be printed on a page, the page header is printed
  11147. --| before the line.  If it is the last line on a page, the page
  11148. --| footer followed by a page terminator is written immediately
  11149. --| after the line is written.
  11150.  
  11151. --| Errors:
  11152. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11153. --| the exception Invalid_File is raised.  If an error
  11154. --| occurs during output, Output_Error is raised.
  11155.  
  11156. --| N/A: Modifies
  11157.                                                     pragma Page;
  11158. procedure Space_Line(
  11159.     Count       : in integer := 1
  11160.     );
  11161.  
  11162. procedure Space_Line(        --| Output one or more spaces on a
  11163.                 --| paginated file
  11164.     File_Handle : in Paginated_File_Handle;
  11165.                 --| The paginated file to 
  11166.                 --| output spaces
  11167.     Count       : in integer := 1
  11168.                 --| The number of spaces.
  11169.     );
  11170.  
  11171. --| Raises:
  11172. --| Invalid_File, Output_Error, Invalid_Count
  11173.  
  11174. --| Requires:
  11175. --| File_Handle is the access to the paginated file control structure
  11176. --| returned by Create_Paginated_File.  Count is the number of
  11177. --| spaces to be output to File_Handle.  If Count is omitted, 1 is
  11178. --| assumed.
  11179.  
  11180. --| Effects:
  11181. --| Count number of line terminators are output to File_Handle.
  11182. --| If Count is greater than the number of lines remaining on
  11183. --| the page, the page footer, a page terminator, and the page header
  11184. --| are written before the remainder of the spaces are output.
  11185. --| If the specified Count is less than equal to 0, no operation
  11186. --| takes place.
  11187.  
  11188. --| Errors:
  11189. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11190. --| the exception Invalid_File is raised.  If the requested space
  11191. --| count is greater than a predetermined amount, Invalid_Count
  11192. --| is raised.  If an error occurs during output, Output_Error
  11193. --| is raised.
  11194.  
  11195. --| N/A: Modifies
  11196.                                                     pragma Page;
  11197. procedure Skip_Line(
  11198.     Count       : in integer := 1
  11199.     );
  11200.  
  11201. procedure Skip_Line(        --| Output one or more spaces on a
  11202.                 --| paginated file
  11203.     File_Handle : in Paginated_File_Handle;
  11204.                 --| The paginated file to
  11205.                 --| output skips
  11206.     Count       : in integer := 1
  11207.                 --| The number of spaces.
  11208.     );
  11209.  
  11210. --| Raises:
  11211. --| Invalid_File, Output_Error, Invalid_Count
  11212.  
  11213. --| Requires:
  11214. --| File_Handle is the access to the paginated file control structure
  11215. --| returned by Create_Paginated_File.  Count is the number of
  11216. --| spaces to be output to File_Handle.  If Count is omitted, 1 is
  11217. --| assumed.
  11218.  
  11219. --| Effects:
  11220. --| Count number of line terminators are output to File_Handle.
  11221. --| If Count is greater than the number of lines remaining on
  11222. --| the page, the page footer is printed, a page terminator is
  11223. --| output and the remainder of the skips are NOT output.
  11224. --| If the specified Count is less than equal to 0, no operation
  11225. --| takes place.
  11226.  
  11227. --| Errors:
  11228. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11229. --| the exception Invalid_File is raised.  If the requested skip
  11230. --| count is greater than a predetermined amount, Invalid_Count
  11231. --| is raised.  If an error occurs during output, Output_Error
  11232. --| is raised.
  11233.  
  11234. --| N/A: Modifies
  11235.                                                     pragma Page;
  11236. procedure Put_Page(
  11237.     Count       : in integer := 1
  11238.     );
  11239.  
  11240. procedure Put_Page(        --| Output one or more page ejects
  11241.                 --| on a paginated file
  11242.     File_Handle : in Paginated_File_Handle;
  11243.                 --| The paginated file to
  11244.                 --| output page ejects
  11245.     Count       : in integer := 1
  11246.                 --| The number of pages.
  11247.     );
  11248.  
  11249. --| Raises:
  11250. --| Invalid_File, Output_Error, Invalid_Count
  11251.  
  11252. --| Requires:
  11253. --| File_Handle is the access to the paginated file control structure
  11254. --| returned by Create_Paginated_File.  Count is the number of
  11255. --| pages to be output to File_Handle.  If Count is omitted, 1 is
  11256. --| assumed.
  11257.  
  11258. --| Effects:
  11259. --| Outputs Count number of page ejects. The page footer and the page
  11260. --| header are printed as appropriate.
  11261. --| If the specified Count is less than equal to 0, no operation
  11262. --| takes place.
  11263.  
  11264. --| Errors:
  11265. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11266. --| the exception Invalid_File is raised.  If the requested page
  11267. --| count is greater than a predetermined amount, Invalid_Count
  11268. --| is raised.  If an error occurs during output, Output_Error
  11269. --| is raised.
  11270.  
  11271. --| N/A: Modifies
  11272.                                                     pragma Page;
  11273. function Available_Lines
  11274.     return integer;
  11275.  
  11276. function Available_Lines(    --| Query the number of lines that
  11277.                 --| are available on the current page
  11278.     File_Handle : in Paginated_File_Handle
  11279.                 --| The paginated file to be
  11280.                 --| queried for available lines
  11281.     ) return integer;
  11282.  
  11283. --| Raises:
  11284. --| Invalid_File
  11285.  
  11286. --| Requires:
  11287. --| File_Handle is the access to the paginated file control structure
  11288. --| returned by Create_Paginated_File.
  11289.  
  11290. --| Effects:
  11291. --| Return the number of lines (excluding the header and the footer
  11292. --| spaces) remaining on the current output page.
  11293.  
  11294. --| Errors:
  11295. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11296. --| the exception Invalid_File is raised.
  11297.  
  11298. --| N/A: Modifies
  11299.                                                     pragma Page;
  11300. procedure Reserve_Lines(
  11301.     Count       : in integer
  11302.     );
  11303.  
  11304. procedure Reserve_Lines(    --| Assure that there are at least
  11305.                 --| a specified number of contiguous
  11306.                 --| lines on a paginated file.
  11307.     File_Handle : in Paginated_File_Handle;
  11308.                 --| The paginated file to
  11309.                 --| reserve the lines
  11310.     Count       : in integer    --| The number of lines needed
  11311.     );
  11312.  
  11313. --| Raises :
  11314. --| Invalid_File, Page_Overflow
  11315.  
  11316. --| Requires:
  11317. --| File_Handle is the access to the paginated file control structure
  11318. --| returned by Create_Paginated_File.  Count is the number of
  11319. --| contiguous lines needed on File_Handle.
  11320.  
  11321. --| Effects:
  11322. --| If Count is greater than the number of lines remaining on
  11323. --| the page, Put_Page is executed to assure that there are Count
  11324. --| number of contiguous lines.
  11325. --| Specifying value less than or equal to 0 for Count will result
  11326. --| in no operation
  11327.  
  11328. --| Errors:
  11329. --| If File_Handle is not a valid, open Paginated_File_Handle,
  11330. --| the exception Invalid_File is raised.  If Count is greater than
  11331. --| the maximum number of lines available on a page as set by
  11332. --| Set_Page_Layout, exception Page_Overflow is raised and Put_Page
  11333. --| is NOT executed.
  11334.                                                     pragma Page;
  11335. private
  11336.                                                     pragma List(on);
  11337.     type Variable_String_Array_Handle is
  11338.     access Variable_String_Array;
  11339.                 --| Handle to array of variable length
  11340.                 --| strings
  11341.  
  11342.     type Paginated_File_Structure;
  11343.                 --| Data structure to store state of
  11344.                 --| the output file.
  11345.  
  11346.     type Paginated_File_Handle is
  11347.     access Paginated_File_Structure;
  11348.                 --| Handle to be passed around in a
  11349.                 --| program that uses paginated_output.
  11350.  
  11351.     type Paginated_File_Structure is
  11352.                 --| a structure to store state of
  11353.     record            --| the output file.
  11354.         access_count     : integer;
  11355.                 --| Number of accesses to this structure
  11356.         forward_link     : Paginated_File_Handle := null;
  11357.                 --| Access to next file structure
  11358.         reverse_link     : Paginated_File_Handle := null;
  11359.                 --| Access to previous file structure
  11360.         standard_flag    : boolean := false;
  11361.                 --| Standard output flag
  11362.         file_name        : String_Pkg.String_Type;
  11363.                 --| External file name
  11364.         file_reference   : Text_IO.File_Type;
  11365.                 --| External file reference
  11366.         output_mode      : Paginated_Output_Mode := OUTPUT;
  11367.                 --| Output mode (OUTPUT or ERROR)
  11368.         page_size        : integer;
  11369.                 --| The number of lines per page
  11370.         maximum_line     : integer;
  11371.                 --| The maximum number of text lines
  11372.         current_calendar : String_Pkg.String_Type;
  11373.                 --| Creation date (eg. March 15, 1985)
  11374.         current_date     : string (1 .. 8);
  11375.                 --| Creation date (eg. 03/15/85)
  11376.         current_time     : string (1 .. 8);
  11377.                 --| Creation time (eg. 15:24:07)
  11378.         current_page     : integer := 0;
  11379.                 --| The number of lines per page
  11380.         current_line     : integer := 0;
  11381.                 --| The number of lines used
  11382.         header_size      : integer;
  11383.                 --| Number of lines of header text
  11384.         odd_page_header  : Variable_String_Array_Handle := null;
  11385.                 --| Access to odd page header text
  11386.         even_page_header : Variable_String_Array_Handle := null;
  11387.                 --| Access to even page header text
  11388.         footer_size      : integer;
  11389.                 --| Number of lines of footer text
  11390.         odd_page_footer  : Variable_String_Array_Handle := null;
  11391.                 --| Access to odd page footer text
  11392.         even_page_footer : Variable_String_Array_Handle := null;
  11393.                 --| Access to even page footer text
  11394.     end record;
  11395.                                                     pragma List(on);
  11396. end  Paginated_Output;
  11397.                                                     pragma Page;
  11398. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11399. --PGFILE.BDY
  11400. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11401. with Text_IO;            use Text_IO;
  11402. with Calendar;            use Calendar;
  11403. with String_Pkg;        use String_Pkg;
  11404. with Unchecked_Deallocation;
  11405.  
  11406.  
  11407. package body Paginated_Output is
  11408.  
  11409.     package Int_IO is new Integer_IO(integer);
  11410.  
  11411.     type Odd_Even is (Odd, Even);
  11412.                 --| Odd/Even page indicator
  11413.  
  11414.     type Header_Footer is (Header,Footer);
  11415.                 --| Header/Footer selection
  11416.  
  11417.     type Kind_Of_Text is    --| Text selection switches
  11418.     record
  11419.         page: Odd_Even;
  11420.         text: Header_Footer;
  11421.     end record;
  11422.  
  11423.     Month_Name : constant Variable_String_Array(1 .. 12) :=
  11424.     ( 1 => Create("January"),
  11425.       2 => Create("February"), 
  11426.       3 => Create("March"), 
  11427.       4 => Create("April"), 
  11428.       5 => Create("May"), 
  11429.       6 => Create("June"), 
  11430.       7 => Create("July"), 
  11431.       8 => Create("August"), 
  11432.       9 => Create("September"), 
  11433.      10 => Create("October"), 
  11434.      11 => Create("November"), 
  11435.      12 => Create("December") );
  11436.  
  11437.     Paginated_Standard_Output : Paginated_File_Handle;
  11438.                                                     pragma Page;
  11439.     function Convert(
  11440.     Input_Number : in integer;
  11441.     Digit        : in integer := 0
  11442.     ) return string is
  11443.  
  11444. --|-Algorithm:
  11445. --| If integer value is negative or greater than 99
  11446. --|    then return null text
  11447. --| If input value is less than 10 (ie. single decimal digit)
  11448. --|    then concatenate 0 and character equivalent of the given value
  11449. --|    else convert value to character equivalent
  11450. --| Return converted text
  11451. --|+
  11452.  
  11453.     Temp_Text : string (1 .. 16);
  11454.     Index     : integer;
  11455.  
  11456.     begin
  11457.  
  11458.     if Digit > Temp_Text'last then
  11459.         return "";
  11460.     end if;
  11461.     Int_IO.Put(Temp_Text, Input_Number);
  11462.     if Digit <= 0 then
  11463.         Index := Temp_Text'last;
  11464.         for i in Temp_Text'range loop
  11465.         if Temp_Text(i) /= ' ' then
  11466.             Index := i;
  11467.             exit;
  11468.         end if;
  11469.         end loop;
  11470.     else
  11471.         Index := Temp_Text'last - Digit + 1;
  11472.         for i in Index .. Temp_Text'last loop
  11473.         if Temp_Text(i) = ' ' then
  11474.             Temp_Text(i) := '0';
  11475.         end if;
  11476.         end loop;
  11477.     end if;
  11478.     return Temp_Text(Index .. Temp_Text'last);
  11479.  
  11480.     end Convert;
  11481.                                                     pragma Page;
  11482.     procedure Set_Date_Time(
  11483.     File_Handle : in Paginated_File_Handle
  11484.     ) is
  11485.  
  11486. --|-Algorithm:
  11487. --| Get the current system date/time
  11488. --| Separate date/time into appropriate components
  11489. --| Calculate in terms of hours, minutes, and seconds
  11490. --| Set current date/time in the file structure
  11491. --| Set the current date in "English" (eg. January 1, 1985)
  11492. --|    in the file structure
  11493. --| Exit
  11494. --|+
  11495.  
  11496.     Clock_Value : Calendar.Time;
  11497.     Year        : Calendar.Year_Number;
  11498.     Month       : Calendar.Month_Number;
  11499.     Day         : Calendar.Day_Number;
  11500.     Duration    : Calendar.Day_Duration;
  11501.  
  11502.     begin
  11503.  
  11504.     Clock_Value := Calendar.Clock;
  11505.     Calendar.Split(Clock_Value, Year, Month, Day, Duration);
  11506.     File_Handle.current_date := Convert(integer(Month), 2) & "/"
  11507.                   & Convert(integer(Day), 2) & "/"
  11508.                   & Convert(integer(Year mod 100), 2);
  11509.     File_Handle.current_time := Convert(integer(Duration) / (60 * 60), 2) & ":"
  11510.                   & Convert((integer(Duration) mod (60 * 60)) / 60, 2) & ":"
  11511.                   & Convert(integer(Duration) mod 60, 2);
  11512.     String_Pkg.Mark;
  11513.     File_Handle.current_calendar := String_Pkg.Make_Persistent( 
  11514.                     Month_Name(integer(Month)) & 
  11515.                     integer'image(Day) &
  11516.                     "," &
  11517.                     integer'image(Year));
  11518.     String_Pkg.Release;
  11519.     return;
  11520.  
  11521.     end Set_Date_Time;
  11522.                                                     pragma Page;
  11523.     procedure Check_Valid(
  11524.     File_Handle : in Paginated_File_Handle
  11525.     ) is
  11526.  
  11527. --|-Algorithm:
  11528. --| If handle is null or external file name is null
  11529. --|    then raise an error
  11530. --| Exit
  11531. --|+
  11532.  
  11533.     begin
  11534.  
  11535.     if File_Handle = null then
  11536.         raise Invalid_File;
  11537.     end if;
  11538.     return;
  11539.  
  11540.     end Check_Valid;
  11541.                                                     pragma Page;
  11542.     procedure Clear_Text(
  11543.     Text_Handle : in Variable_String_Array_Handle
  11544.     ) is
  11545.  
  11546. --|-Algorithm:
  11547. --| If valid access to text array
  11548. --|    then return text array storage to the heap (access set to null)
  11549. --| Exit
  11550. --|+
  11551.  
  11552.     begin
  11553.  
  11554.     if Text_Handle /= null then
  11555.         for i in Text_Handle'range loop
  11556.         String_Pkg.Flush(Text_Handle(i));
  11557.         end loop;
  11558.     end if;
  11559.     return;
  11560.  
  11561.     end Clear_Text;
  11562.                                                     pragma Page;
  11563.     procedure Set_Text(
  11564.     File_Handle  : in Paginated_File_Handle;
  11565.     Text_String  : in Variable_String_Array;
  11566.     Text_Control : in Kind_Of_Text
  11567.     ) is
  11568.  
  11569. --|-Algorithm:
  11570. --| Validate paginated file structure (raise error if not valid)
  11571. --| If requested text array is too large
  11572. --|    then raise an error
  11573. --| Clear old text array
  11574. --| Set new text array with specified justification (top or bottom)
  11575. --| in the area as specified
  11576. --| Exit
  11577. --|+
  11578.  
  11579.     Text_Handle : Variable_String_Array_Handle;
  11580.     Text_Index  : integer;
  11581.     Text_Size   : integer;
  11582.     Handle      : Paginated_File_Handle;
  11583.  
  11584.     begin
  11585.     Check_Valid(File_Handle);
  11586.     Handle := File_Handle;
  11587.     loop
  11588.         exit when Handle = null;
  11589.         case Text_Control.text is
  11590.         when Header =>
  11591.             Text_Size := Handle.header_size;
  11592.             Text_Index := 1;
  11593.             case Text_Control.page is
  11594.             when Odd =>
  11595.                 Text_Handle := Handle.odd_page_header;
  11596.             when Even =>
  11597.                 Text_Handle := Handle.even_page_header;
  11598.             end case;
  11599.         when Footer =>
  11600.             Text_Size := Handle.footer_size;
  11601.             Text_Index := Text_Size - Text_String'last + 1;
  11602.             case Text_Control.page is
  11603.             when Odd =>
  11604.                 Text_Handle := Handle.odd_page_footer;
  11605.             when Even =>
  11606.                 Text_Handle := Handle.even_page_footer;
  11607.             end case;
  11608.         end case;
  11609.         if Text_Size < Text_String'last then
  11610.         raise Text_Overflow;
  11611.         end if;
  11612.         Clear_Text(Text_Handle);
  11613.         for i in Text_String'range loop
  11614.         Text_Handle(Text_Index) := String_Pkg.Make_Persistent(Text_String(i));
  11615.         Text_Index := Text_Index + 1;
  11616.         end loop;
  11617.         Handle := Handle.forward_link;
  11618.     end loop;
  11619.     return;
  11620.  
  11621.     end Set_Text;
  11622.                                                     pragma Page;
  11623.     function Tilde_Substitute(
  11624.     File_Handle : in Paginated_File_Handle;
  11625.     Input_Text : in String_Pkg.String_Type
  11626.     ) return string is
  11627.  
  11628. --|-Algorithm:
  11629. --| Set the length of the text in question
  11630. --| Clear the result string to null
  11631. --| Loop until all input characters are processed
  11632. --|    Fetch one character
  11633. --|    If the character is a tilde (~) 
  11634. --|       then bump input index and if past the end exit the loop
  11635. --|            Fetch the next character
  11636. --|            Based on this character substitute appropriately
  11637. --|        else add this to the output
  11638. --|     Bump input index and loop
  11639. --| Return the output (substituted) string
  11640. --| Exit
  11641. --|+
  11642.  
  11643.     Output_Text : String_Pkg.String_Type;
  11644.     S_Str       : String_Pkg.String_Type;
  11645.     Letter      : character;
  11646.     Index       : natural;
  11647.  
  11648.     begin
  11649.  
  11650.     S_Str := Input_Text;
  11651.     loop
  11652.         Index := String_Pkg.Match_C(S_Str, '~');
  11653.         if Index = 0 then
  11654.         Output_Text := Output_Text & S_Str;
  11655.         exit;
  11656.         end if;
  11657.         if Index > 1 then
  11658.         Output_Text := Output_Text & String_Pkg.Substr(S_Str, 1, Index - 1);
  11659.         end if;
  11660.         if Index < String_Pkg.Length(S_Str) then
  11661.         Letter := String_Pkg.Fetch(S_Str, Index + 1);
  11662.         else
  11663.         exit;
  11664.         end if;
  11665.         case Letter is
  11666.         when 'f' | 'F' =>
  11667.             Output_Text := Output_Text & File_Handle.file_name;
  11668.         when 'c' | 'C' =>
  11669.             Output_Text := Output_Text & File_Handle.current_calendar;
  11670.         when 'd' | 'D' =>
  11671.             Output_Text := Output_Text & File_Handle.current_date;
  11672.         when 't' | 'T' =>
  11673.             Output_Text := Output_Text & File_Handle.current_time;
  11674.         when 'p' | 'P' =>
  11675.             Output_Text := Output_Text & Convert(File_Handle.current_page, 0);
  11676.         when others    =>
  11677.             Output_Text := Output_Text & ("" & Letter);
  11678.         end case;
  11679.         Index := Index + 2;
  11680.         if Index > String_Pkg.Length(S_Str) then
  11681.         exit;
  11682.         end if;
  11683.         S_Str := String_Pkg.Substr(S_Str, Index, String_Pkg.Length(S_Str) - Index + 1);
  11684.     end loop;
  11685.         
  11686.     return String_Pkg.Value(Output_Text);
  11687.  
  11688.     end Tilde_Substitute;
  11689.                                                     pragma Page;
  11690.     procedure Put_Text(
  11691.     File_Handle  : in Paginated_File_Handle;
  11692.     Text_Control : in Kind_Of_Text
  11693.     ) is
  11694.  
  11695. --|-Algorithm:
  11696. --| If access to text array is null
  11697. --|    then write appropriate number of line terminators
  11698. --|         exit
  11699. --| Loop over the depth of the text array
  11700. --|    If text is null
  11701. --|       then write line terminator
  11702. --|       else resolve tilde substitution
  11703. --|            write a line of text followed by a line terminator
  11704. --| Exit
  11705. --|+
  11706.  
  11707.     Text_Handle : Variable_String_Array_Handle;
  11708.     Text_Size   : integer;
  11709.  
  11710.     begin
  11711.     case Text_Control.text is
  11712.         when Header =>
  11713.         if File_Handle.header_size = 0 then
  11714.             return;
  11715.         end if;
  11716.         Text_Size := File_Handle.header_size;
  11717.         if File_Handle.current_page mod 2 = 0 then
  11718.             Text_Handle := File_Handle.even_page_header;
  11719.         else
  11720.             Text_Handle := File_Handle.odd_page_header;
  11721.         end if;
  11722.         when Footer =>
  11723.         if File_Handle.footer_size = 0 then
  11724.             return;
  11725.         end if;
  11726.         Text_Size := File_Handle.footer_size;
  11727.         if File_Handle.current_page mod 2 = 0 then
  11728.             Text_Handle := File_Handle.even_page_footer;
  11729.         else
  11730.             Text_Handle := File_Handle.odd_page_footer;
  11731.         end if;
  11732.     end case;
  11733.     if Text_Handle = null then
  11734.         if String_Pkg.Equal(File_Handle.file_name, "") then
  11735.         if File_Handle.output_mode = OUTPUT then
  11736.             Text_IO.New_Line(Text_IO.Standard_Output,
  11737.                      Text_IO.Positive_Count(Text_Size));
  11738.         else
  11739.             Text_IO.New_Line(Text_IO.Current_Output,
  11740.                      Text_IO.Positive_Count(Text_Size));
  11741.         end if;
  11742.         else
  11743.         Text_IO.New_Line(File_Handle.file_reference,
  11744.                  Text_IO.Positive_Count(Text_Size));
  11745.         end if;
  11746.         return;
  11747.     end if;
  11748.     for i in 1 .. Text_Size loop
  11749.         String_Pkg.Mark;
  11750.         if String_Pkg.Is_Empty(Text_Handle(i)) then
  11751.             if String_Pkg.Equal(File_Handle.file_name, "") then
  11752.             if File_Handle.output_mode = OUTPUT then
  11753.             Text_IO.New_Line(Text_IO.Standard_Output, 1);
  11754.             else
  11755.             Text_IO.New_Line(Text_IO.Current_Output, 1);
  11756.             end if;
  11757.         else
  11758.             Text_IO.New_Line(File_Handle.file_reference, 1);
  11759.         end if;
  11760.         else
  11761.             if String_Pkg.Equal(File_Handle.file_name, "") then
  11762.             if File_Handle.output_mode = OUTPUT then
  11763.             Text_IO.Put_Line(Text_IO.Standard_Output,
  11764.                      Tilde_Substitute(File_Handle, Text_Handle(i)));
  11765.             else
  11766.             Text_IO.Put_Line(Text_IO.Current_Output,
  11767.                      Tilde_Substitute(File_Handle, Text_Handle(i)));
  11768.             end if;
  11769.         else
  11770.             Text_IO.Put_Line(File_Handle.file_reference,
  11771.                      Tilde_Substitute(File_Handle, Text_Handle(i)));
  11772.         end if;
  11773.         end if;
  11774.         String_Pkg.Release;
  11775.     end loop;
  11776.     return;
  11777.  
  11778.     end Put_Text;
  11779.                                                     pragma Page;
  11780.     procedure Free_Structure is
  11781.     new Unchecked_Deallocation(Paginated_File_Structure, Paginated_File_Handle);
  11782.  
  11783.     procedure Abort_Paginated_Output(
  11784.     File_Handle : in out Paginated_File_Handle
  11785.     ) is
  11786.  
  11787. --|-Algorithm:
  11788. --| If given handle is null
  11789. --|    return
  11790. --| Return header/footer text array storage to the heap
  11791. --| Close file
  11792. --| Return file structure storage to the heap
  11793. --| Exit
  11794. --|+        
  11795.  
  11796.     begin
  11797.     if File_Handle = null then
  11798.         return;
  11799.     end if;
  11800.     Clear_Text(File_Handle.odd_page_header);
  11801.     Clear_Text(File_Handle.even_page_header);
  11802.     Clear_Text(File_Handle.odd_page_footer);
  11803.     Clear_Text(File_Handle.even_page_footer);
  11804.     String_Pkg.Flush(File_Handle.current_calendar);
  11805.     if not String_Pkg.Equal(File_Handle.file_name, "") then
  11806.         String_Pkg.Flush(File_Handle.file_name);
  11807.         Text_IO.Close(File_Handle.file_reference);
  11808.     end if;
  11809.     Free_Structure(File_Handle);
  11810.     return;
  11811.  
  11812.     exception
  11813.  
  11814.     when Text_IO.Status_Error =>
  11815.         Free_Structure(File_Handle);
  11816.  
  11817.     end Abort_Paginated_Output;
  11818.                                                     pragma Page;
  11819.     procedure Line_Feed(
  11820.     File_Handle : in Paginated_File_Handle;
  11821.     Count       : in integer
  11822.     ) is
  11823.  
  11824. --|-Algorithm:
  11825. --| If at top of the page
  11826. --|    then write header 
  11827. --| If the request count is 0
  11828. --|    then return
  11829. --| If the request is greater than the remainder on the page
  11830. --|    then write remainder number of new lines
  11831. --|         decrement request by this amount
  11832. --|         write footer
  11833. --|         eject page and update page and line count
  11834. --|         if more space needed
  11835. --|            then recursively call self with count
  11836. --|    else write requested number of new lines
  11837. --|         update line count
  11838. --| Exit
  11839. --|+
  11840.  
  11841.     Skip_Count : integer;
  11842.     Text_Kind  : Kind_Of_Text;
  11843.  
  11844.     begin
  11845.  
  11846.     if File_Handle.current_line = 0 and File_Handle.page_size /= 0 then
  11847.         File_Handle.current_line := 1;
  11848.         File_Handle.current_page := File_Handle.current_page + 1;
  11849.         if String_Pkg.Equal(File_Handle.file_name, "") then
  11850.         if File_Handle.output_mode = OUTPUT then
  11851.             Text_IO.New_Page(Text_IO.Standard_Output);
  11852.         else
  11853.             Text_IO.New_Page(Text_IO.Current_Output);
  11854.         end if;
  11855.         else
  11856.         Text_IO.New_Page(File_Handle.file_reference);
  11857.         end if;
  11858.         Text_Kind.text := Header;
  11859.         Put_Text(File_Handle, Text_Kind);
  11860.     end if;
  11861.     if Count <= 0 then
  11862.         return;
  11863.     end if;
  11864.     Skip_Count := File_Handle.maximum_line - File_Handle.current_line + 1;
  11865.     if Count >= Skip_Count and File_Handle.page_size /= 0 then
  11866.         if String_Pkg.Equal(File_Handle.file_name, "") then
  11867.         if File_Handle.output_mode = OUTPUT then
  11868.             Text_IO.New_Line(Text_IO.Standard_Output,
  11869.                      Text_IO.Positive_Count(Skip_Count));
  11870.         else
  11871.             Text_IO.New_Line(Text_IO.Current_Output,
  11872.                      Text_IO.Positive_Count(Skip_Count));
  11873.         end if;
  11874.         else
  11875.         Text_IO.New_Line(File_Handle.file_reference,
  11876.                  Text_IO.Positive_Count(Skip_Count));
  11877.         end if;
  11878.         Skip_Count := Count - Skip_Count;
  11879.         Text_Kind.text := footer;
  11880.         Put_Text(File_Handle, Text_Kind);
  11881.         File_Handle.current_line := 0;
  11882.         if Skip_Count /= 0 then
  11883.         Line_Feed(File_Handle, Skip_Count);
  11884.         end if;
  11885.     else
  11886.         if String_Pkg.Equal(File_Handle.file_name, "") then
  11887.         if File_Handle.output_mode = OUTPUT then
  11888.             Text_IO.New_Line(Text_IO.Standard_Output,
  11889.                      Text_IO.Positive_Count(Count));
  11890.         else
  11891.             Text_IO.New_Line(Text_IO.Current_Output,
  11892.                      Text_IO.Positive_Count(Count));
  11893.         end if;
  11894.         else
  11895.         Text_IO.New_Line(File_Handle.file_reference,
  11896.                  Text_IO.Positive_Count(Count));
  11897.         end if;
  11898.         if File_Handle.page_size /= 0 then
  11899.         File_Handle.current_line := File_Handle.current_line + Count;
  11900.         end if;
  11901.     end if;
  11902.     return;
  11903.  
  11904.     end Line_Feed;
  11905.                                                     pragma Page;
  11906.     procedure Page_Eject(
  11907.     File_Handle : in Paginated_File_Handle;
  11908.     Count       : in integer := 1
  11909.     ) is
  11910.  
  11911. --|-Algorithm:
  11912. --| Validate paginated file structure (raise error if not valid)
  11913. --| Raise Invalid_Count if page request is too large
  11914. --| Convert the number of pages to skip into number of lines  
  11915. --| Write out this number of new line control characters
  11916. --| while taking into account header, footer, and pagination.
  11917. --| Exit
  11918. --|+
  11919.  
  11920.     begin
  11921.  
  11922.     if File_Handle.page_size = 0 then
  11923.         Line_Feed(File_Handle, 1);
  11924.         return;
  11925.     end if;
  11926.     if Count > 99 then
  11927.         raise Invalid_Count;
  11928.     end if;
  11929.     if File_Handle.current_line = 0 then
  11930.         Line_Feed(File_Handle,
  11931.         (Count * File_Handle.maximum_line));
  11932.     else
  11933.         Line_Feed(File_Handle,
  11934.         (Count * File_Handle.maximum_line - File_Handle.current_line + 1));
  11935.     end if;
  11936.     return;
  11937.  
  11938.     end Page_Eject;
  11939.                                                     pragma Page;
  11940.     procedure Set_Text_Area(
  11941.     Text_Handle : in out Variable_String_Array_Handle;
  11942.     Area_Size   : in     integer
  11943.     ) is
  11944.  
  11945.     Temp_Handle : Variable_String_Array_Handle;
  11946.  
  11947.     begin
  11948.  
  11949.     if Area_Size <= 0 then
  11950.         return;
  11951.     end if;
  11952.     if Text_Handle = null or else
  11953.        Text_Handle'last < Area_Size then
  11954.         Temp_Handle := Text_Handle;
  11955.         Text_Handle := new Variable_String_Array (1 .. Area_Size);
  11956.         if Temp_Handle /= null then
  11957.         for i in Temp_Handle'range loop
  11958.             Text_Handle(i) := String_Pkg.Make_Persistent(Temp_Handle(i));
  11959.         end loop;
  11960.         Clear_Text(Temp_Handle);
  11961.         end if;
  11962.       end if;
  11963.  
  11964.     end Set_Text_Area;
  11965.                                                     pragma Page;
  11966.     procedure Write(
  11967.     File_Handle : in Paginated_File_Handle;
  11968.     Text_Line   : in string;
  11969.     Feed        : in boolean
  11970.     ) is
  11971.  
  11972. --|-Algorithm:
  11973. --| Validate paginated file structure (raise error if not valid)
  11974. --| If at the top of the page
  11975. --|    then write out the header
  11976. --| Output the given line of text to the paginated file
  11977. --| Write out a new line control character
  11978. --| If at the bottom of the page
  11979. --|    then write out the footer and eject the page
  11980. --| Exit
  11981. --|+
  11982.  
  11983.     Handle : Paginated_File_Handle;
  11984.  
  11985.     begin
  11986.  
  11987.     Check_Valid(File_Handle);
  11988.     Handle := File_Handle;
  11989.     loop
  11990.         exit when Handle = null;
  11991.         Line_Feed(Handle, 0);
  11992.         if String_Pkg.Equal(Handle.file_name, "") then
  11993.         if Handle.output_mode = OUTPUT then
  11994.             Text_IO.Put(Text_IO.Standard_Output, Text_Line);
  11995.         else
  11996.             Text_IO.Put(Text_IO.Current_Output, Text_Line);
  11997.         end if;
  11998.         else
  11999.         Text_IO.Put(Handle.file_reference, Text_Line);
  12000.         end if;
  12001.         if Feed then
  12002.         Line_Feed(Handle, 1);
  12003.         end if;
  12004.         Handle := Handle.forward_link;
  12005.     end loop;
  12006.     return;
  12007.  
  12008.     end Write;
  12009.                                                     pragma Page;
  12010.     procedure Create_Paginated_File(
  12011.     File_Name   : in Host_File_Name             := "";
  12012.     File_Handle : in out Paginated_File_Handle;
  12013.     Page_Size   : in integer                    := 66;
  12014.     Header_Size : in integer                    := 6;
  12015.     Footer_Size : in integer                    := 6;
  12016.     Output_Mode : in Paginated_Output_Mode      := OUTPUT
  12017.     ) is
  12018.  
  12019. --|-Algorithm:
  12020. --| If an active (ie. non-null) handle is given
  12021. --|    then close that file first
  12022. --| Create a paginated file structure
  12023. --| If no file name is given
  12024. --|    then assume standard output
  12025. --|    else create (open) an external file 
  12026. --| Fill the paginated file structure with external file information,
  12027. --| page layout information, and current date/time
  12028. --| Return access to the completed structure
  12029. --| Exit
  12030. --|+
  12031.  
  12032.     begin
  12033.  
  12034.     Close_Paginated_File(File_Handle);
  12035.     File_Handle := new Paginated_File_Structure;
  12036.     if File_Name /= "" then
  12037.         File_Handle.file_name := String_Pkg.Make_Persistent(File_Name);
  12038.         Text_IO.Create(File => File_Handle.file_reference,
  12039.                Name => File_Name);
  12040.     end if;
  12041.     Set_Page_Layout(File_Handle, Page_Size, Header_Size, Footer_Size);
  12042.     Set_Date_Time(File_Handle);
  12043.     File_Handle.output_mode := Output_Mode;
  12044.     File_Handle.access_count := 1;
  12045.     return;
  12046.  
  12047.     exception
  12048.  
  12049.     when Text_IO.Status_Error =>
  12050.         Abort_Paginated_Output(File_Handle);
  12051.         raise File_Already_Open;
  12052.     when Text_IO.Name_Error | Text_IO.Use_Error =>
  12053.         Abort_Paginated_Output(File_Handle);
  12054.         raise File_Error;
  12055.     when Page_Layout_Error =>
  12056.         Abort_Paginated_Output(File_Handle);
  12057.         raise Page_Layout_Error;
  12058.  
  12059.     end Create_Paginated_File;
  12060.                                                     pragma Page;
  12061.     procedure Set_Standard_Paginated_File(
  12062.     File_Name   : in Host_File_Name;
  12063.     Page_Size   : in integer;
  12064.     Header_Size : in integer;
  12065.     Footer_Size : in integer
  12066.     ) is
  12067.  
  12068.     begin
  12069.  
  12070.     Create_Paginated_File(File_Name,
  12071.                   Paginated_Standard_Output,
  12072.                   Page_Size,
  12073.                   Header_Size,
  12074.                   Footer_Size);
  12075.     Paginated_Standard_Output.standard_flag := true;
  12076.  
  12077.     end Set_Standard_Paginated_File;
  12078.                                                     pragma Page;
  12079.     procedure Duplicate_Paginated_File(
  12080.     Old_Handle : in Paginated_File_Handle;
  12081.     New_Handle : in out Paginated_File_Handle
  12082.     ) is
  12083.  
  12084. --|-Algorithm:
  12085. --| Close file refered to by the handle to which the existing handle
  12086. --| is to be copied (if such file exists)
  12087. --| Duplicate the handle
  12088. --| Exit
  12089. --|+
  12090.  
  12091.     begin
  12092.  
  12093.     Close_Paginated_File(New_Handle);
  12094.     Old_Handle.access_count := Old_Handle.access_count + 1;
  12095.     New_Handle := Old_Handle;
  12096.     return;
  12097.  
  12098.     end Duplicate_Paginated_File;
  12099.                                                     pragma Page;
  12100.     procedure Set_Page_Layout(
  12101.     Page_Size   : in integer;
  12102.     Header_Size : in integer;
  12103.     Footer_Size : in integer
  12104.     ) is
  12105.  
  12106.     begin
  12107.  
  12108.     Set_Page_Layout(Paginated_Standard_Output,
  12109.             Page_Size,
  12110.             Header_Size,
  12111.             Footer_Size);
  12112.  
  12113.     end Set_Page_Layout;
  12114.                                                     pragma Page;
  12115.     procedure Set_Page_Layout(
  12116.     File_Handle : in Paginated_File_Handle;
  12117.     Page_Size   : in integer;
  12118.     Header_Size : in integer;
  12119.     Footer_Size : in integer
  12120.     ) is
  12121.  
  12122. --|-Algorithm:
  12123. --| Validate paginated file structure (raise error if not valid)
  12124. --| If page layout is contradictory
  12125. --|    then raise an error
  12126. --| If not at the top of the page
  12127. --|    then eject current page
  12128. --| Set page size, header size, footer size, and text area size
  12129. --| per page
  12130. --| Exit
  12131. --|+
  12132.  
  12133.     Temp_Handle : Variable_String_Array_Handle;
  12134.  
  12135.     begin
  12136.  
  12137.     Check_Valid(File_Handle);
  12138.     if Page_Size < 0 or Header_Size < 0 or Footer_Size < 0 or
  12139.        (Page_Size /= 0 and Page_Size <= Header_Size + Footer_Size) then
  12140.         raise Page_Layout_Error;
  12141.         return;
  12142.     end if;
  12143.     if File_Handle.current_line /= 0 and File_Handle.page_size /= 0 then
  12144.         Page_Eject(File_Handle, 1);
  12145.     end if;
  12146.     File_Handle.page_size := Page_Size;
  12147.     if Page_Size = 0 then
  12148.         File_Handle.maximum_line := 0;
  12149.     else
  12150.         File_Handle.maximum_line := Page_Size - (Header_Size + Footer_Size);
  12151.     end if;
  12152.     File_Handle.header_size := Header_Size;
  12153.     Set_Text_Area(File_Handle.odd_page_header, File_Handle.header_size);
  12154.     Set_Text_Area(File_Handle.even_page_header, File_Handle.header_size);
  12155.     File_Handle.footer_size := Footer_Size;
  12156.     Set_Text_Area(File_Handle.odd_page_footer, File_Handle.footer_size);
  12157.     Set_Text_Area(File_Handle.even_page_footer, File_Handle.footer_size);
  12158.     return;
  12159.  
  12160.     end Set_Page_Layout;
  12161.                                                     pragma Page;
  12162.     procedure Link_Paginated_File(
  12163.     File_Handle1 : in Paginated_File_Handle;
  12164.     File_Handle2 : in Paginated_File_Handle
  12165.     ) is
  12166.  
  12167.     begin
  12168.  
  12169.     Check_Valid(File_Handle1);
  12170.     Check_Valid(File_Handle2);
  12171.     if File_Handle1.forward_link = null and
  12172.        File_Handle2.reverse_link = null then
  12173.         File_Handle1.forward_link := File_Handle2;
  12174.         File_Handle2.reverse_link := File_Handle1;
  12175.         return; 
  12176.     end if;
  12177.  
  12178.     raise Files_Already_Linked;
  12179.         
  12180.     end Link_Paginated_File;
  12181.                                                     pragma Page;
  12182.     procedure Unlink_Paginated_File(
  12183.     File_Handle : in Paginated_File_Handle
  12184.     ) is
  12185.  
  12186.     begin
  12187.  
  12188.     Check_Valid(File_Handle);
  12189.     if File_Handle.reverse_link /= null then
  12190.         File_Handle.reverse_link.forward_link := File_Handle.forward_link;
  12191.         File_Handle.reverse_link := null;
  12192.     end if;
  12193.     if File_Handle.forward_link /= null then
  12194.         File_Handle.forward_link.reverse_link := File_Handle.reverse_link;
  12195.         File_Handle.forward_link := null;
  12196.     end if;
  12197.     return;    
  12198.  
  12199.     end Unlink_Paginated_File;
  12200.                                                     pragma Page;
  12201.     procedure Set_Header(
  12202.     Header_Text : in Variable_String_Array
  12203.     ) is
  12204.  
  12205.     begin
  12206.     Set_Header(Paginated_Standard_Output,
  12207.            Header_Text);
  12208.  
  12209.     end Set_Header;
  12210.                                                 pragma Page;
  12211.     procedure Set_Header(
  12212.     File_Handle : in Paginated_File_Handle;
  12213.     Header_Text : in Variable_String_Array
  12214.     ) is
  12215.  
  12216. --|-Algorithm:
  12217. --| Set given header text as odd page header 
  12218. --| Set given header text as even page header 
  12219. --| Exit
  12220. --|+
  12221.  
  12222.     begin
  12223.  
  12224.     Set_Text(File_Handle, Header_Text, (Odd, Header));
  12225.     Set_Text(File_Handle, Header_Text, (Even, Header));
  12226.     return;
  12227.  
  12228.     end Set_Header;
  12229.                                                     pragma Page;
  12230.     procedure Set_Header(
  12231.     Header_Line : in integer;
  12232.     Header_Text : in String_Pkg.String_Type
  12233.     ) is
  12234.  
  12235.     begin
  12236.  
  12237.     Set_Header(Paginated_Standard_Output,
  12238.            Header_Line,
  12239.            Header_Text);
  12240.  
  12241.     end Set_Header;
  12242.                                                     pragma Page;
  12243.     procedure Set_Header(
  12244.     File_Handle : in Paginated_File_Handle;
  12245.     Header_Line : in integer;
  12246.     Header_Text : in String_Pkg.String_Type
  12247.     ) is
  12248.  
  12249. --|-Algorithm:
  12250. --| Set odd page header
  12251. --| Set even page header
  12252. --| Exit
  12253. --|+
  12254.  
  12255.     begin
  12256.  
  12257.     Set_Odd_Header(File_Handle, Header_Line, Header_Text);
  12258.     Set_Even_Header(File_Handle, Header_Line, Header_Text);
  12259.     return;
  12260.  
  12261.     end Set_Header;
  12262.                                                     pragma Page;
  12263.     procedure Set_Header(
  12264.     Header_Line : in integer;
  12265.     Header_Text : in string
  12266.     ) is
  12267.  
  12268.     begin
  12269.  
  12270.     Set_Header(Paginated_Standard_Output,
  12271.            Header_Line,
  12272.            Header_Text);
  12273.  
  12274.     end Set_Header;
  12275.                                                     pragma Page;
  12276.     procedure Set_Header(
  12277.     File_Handle : in Paginated_File_Handle;
  12278.     Header_Line : in integer;
  12279.     Header_Text : in string
  12280.     ) is
  12281.  
  12282. --|-Algorithm:
  12283. --| Create a variable string
  12284. --| Set odd page header
  12285. --| Set even page header
  12286. --| Exit
  12287. --|+
  12288.  
  12289.     Text : String_Pkg.String_Type;
  12290.  
  12291.     begin
  12292.  
  12293.     Text :=    String_Pkg.Make_Persistent(Header_Text);
  12294.     Set_Odd_Header(File_Handle, Header_Line, Text);
  12295.     Set_Even_Header(File_Handle, Header_Line, Text);
  12296.     String_Pkg.Flush(Text);
  12297.     return;
  12298.  
  12299.     end Set_Header;
  12300.                                                     pragma Page;
  12301.     procedure Set_Odd_Header(
  12302.     Header_Text : in Variable_String_Array
  12303.     ) is
  12304.  
  12305.     begin
  12306.  
  12307.     Set_Odd_Header(Paginated_Standard_Output,
  12308.                Header_Text);
  12309.  
  12310.     end Set_Odd_Header;
  12311.                                                     pragma Page;
  12312.     procedure Set_Odd_Header(
  12313.     File_Handle : in Paginated_File_Handle;
  12314.     Header_Text : in Variable_String_Array
  12315.     ) is
  12316.  
  12317. --|-Algorithm:
  12318. --| Set given header text as odd page header 
  12319. --| Exit
  12320. --|+
  12321.  
  12322.     begin
  12323.  
  12324.     Set_Text(File_Handle, Header_Text, (Odd, Header));
  12325.     return;
  12326.  
  12327.     end Set_Odd_Header;
  12328.                                                     pragma Page;
  12329.     procedure Set_Odd_Header(
  12330.     Header_Line : in integer;
  12331.     Header_Text : in String_Pkg.String_Type
  12332.     ) is
  12333.  
  12334.     begin
  12335.  
  12336.     Set_Odd_Header(Paginated_Standard_Output,
  12337.                Header_Line,
  12338.                Header_Text);
  12339.  
  12340.     end Set_Odd_Header;
  12341.                                                     pragma Page;
  12342.     procedure Set_Odd_Header(
  12343.     File_Handle : in Paginated_File_Handle;
  12344.     Header_Line : in integer;
  12345.     Header_Text : in String_Pkg.String_Type
  12346.     ) is
  12347.  
  12348. --|-Algorithm:
  12349. --| Validate paginated file structure (raise error if not valid)
  12350. --| If requested header line number is out of range
  12351. --|     then raise an error
  12352. --| Set header text at requested line for odd pages
  12353. --| Exit
  12354. --|+
  12355.  
  12356.     begin
  12357.  
  12358.     Check_Valid(File_Handle);
  12359.     if Header_Line < 1 then
  12360.         raise Text_Underflow;
  12361.     end if;
  12362.     if Header_Line > File_Handle.header_size then
  12363.         raise Text_Overflow;
  12364.     end if;
  12365.     File_Handle.odd_page_header(Header_Line) := String_Pkg.Make_Persistent(Header_Text);
  12366.     return;
  12367.  
  12368.     end Set_Odd_Header;
  12369.                                                     pragma Page;
  12370.     procedure Set_Odd_Header(
  12371.     Header_Line : in integer;
  12372.     Header_Text : in string
  12373.     ) is
  12374.  
  12375.     begin
  12376.  
  12377.     Set_Odd_Header(Paginated_Standard_Output,
  12378.                Header_Line,
  12379.                Header_Text);
  12380.  
  12381.     end Set_Odd_Header;
  12382.                                                     pragma Page;
  12383.     procedure Set_Odd_Header(
  12384.     File_Handle : in Paginated_File_Handle;
  12385.     Header_Line : in integer;
  12386.     Header_Text : in string
  12387.     ) is
  12388.  
  12389. --|-Algorithm:
  12390. --| Create a variable string
  12391. --| Set odd page header
  12392. --| Exit
  12393. --|+
  12394.  
  12395.     Text : String_Pkg.String_Type;
  12396.  
  12397.     begin
  12398.  
  12399.     Text := String_Pkg.Make_Persistent(Header_Text);
  12400.     Set_Odd_Header(File_Handle, Header_Line, Text);
  12401.     String_Pkg.Flush(Text);
  12402.     return;
  12403.  
  12404.     end Set_Odd_Header;
  12405.                                                     pragma Page;
  12406.     procedure Set_Even_Header(
  12407.     Header_Text : in Variable_String_Array
  12408.     ) is
  12409.  
  12410.     begin
  12411.  
  12412.     Set_Even_Header(Paginated_Standard_Output,
  12413.             Header_Text);
  12414.  
  12415.     end Set_Even_Header;
  12416.                                                     pragma Page;
  12417.     procedure Set_Even_Header(
  12418.     File_Handle : in Paginated_File_Handle;
  12419.     Header_Text : in Variable_String_Array
  12420.     ) is
  12421.  
  12422. --|-Algorithm:
  12423. --| Set given header text as even page header 
  12424. --| Exit
  12425. --|+
  12426.  
  12427.     begin
  12428.  
  12429.     Set_Text(File_Handle, Header_Text, (Even, Header));
  12430.     return;
  12431.  
  12432.     end Set_Even_Header;
  12433.                                                     pragma Page;
  12434.     procedure Set_Even_Header(
  12435.     Header_Line : in integer;
  12436.     Header_Text : in String_Pkg.String_Type
  12437.     ) is
  12438.  
  12439.     begin
  12440.  
  12441.     Set_Even_Header(Paginated_Standard_Output,
  12442.             Header_Line,
  12443.             Header_Text);
  12444.  
  12445.     end Set_Even_Header;
  12446.                                                     pragma Page;
  12447.     procedure Set_Even_Header(
  12448.     File_Handle : in Paginated_File_Handle;
  12449.     Header_Line : in integer;
  12450.     Header_Text : in String_Pkg.String_Type
  12451.     ) is
  12452.  
  12453. --|-Algorithm:
  12454. --| Validate paginated file structure (raise error if not valid)
  12455. --| If requested header line number is out of range
  12456. --|     then raise an error
  12457. --| Set header text at requested line for even pages
  12458. --| Exit
  12459. --|+
  12460.  
  12461.     begin
  12462.  
  12463.     Check_Valid(File_Handle);
  12464.     if Header_Line < 1 then 
  12465.         raise Text_Underflow;
  12466.     end if;
  12467.     if Header_Line > File_Handle.header_size then
  12468.         raise Text_Overflow;
  12469.     end if;
  12470.     String_Pkg.Flush(File_Handle.even_page_header(Header_Line));
  12471.     File_Handle.even_page_header(Header_Line) := String_Pkg.Make_Persistent(Header_Text);
  12472.     return;
  12473.  
  12474.     end Set_Even_Header;
  12475.                                                     pragma Page;
  12476.     procedure Set_Even_Header(
  12477.     Header_Line : in integer;
  12478.     Header_Text : in string
  12479.     ) is
  12480.  
  12481.     begin
  12482.  
  12483.     Set_Even_Header(Paginated_Standard_Output,
  12484.             Header_Line,
  12485.             Header_Text);
  12486.  
  12487.     end Set_Even_Header;
  12488.                                                     pragma Page;
  12489.     procedure Set_Even_Header(
  12490.     File_Handle : in Paginated_File_Handle;
  12491.     Header_Line : in integer;
  12492.     Header_Text : in string
  12493.     ) is
  12494.  
  12495. --|-Algorithm:
  12496. --| Create a variable string
  12497. --| Set even page header
  12498. --| Exit
  12499. --|+
  12500.  
  12501.     Text : String_Pkg.String_Type;
  12502.  
  12503.     begin
  12504.  
  12505.     Text :=    String_Pkg.Make_Persistent(Header_Text);
  12506.     Set_Even_Header(File_Handle, Header_Line, Text);
  12507.     String_Pkg.Flush(Text);
  12508.     return;
  12509.  
  12510.     end Set_Even_Header;
  12511.                                                     pragma Page;
  12512.     procedure Set_Footer(
  12513.     Footer_Text : in Variable_String_Array
  12514.     ) is
  12515.  
  12516.     begin
  12517.  
  12518.     Set_Footer(Paginated_Standard_Output,
  12519.            Footer_Text);
  12520.  
  12521.     end Set_Footer;
  12522.                                                     pragma Page;
  12523.     procedure Set_Footer(
  12524.     File_Handle : in Paginated_File_Handle;
  12525.     Footer_Text : in Variable_String_Array
  12526.     ) is
  12527.  
  12528. --|-Algorithm:
  12529. --| Set given footer text as odd page header 
  12530. --| Set given footer text as even page header 
  12531. --| Exit
  12532. --|+
  12533.  
  12534.     begin
  12535.  
  12536.     Set_Text(File_Handle, Footer_Text, (Odd, Footer));
  12537.     Set_Text(File_Handle, Footer_Text, (Even, Footer));
  12538.     return;
  12539.  
  12540.     end Set_Footer;
  12541.                                                     pragma Page;
  12542.     procedure Set_Footer(
  12543.     Footer_Line : in integer;
  12544.     Footer_Text : in String_Pkg.String_Type
  12545.     ) is
  12546.  
  12547.     begin
  12548.  
  12549.     Set_Footer(Paginated_Standard_Output,
  12550.            Footer_Line,
  12551.            Footer_Text);
  12552.  
  12553.     end Set_Footer;
  12554.                                                     pragma Page;
  12555.     procedure Set_Footer(
  12556.     File_Handle : in Paginated_File_Handle;
  12557.     Footer_Line : in integer;
  12558.     Footer_Text : in String_Pkg.String_Type
  12559.     ) is
  12560.  
  12561. --|-Algorithm:
  12562. --| Set odd page footer
  12563. --| Set even page footer
  12564. --| Exit
  12565. --|+
  12566.  
  12567.     begin
  12568.  
  12569.     Set_Odd_Footer(File_Handle, Footer_Line, Footer_Text);
  12570.     Set_Even_Footer(File_Handle, Footer_Line, Footer_Text);
  12571.     return;
  12572.  
  12573.     end Set_Footer;
  12574.                                                     pragma Page;
  12575.     procedure Set_Footer(
  12576.     Footer_Line : in integer;
  12577.     Footer_Text : in string
  12578.     ) is
  12579.  
  12580.     begin
  12581.  
  12582.     Set_Footer(Paginated_Standard_Output,
  12583.            Footer_Line,
  12584.            Footer_Text);
  12585.  
  12586.     end Set_Footer;
  12587.                                                     pragma Page;
  12588.     procedure Set_Footer(
  12589.     File_Handle : in Paginated_File_Handle;
  12590.     Footer_Line : in integer;
  12591.     Footer_Text : in string
  12592.     ) is
  12593.  
  12594. --|-Algorithm:
  12595. --| Create a variable string
  12596. --| Set odd page footer
  12597. --| Set even page footer
  12598. --| Exit
  12599. --|+
  12600.  
  12601.     Text : String_Pkg.String_Type;
  12602.  
  12603.     begin
  12604.  
  12605.     Text := String_Pkg.Make_Persistent(Footer_Text);
  12606.     Set_Odd_Footer(File_Handle, Footer_Line, Text);
  12607.     Set_Even_Footer(File_Handle, Footer_Line, Text);
  12608.     String_Pkg.Flush(Text);
  12609.     return;
  12610.  
  12611.     end Set_Footer;
  12612.                                                     pragma Page;
  12613.     procedure Set_Odd_Footer(
  12614.     Footer_Text : in Variable_String_Array
  12615.     ) is
  12616.  
  12617.     begin
  12618.  
  12619.     Set_Odd_Footer(Paginated_Standard_Output,
  12620.                Footer_Text);
  12621.  
  12622.     end Set_Odd_Footer;
  12623.                                                                                pragma Page;
  12624.     procedure Set_Odd_Footer(
  12625.     File_Handle : in Paginated_File_Handle;
  12626.     Footer_Text : in Variable_String_Array
  12627.     ) is
  12628.  
  12629. --|-Algorithm:
  12630. --| Set given footer text as odd page header 
  12631. --| Exit
  12632. --|+
  12633.  
  12634.     begin
  12635.  
  12636.     Set_Text(File_Handle, Footer_Text, (Odd, Footer));
  12637.     return;
  12638.  
  12639.     end Set_Odd_Footer;
  12640.                                                     pragma Page;
  12641.     procedure Set_Odd_Footer(
  12642.     Footer_Line : in integer;
  12643.     Footer_Text : in String_Pkg.String_Type
  12644.     ) is
  12645.  
  12646.     begin
  12647.  
  12648.     Set_Odd_Footer(Paginated_Standard_Output,
  12649.                Footer_Line,
  12650.                Footer_Text);
  12651.  
  12652.     end Set_Odd_Footer;
  12653.                                                                 pragma Page;
  12654.     procedure Set_Odd_Footer(
  12655.     File_Handle : in Paginated_File_Handle;
  12656.     Footer_Line : in integer;
  12657.     Footer_Text : in String_Pkg.String_Type
  12658.     ) is
  12659.  
  12660. --|-Algorithm:
  12661. --| Validate paginated file structure (raise error if not valid)
  12662. --| If requested footer line number is out of range
  12663. --|     then raise an error
  12664. --| Set footer text at requested line for odd pages
  12665. --| Exit
  12666. --|+
  12667.  
  12668.     begin
  12669.  
  12670.     Check_Valid(File_Handle);
  12671.     if Footer_Line < 1 then 
  12672.         raise Text_Underflow;
  12673.     end if;
  12674.     if Footer_Line > File_Handle.footer_size then
  12675.         raise Text_Overflow;
  12676.     end if;
  12677.     String_Pkg.Flush(File_Handle.odd_page_footer(Footer_Line));
  12678.     File_Handle.odd_page_footer(Footer_Line) := String_Pkg.Make_Persistent(Footer_Text);
  12679.     return;
  12680.  
  12681.     end Set_Odd_Footer;
  12682.                                                     pragma Page;
  12683.     procedure Set_Odd_Footer(
  12684.     Footer_Line : in integer;
  12685.     Footer_Text : in string
  12686.     ) is
  12687.  
  12688.     begin
  12689.  
  12690.     Set_Odd_Footer(Paginated_Standard_Output,
  12691.                Footer_Line,
  12692.                Footer_Text);
  12693.  
  12694.     end Set_Odd_Footer;
  12695.                                                     pragma Page;
  12696.     procedure Set_Odd_Footer(
  12697.     File_Handle : in Paginated_File_Handle;
  12698.     Footer_Line : in integer;
  12699.     Footer_Text : in string
  12700.     ) is
  12701.  
  12702.     Text : String_Pkg.String_Type;
  12703.  
  12704.     begin
  12705.  
  12706.     Text := String_Pkg.Make_Persistent(Footer_Text);
  12707.     Set_Odd_Footer(File_Handle, Footer_Line, Text);
  12708.     String_Pkg.Flush(Text);
  12709.     return;
  12710.  
  12711.     end Set_Odd_Footer;
  12712.                                                     pragma Page;
  12713.     procedure Set_Even_Footer(
  12714.     Footer_Text : in Variable_String_Array
  12715.     ) is
  12716.  
  12717.     begin
  12718.  
  12719.     Set_Even_Footer(Paginated_Standard_Output,
  12720.             Footer_Text);
  12721.  
  12722.     end Set_Even_Footer;
  12723.                                                     pragma Page;
  12724.     procedure Set_Even_Footer(
  12725.     File_Handle : in Paginated_File_Handle;
  12726.     Footer_Text : in Variable_String_Array
  12727.     ) is
  12728.  
  12729. --|-Algorithm:
  12730. --| Set given footer text as even page header 
  12731. --| Exit
  12732. --|+
  12733.  
  12734.     begin
  12735.  
  12736.     Set_Text(File_Handle, Footer_Text, (Even, Footer));
  12737.     return;
  12738.  
  12739.     end Set_Even_Footer;
  12740.                                                     pragma Page;
  12741.     procedure Set_Even_Footer(
  12742.     Footer_Line : in integer;
  12743.     Footer_Text : in String_Pkg.String_Type
  12744.     ) is
  12745.  
  12746.     begin
  12747.  
  12748.     Set_Even_Footer(Paginated_Standard_Output,
  12749.             Footer_Line,
  12750.             Footer_Text);
  12751.  
  12752.     end Set_Even_Footer;
  12753.                                                     pragma Page;
  12754.     procedure Set_Even_Footer(
  12755.     File_Handle : in Paginated_File_Handle;
  12756.     Footer_Line : in integer;
  12757.     Footer_Text : in String_Pkg.String_Type
  12758.     ) is
  12759.  
  12760. --|-Algorithm:
  12761. --| Validate paginated file structure (raise error if not valid)
  12762. --| If requested footer line number is out of range
  12763. --|     then raise an error
  12764. --| Set footer text at requested line for even pages
  12765. --| Exit
  12766. --|+
  12767.  
  12768.     begin
  12769.  
  12770.     Check_Valid(File_Handle);
  12771.     if Footer_Line < 1 then 
  12772.         raise Text_Underflow;
  12773.     end if;
  12774.     if Footer_Line > File_Handle.footer_size then
  12775.         raise Text_Overflow;
  12776.     end if;
  12777.     String_Pkg.Flush(File_Handle.even_page_footer(Footer_Line));
  12778.     File_Handle.even_page_footer(Footer_Line) := String_Pkg.Make_Persistent(Footer_Text);
  12779.     return;
  12780.  
  12781.     end Set_Even_Footer;
  12782.                                                     pragma Page;
  12783.     procedure Set_Even_Footer(
  12784.     Footer_Line : in integer;
  12785.     Footer_Text : in string
  12786.     ) is
  12787.  
  12788.     begin
  12789.  
  12790.     Set_Even_Footer(Paginated_Standard_Output,
  12791.             Footer_Line,
  12792.             Footer_Text);
  12793.  
  12794.     end Set_Even_Footer;
  12795.                                                     pragma Page;
  12796.     procedure Set_Even_Footer(
  12797.     File_Handle : in Paginated_File_Handle;
  12798.     Footer_Line : in integer;
  12799.     Footer_Text : in string
  12800.     ) is
  12801.  
  12802. --|-Algorithm:
  12803. --| Create a variable string
  12804. --| Set even page footer
  12805. --| Exit
  12806. --|+
  12807.     Text : String_Pkg.String_Type;
  12808.  
  12809.     begin
  12810.  
  12811.     Text := String_Pkg.Make_Persistent(Footer_Text);
  12812.     Set_Even_Footer(File_Handle, Footer_Line, Text);
  12813.     String_Pkg.Flush(Text);
  12814.     return;
  12815.  
  12816.     end Set_Even_Footer;
  12817.                                                     pragma Page;
  12818.     procedure Clear_Header    
  12819.     is
  12820.  
  12821.     begin
  12822.  
  12823.     Clear_Header(Paginated_Standard_Output);
  12824.  
  12825.     end Clear_Header;
  12826.                                                     pragma Page;
  12827.     procedure Clear_Header(    
  12828.     File_Handle : in Paginated_File_Handle
  12829.     ) is
  12830.  
  12831. --|-Algorithm:
  12832. --| Clear odd page header
  12833. --| Clear even page header
  12834. --| Exit
  12835. --|+
  12836.  
  12837.     begin
  12838.  
  12839.     Clear_Odd_Header(File_Handle);
  12840.     Clear_Even_Header(File_Handle);
  12841.     return;
  12842.  
  12843.     end Clear_Header;
  12844.                                                     pragma Page;
  12845.     procedure Clear_Odd_Header
  12846.     is
  12847.  
  12848.     begin
  12849.  
  12850.     Clear_Odd_Header(Paginated_Standard_Output);
  12851.  
  12852.     end Clear_Odd_Header;
  12853.                                                     pragma Page;
  12854.     procedure Clear_Odd_Header(
  12855.     File_Handle : in Paginated_File_Handle
  12856.     ) is
  12857.  
  12858. --|-Algorithm:
  12859. --| Validate paginated file structure (raise error if not valid)
  12860. --| Clear all text for odd page header lines
  12861. --| Exit
  12862. --|+
  12863.  
  12864.     begin
  12865.  
  12866.     Check_Valid(File_Handle);
  12867.     Clear_Text(File_Handle.odd_page_header);
  12868.     return;
  12869.  
  12870.     end Clear_Odd_Header;
  12871.                                                     pragma Page;
  12872.     procedure Clear_Even_Header
  12873.     is
  12874.  
  12875.     begin
  12876.  
  12877.     Clear_Even_Header(Paginated_Standard_Output);
  12878.  
  12879.     end Clear_Even_Header;
  12880.                                                     pragma Page;
  12881.     procedure Clear_Even_Header(
  12882.     File_Handle : in Paginated_File_Handle
  12883.     ) is
  12884.  
  12885. --|-Algorithm:
  12886. --| Validate paginated file structure (raise error if not valid)
  12887. --| Clear all text for even page header lines
  12888. --| Exit
  12889. --|+
  12890.  
  12891.     begin
  12892.  
  12893.     Check_Valid(File_Handle);
  12894.     Clear_Text(File_Handle.even_page_header);
  12895.     return;
  12896.  
  12897.     end Clear_Even_Header;
  12898.                                                     pragma Page;
  12899.     procedure Clear_Footer
  12900.     is
  12901.  
  12902.     begin
  12903.  
  12904.     Clear_Footer(Paginated_Standard_Output);
  12905.  
  12906.     end Clear_Footer;
  12907.                                                     pragma Page;
  12908.     procedure Clear_Footer(    
  12909.     File_Handle : in Paginated_File_Handle
  12910.     ) is
  12911.  
  12912. --|-Algorithm:
  12913. --| Clear odd page footer
  12914. --| Clear even page footer
  12915. --| Exit
  12916. --|+
  12917.  
  12918.     begin
  12919.  
  12920.     Clear_Odd_Footer(File_Handle);
  12921.     Clear_Even_Footer(File_Handle);
  12922.     return;
  12923.  
  12924.     end Clear_Footer;
  12925.                                                     pragma Page;
  12926.     procedure Clear_Odd_Footer
  12927.     is
  12928.  
  12929.     begin
  12930.  
  12931.     Clear_Odd_Footer(Paginated_Standard_Output);
  12932.  
  12933.     end Clear_Odd_Footer;
  12934.                                                     pragma Page;
  12935.     procedure Clear_Odd_Footer(
  12936.     File_Handle : in Paginated_File_Handle
  12937.     ) is
  12938.  
  12939. --|-Algorithm:
  12940. --| Validate paginated file structure (raise error if not valid)
  12941. --| Clear all text for odd page footer lines
  12942. --| Exit
  12943. --|+
  12944.  
  12945.     begin
  12946.  
  12947.     Check_Valid(File_Handle);
  12948.     Clear_Text(File_Handle.odd_page_footer);
  12949.     return;
  12950.  
  12951.     end Clear_Odd_Footer;
  12952.                                                     pragma Page;
  12953.     procedure Clear_Even_Footer
  12954.     is
  12955.  
  12956.     begin
  12957.  
  12958.     Clear_Even_Footer(Paginated_Standard_Output);
  12959.  
  12960.     end Clear_Even_Footer;
  12961.                                                     pragma Page;
  12962.     procedure Clear_Even_Footer(
  12963.     File_Handle : in Paginated_File_Handle
  12964.     ) is
  12965.  
  12966. --|-Algorithm:
  12967. --| Validate paginated file structure (raise error if not valid)
  12968. --| Clear all text for even footer lines
  12969. --| Exit
  12970. --|+
  12971.  
  12972.     begin
  12973.  
  12974.     Check_Valid(File_Handle);
  12975.     Clear_Text(File_Handle.even_page_footer);
  12976.     return;
  12977.  
  12978.     end Clear_Even_Footer;
  12979.                                                     pragma Page;
  12980.     procedure Close_Paginated_File
  12981.     is
  12982.  
  12983.     begin
  12984.  
  12985.     Close_Paginated_File(Paginated_Standard_Output);
  12986.     Create_Paginated_File("", Paginated_Standard_Output, 0, 0, 0);
  12987.     Paginated_Standard_Output.standard_flag := true;
  12988.     
  12989.     end Close_Paginated_File;
  12990.                                                     pragma Page;
  12991.     procedure Close_Paginated_File(
  12992.     File_Handle : in out Paginated_File_Handle
  12993.     ) is
  12994.  
  12995. --|-Algorithm:
  12996. --| If no file (ie. handle is null)
  12997. --|    then return
  12998. --| Decrement access count to this file structure
  12999. --| If other accesses still exist for this structure
  13000. --|    then null this handle and return
  13001. --| If not at the top of the page
  13002. --|    then eject current page
  13003. --| Return all storage used for this file to the heap
  13004. --| Close the external file
  13005. --| Exit
  13006. --|+
  13007.  
  13008.     begin
  13009.  
  13010.     if File_Handle = null then
  13011.         return;
  13012.     end if;
  13013.     File_Handle.access_count := File_Handle.access_count - 1;
  13014.     if File_Handle.access_count > 0 then
  13015.         File_Handle := null;
  13016.         return;
  13017.     end if;
  13018.     Unlink_Paginated_File(File_Handle);
  13019.     if File_Handle.current_line /= 0 and File_Handle.page_size /= 0 then
  13020.         Page_Eject(File_Handle, 1);
  13021.     end if;
  13022.     Abort_Paginated_Output(File_Handle);
  13023.     return;
  13024.  
  13025.     end Close_Paginated_File;
  13026.                                                     pragma Page;
  13027.     procedure Put(
  13028.     Text        : in character
  13029.     ) is
  13030.  
  13031.     begin
  13032.  
  13033.     Put(Paginated_Standard_Output,
  13034.         Text);
  13035.  
  13036.     end Put;
  13037.                                                     pragma Page;
  13038.     procedure Put(
  13039.     File_Handle : in Paginated_File_Handle;
  13040.     Text        : in character
  13041.     ) is
  13042.  
  13043.     begin
  13044.  
  13045.     Write(File_Handle, "" & Text, false);
  13046.  
  13047.     end Put;
  13048.                                                     pragma Page;
  13049.     procedure Put(
  13050.     Text        : in string
  13051.     ) is
  13052.  
  13053.     begin
  13054.  
  13055.     Write(Paginated_Standard_Output, Text, false);
  13056.  
  13057.     end Put;
  13058.                                                     pragma Page;
  13059.     procedure Put(
  13060.     File_Handle : in Paginated_File_Handle;
  13061.     Text        : in string
  13062.     ) is
  13063.  
  13064. --|-Algorithm:
  13065. --| Execute Write procedure with feed
  13066. --| Exit
  13067. --|+
  13068.  
  13069.     begin
  13070.  
  13071.     Write(File_Handle, Text, false);
  13072.  
  13073.     end Put;
  13074.                                                     pragma Page;
  13075.     procedure Put(
  13076.     Text        : in String_Pkg.String_Type
  13077.     ) is
  13078.  
  13079.     begin
  13080.  
  13081.     Put(Paginated_Standard_Output,
  13082.         String_Pkg.Value(Text));
  13083.  
  13084.     end Put;
  13085.                                                     pragma Page;
  13086.     procedure Put(
  13087.     File_Handle : in Paginated_File_Handle;
  13088.     Text        : in String_Pkg.String_Type
  13089.     ) is
  13090.  
  13091. --|-Algorithm:
  13092. --| Create a fixed length string
  13093. --| Output the line
  13094. --| Exit
  13095. --|+
  13096.  
  13097.     begin
  13098.  
  13099.     Put(File_Handle, String_Pkg.Value(Text));
  13100.     return;
  13101.  
  13102.     end Put;
  13103.                                                     pragma Page;
  13104.     procedure Put(
  13105.     Text        : in Variable_String_Array
  13106.     ) is
  13107.  
  13108.     begin
  13109.  
  13110.     for i in Text'range loop
  13111.         Put(Paginated_Standard_Output, String_Pkg.Value(Text(i)));
  13112.     end loop;
  13113.     return;
  13114.  
  13115.     end Put;
  13116.                                                     pragma Page;
  13117.     procedure Put(
  13118.     File_Handle : in Paginated_File_Handle;
  13119.     Text        : in Variable_String_Array
  13120.     ) is
  13121.  
  13122. --|-Algorithm:
  13123. --| Loop for all elements of the variable string array
  13124. --|    Create a fixed length string
  13125. --|    Output the line
  13126. --| Exit
  13127. --|+
  13128.  
  13129.     begin
  13130.  
  13131.     for i in Text'range loop
  13132.         Put(File_Handle, String_Pkg.Value(Text(i)));
  13133.     end loop;
  13134.     return;
  13135.  
  13136.     end Put;
  13137.                                                     pragma Page;
  13138.     procedure Space(
  13139.     Count       : in integer
  13140.     ) is
  13141.  
  13142.     begin
  13143.  
  13144.     Space(Paginated_Standard_Output,
  13145.           Count);
  13146.  
  13147.     end Space;
  13148.                                                     pragma Page;
  13149.     procedure Space(
  13150.     File_Handle : in Paginated_File_Handle;
  13151.     Count       : in integer
  13152.     ) is
  13153.  
  13154.     begin
  13155.  
  13156.     Check_Valid(File_Handle);
  13157.     if Count <= 0 then
  13158.         return;
  13159.     end if;
  13160.     declare
  13161.         Space_String : string (1 .. Count) := (1 .. Count => ' ');
  13162.     begin
  13163.         Put(File_Handle, Space_String);
  13164.     end;
  13165.  
  13166.     end Space;
  13167.                                                     pragma Page;
  13168.     procedure Put_Line(
  13169.     Text_Line   : in string
  13170.     ) is
  13171.  
  13172.     begin
  13173.  
  13174.     Write(Paginated_Standard_Output, Text_Line, true);
  13175.  
  13176.     end Put_Line;
  13177.                                                     pragma Page;
  13178.     procedure Put_Line(
  13179.     File_Handle : in Paginated_File_Handle;
  13180.     Text_Line   : in string
  13181.     ) is
  13182.  
  13183. --|-Algorithm:
  13184. --| Execute Write procedure with feed
  13185. --| Exit
  13186. --|+
  13187.  
  13188.     begin
  13189.  
  13190.     Write(File_Handle, Text_Line, true);
  13191.  
  13192.     end Put_Line;
  13193.                                                     pragma Page;
  13194.     procedure Put_Line(
  13195.     Text_Line   : in String_Pkg.String_Type
  13196.     ) is
  13197.  
  13198.     begin
  13199.  
  13200.     Put_Line(Paginated_Standard_Output,
  13201.          String_Pkg.Value(Text_Line));
  13202.     return;
  13203.  
  13204.     end Put_Line;
  13205.                                                     pragma Page;
  13206.     procedure Put_Line(
  13207.     File_Handle : in Paginated_File_Handle;
  13208.     Text_Line   : in String_Pkg.String_Type
  13209.     ) is
  13210.  
  13211. --|-Algorithm:
  13212. --| Create a fixed length string
  13213. --| Output the line
  13214. --| Exit
  13215. --|+
  13216.  
  13217.     begin
  13218.  
  13219.     Put_Line(File_Handle, String_Pkg.Value(Text_Line));
  13220.     return;
  13221.  
  13222.     end Put_Line;
  13223.                                                     pragma Page;
  13224.     procedure Put_Line(
  13225.     Text_Line   : in Variable_String_Array
  13226.     ) is
  13227.  
  13228.     begin
  13229.  
  13230.     for i in Text_Line'range loop
  13231.         Put_Line(Paginated_Standard_Output,
  13232.              String_Pkg.Value(Text_Line(i)));
  13233.     end loop;
  13234.     return;
  13235.  
  13236.     end Put_Line;
  13237.                                                     pragma Page;
  13238.     procedure Put_Line(
  13239.     File_Handle : in Paginated_File_Handle;
  13240.     Text_Line   : in Variable_String_Array
  13241.     ) is
  13242.  
  13243. --|-Algorithm:
  13244. --| Loop for all elements of the variable string array
  13245. --|    Create a fixed length string
  13246. --|    Output the line
  13247. --| Exit
  13248. --|+
  13249.  
  13250.     begin
  13251.  
  13252.     for i in Text_Line'range loop
  13253.         Put_Line(File_Handle, String_Pkg.Value(Text_Line(i)));
  13254.     end loop;
  13255.     return;
  13256.  
  13257.     end Put_Line;
  13258.                                                     pragma Page;
  13259.     procedure Space_Line(
  13260.     Count       : in integer := 1
  13261.     ) is
  13262.  
  13263.     begin
  13264.  
  13265.     Space_Line(Paginated_Standard_Output,
  13266.            Count);
  13267.  
  13268.     end Space_Line;
  13269.                                                     pragma Page;
  13270.     procedure Space_Line(
  13271.     File_Handle : in Paginated_File_Handle;
  13272.     Count       : in integer := 1
  13273.     ) is
  13274.  
  13275. --|-Algorithm:
  13276. --| Validate paginated file structure (raise error if not valid)
  13277. --| Raise Invalid_Count if space request is too large
  13278. --| Write out the given number of new line control characters
  13279. --| while taking into account header, footer, and pagination.
  13280. --| Exit
  13281. --|+
  13282.  
  13283.     Handle : Paginated_File_Handle;
  13284.  
  13285.     begin
  13286.     
  13287.     Check_Valid(File_Handle);
  13288.     Handle := File_Handle;
  13289.     loop
  13290.         exit when Handle = null;
  13291.         Line_Feed(Handle, Count);
  13292.         Handle := Handle.forward_link;
  13293.     end loop;
  13294.     return;
  13295.  
  13296.     end Space_Line;
  13297.                                                     pragma Page;
  13298.     procedure Skip_Line(
  13299.     Count       : in integer := 1
  13300.     ) is
  13301.  
  13302.     begin
  13303.  
  13304.     Skip_Line(Paginated_Standard_Output,
  13305.           Count);
  13306.  
  13307.     end Skip_Line;
  13308.                                                     pragma Page;
  13309.     procedure Skip_Line(
  13310.     File_Handle : in Paginated_File_Handle;
  13311.     Count       : in integer := 1
  13312.     ) is
  13313.  
  13314. --|-Algorithm:
  13315. --| Validate paginated file structure (raise error if not valid)
  13316. --| Set the number of new line characters to be written as the
  13317. --| number specified or the number of lines remaining on the 
  13318. --| page which ever is smaller.
  13319. --| Write out this number of new line control characters
  13320. --| while taking into account header, footer, and pagination.
  13321. --| (If at the top of the page then Skip_Lines does nothing)
  13322. --| Exit
  13323. --|+
  13324.  
  13325.     Skip_Count : integer;
  13326.     Handle     : Paginated_File_Handle;
  13327.  
  13328.     begin
  13329.     
  13330.     Check_Valid(File_Handle);
  13331.     Handle := File_Handle;
  13332.     loop
  13333.         exit when Handle = null;
  13334.         if Handle.current_line /= 0 or Handle.page_size = 0 then
  13335.         Skip_Count := Handle.maximum_line - Handle.current_line + 1;
  13336.         if Skip_Count > Count or Handle.page_size = 0 then
  13337.             Skip_Count := Count;
  13338.         end if;
  13339.         Line_Feed(Handle, Skip_Count);
  13340.         end if;
  13341.         Handle := Handle.forward_link;
  13342.     end loop;
  13343.     return;
  13344.  
  13345.     end Skip_Line;
  13346.                                                     pragma Page;
  13347.     procedure Put_Page(
  13348.     Count       : in integer := 1
  13349.     ) is
  13350.  
  13351.     begin
  13352.  
  13353.     Put_Page(Paginated_Standard_Output,
  13354.          Count);
  13355.  
  13356.     end Put_Page;
  13357.                                                     pragma Page;
  13358.     procedure Put_Page(
  13359.     File_Handle : in Paginated_File_Handle;
  13360.     Count       : in integer := 1
  13361.     ) is
  13362.  
  13363. --|-Algorithm:
  13364. --| Validate paginated file structure (raise error if not valid)
  13365. --| Raise Invalid_Count if page request is too large
  13366. --| Convert the number of pages to skip into number of lines  
  13367. --| Write out this number of new line control characters
  13368. --| while taking into account header, footer, and pagination.
  13369. --| Exit
  13370. --|+
  13371.  
  13372.     Handle : Paginated_File_Handle;
  13373.  
  13374.     begin
  13375.  
  13376.     Check_Valid(File_Handle);
  13377.     Handle := File_Handle;
  13378.     loop
  13379.         exit when Handle = null;
  13380.         Page_Eject(Handle, Count);
  13381.         Handle := Handle.forward_link;
  13382.     end loop;
  13383.     return;
  13384.  
  13385.     end Put_Page;
  13386.                                                     pragma Page;
  13387.     function Available_Lines
  13388.     return integer is
  13389.  
  13390.     begin
  13391.  
  13392.     return Available_Lines(Paginated_Standard_Output);
  13393.  
  13394.     end Available_Lines;
  13395.                                                     pragma Page;
  13396.     function Available_Lines(
  13397.     File_Handle : in Paginated_File_Handle
  13398.     ) return integer is
  13399.  
  13400. --|-Algorithm:
  13401. --| Validate paginated file structure (raise error if not valid)
  13402. --| Return the number of lines remaining on the page
  13403. --|+
  13404.  
  13405.     begin
  13406.  
  13407.     Check_Valid(File_Handle);
  13408.     if File_Handle.page_size = 0 then
  13409.         return -1;
  13410.     end if;
  13411.     if File_Handle.current_line = 0 then
  13412.         return File_Handle.maximum_line;
  13413.     else
  13414.         return File_Handle.maximum_line - File_Handle.current_line + 1;
  13415.     end if;
  13416.  
  13417.     end Available_Lines;
  13418.                                                     pragma Page;
  13419.     procedure Reserve_Lines(
  13420.     Count       : in integer
  13421.     ) is
  13422.  
  13423.     begin
  13424.  
  13425.     Reserve_Lines(Paginated_Standard_Output,
  13426.               Count);
  13427.  
  13428.     end Reserve_Lines;
  13429.                                                                  pragma Page;
  13430.     procedure Reserve_Lines(
  13431.     File_Handle : in Paginated_File_Handle;
  13432.     Count       : in integer
  13433.     ) is
  13434.  
  13435. --|-Algorithm:
  13436. --| Validate paginated file structure (raise error if not valid)
  13437. --| If the requested number of lines is greater than the page size
  13438. --|    then raise an error
  13439. --| If the requested is greater than the remaining space
  13440. --|    then eject page
  13441. --| Exit
  13442. --|+
  13443.  
  13444.     begin
  13445.  
  13446.     Check_Valid(File_Handle);
  13447.     if File_Handle.page_size = 0 then
  13448.         return;
  13449.     end if;
  13450.     if Count > File_Handle.page_size then
  13451.         raise Page_Overflow;
  13452.     end if;
  13453.     if Count > Available_Lines(File_Handle) then
  13454.         Page_Eject(File_Handle, 1);
  13455.     end if;
  13456.     return;
  13457.  
  13458.     end Reserve_Lines;
  13459.                                                                  pragma Page;
  13460. begin
  13461.  
  13462.     Create_Paginated_File("", Paginated_Standard_Output, 0, 0, 0);
  13463.     Paginated_Standard_Output.standard_flag := true;
  13464.  
  13465. end Paginated_Output;
  13466.                                                                  pragma Page;
  13467. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  13468. --SCANNER.BDY
  13469. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  13470. with String_Pkg;            use String_Pkg;
  13471. with Unchecked_Deallocation;
  13472.  
  13473. package body String_Scanner is
  13474.  
  13475.  
  13476. White_Space   : constant string := " " & ASCII.HT;
  13477. Number_1      : constant string := "0123456789";
  13478. Number        : constant string := Number_1 & "_";
  13479. Quote         : constant string := """";
  13480. Ada_Id_1      : constant string := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  13481. Ada_Id        : constant string := Ada_Id_1 & Number;
  13482.  
  13483. procedure Free_Scanner is
  13484.     new Unchecked_Deallocation(Scan_Record, Scanner);
  13485.                                                     pragma Page;
  13486. function Is_Valid(
  13487.     T : in Scanner
  13488.     ) return boolean is
  13489.  
  13490. begin
  13491.  
  13492.     return T /= null;
  13493.  
  13494. end Is_Valid;
  13495.  
  13496. function Make_Scanner(
  13497.     S : in String_Type
  13498.     ) return Scanner is
  13499.  
  13500.     T : Scanner := new Scan_Record;
  13501.  
  13502. begin
  13503.  
  13504.     T.text := String_Pkg.Make_Persistent(S);
  13505.     return T;
  13506.  
  13507. end Make_Scanner;
  13508.  
  13509. ----------------------------------------------------------------
  13510.  
  13511. procedure Destroy_Scanner(
  13512.     T : in out Scanner
  13513.     ) is
  13514.  
  13515. begin
  13516.  
  13517.     if Is_Valid(T) then
  13518.     String_Pkg.Flush(T.text);
  13519.     Free_Scanner(T);
  13520.     end if;
  13521.  
  13522. end Destroy_Scanner;
  13523.  
  13524. ----------------------------------------------------------------
  13525.  
  13526. function More(
  13527.     T : in Scanner
  13528.     ) return boolean is
  13529.  
  13530. begin
  13531.  
  13532.     if Is_Valid(T) then
  13533.     if T.index > String_Pkg.Length(T.text) then
  13534.         return false;
  13535.     else
  13536.             return true;
  13537.     end if;
  13538.     else
  13539.     return false;
  13540.     end if;
  13541.  
  13542. end More;
  13543.  
  13544. ----------------------------------------------------------------
  13545.  
  13546. function Get(
  13547.     T : in Scanner
  13548.     ) return character is
  13549.  
  13550. begin
  13551.  
  13552.     if not More(T) then
  13553.     raise Out_Of_Bounds;
  13554.     end if;
  13555.     return String_Pkg.Fetch(T.text, T.index);
  13556.  
  13557. end Get;
  13558.  
  13559. ----------------------------------------------------------------
  13560.  
  13561. procedure Forward(
  13562.     T : in Scanner
  13563.     ) is
  13564.  
  13565. begin
  13566.  
  13567.     if Is_Valid(T) then
  13568.     if String_Pkg.Length(T.text) >= T.index then
  13569.         T.index := T.index + 1;
  13570.     end if;
  13571.     end if;
  13572.  
  13573. end Forward;
  13574.  
  13575. ----------------------------------------------------------------
  13576.  
  13577. procedure Backward(
  13578.     T : in Scanner
  13579.     ) is
  13580.  
  13581. begin
  13582.  
  13583.     if Is_Valid(T) then
  13584.     if T.index > 1 then
  13585.         T.index := T.index - 1;
  13586.     end if;
  13587.     end if;
  13588.  
  13589. end Backward;
  13590.  
  13591. ----------------------------------------------------------------
  13592.  
  13593. procedure Next(
  13594.     T : in     Scanner;
  13595.     C :    out character
  13596.     ) is
  13597.  
  13598. begin
  13599.  
  13600.     C := Get(T);
  13601.     Forward(T);
  13602.  
  13603. end Next;
  13604.  
  13605. ----------------------------------------------------------------
  13606.  
  13607. function Position(
  13608.     T : in Scanner
  13609.     ) return positive is
  13610.  
  13611. begin
  13612.  
  13613.     if not More(T) then
  13614.     raise Out_Of_Bounds;
  13615.     end if;
  13616.     return T.index;
  13617.  
  13618. end Position;
  13619.  
  13620. ----------------------------------------------------------------
  13621.  
  13622. function Get_String(
  13623.     T : in Scanner
  13624.     ) return String_Type is
  13625.  
  13626. begin
  13627.  
  13628.     if Is_Valid(T) then
  13629.     return String_Pkg.Make_Persistent(T.text);
  13630.     else
  13631.     return String_Pkg.Make_Persistent("");
  13632.     end if;
  13633.  
  13634. end Get_String;
  13635.  
  13636. ----------------------------------------------------------------
  13637.  
  13638. function Get_Remainder(
  13639.     T : in Scanner
  13640.     ) return String_Type is
  13641.  
  13642.     S_Str : String_Type;
  13643.  
  13644. begin
  13645.  
  13646.     if More(T) then
  13647.     String_Pkg.Mark;
  13648.     S_Str := String_Pkg.Make_Persistent(
  13649.     String_Pkg.Substr(T.text,
  13650.               T.index,
  13651.               String_Pkg.Length(T.text) - T.index + 1));
  13652.     String_Pkg.Release;
  13653.     else
  13654.     S_Str := String_Pkg.Make_Persistent("");
  13655.     end if;
  13656.     return S_Str;
  13657.  
  13658. end Get_Remainder;
  13659.  
  13660. ----------------------------------------------------------------
  13661.  
  13662. procedure Mark(
  13663.     T : in Scanner
  13664.     ) is
  13665.  
  13666. begin
  13667.  
  13668.     if Is_Valid(T) then
  13669.     if T.mark /= 0 then
  13670.         raise Scanner_Already_Marked;
  13671.     else
  13672.         T.mark := T.index;
  13673.     end if;
  13674.     end if;
  13675.  
  13676. end Mark;
  13677.  
  13678. ----------------------------------------------------------------
  13679.  
  13680. procedure Restore(
  13681.     T : in Scanner
  13682.     ) is
  13683.  
  13684. begin
  13685.  
  13686.     if Is_Valid(T) then
  13687.     if T.mark /= 0 then
  13688.         T.index := T.mark;
  13689.         T.mark  := 0;
  13690.     end if;
  13691.     end if;
  13692.  
  13693. end Restore;
  13694.                                                     pragma Page;
  13695. function Is_Any(
  13696.     T : in Scanner;
  13697.     Q : in string
  13698.     ) return boolean is
  13699.  
  13700.     N     : natural;
  13701.  
  13702. begin
  13703.  
  13704.     if not More(T) then
  13705.     return false;
  13706.     end if;
  13707.     String_Pkg.Mark;
  13708.     N := String_Pkg.Match_Any(T.text, Q, T.index);
  13709.     if N /= T.index then
  13710.     N := 0;
  13711.     end if;
  13712.     String_Pkg.Release;
  13713.     return N /= 0;
  13714.  
  13715. end Is_Any;
  13716.                                                      pragma Page;
  13717. procedure Scan_Any(
  13718.     T      : in     Scanner;
  13719.     Q      : in     string;
  13720.     Found  :    out boolean;
  13721.     Result : in out String_Type
  13722.     ) is
  13723.  
  13724.     S_Str : String_Type;
  13725.     N     : natural;
  13726.  
  13727. begin
  13728.  
  13729.     if Is_Any(T, Q) then
  13730.     N := String_Pkg.Match_None(T.text, Q, T.index);
  13731.     if N = 0 then
  13732.         N := String_Pkg.Length(T.text) + 1;
  13733.     end if;
  13734.     Result  := Result & String_Pkg.Substr(T.text, T.index, N - T.index);
  13735.     T.index := N;    
  13736.     Found   := true;
  13737.     else
  13738.     Found := false;
  13739.     end if;
  13740.  
  13741. end Scan_Any;
  13742.                                                     pragma Page;
  13743. function Quoted_String(
  13744.     T : in Scanner
  13745.     ) return integer is
  13746.  
  13747.     Count : integer := 0;
  13748.     I     : positive;
  13749.     N     : natural;
  13750.  
  13751. begin
  13752.  
  13753.     if not Is_Valid(T) then
  13754.     return Count;
  13755.     end if;
  13756.     I := T.index;
  13757.     while Is_Any(T, """") loop
  13758.     T.index := T.index + 1;
  13759.     if not More(T) then
  13760.         T.index := I;
  13761.         return 0;
  13762.     end if;
  13763.     String_Pkg.Mark;
  13764.     N := String_Pkg.Match_Any(T.text, """", T.index);
  13765.     String_Pkg.Release;
  13766.     if N = 0 then
  13767.         T.index := I;
  13768.         return 0;
  13769.     end if;
  13770.     T.index := N + 1;
  13771.     end loop;
  13772.     Count := T.index - I;
  13773.     T.index := I;
  13774.     return Count;
  13775.  
  13776. end Quoted_String;
  13777.                                                     pragma Page;
  13778. function Enclosed_String(
  13779.     B : in character;
  13780.     E : in character;
  13781.     T : in Scanner
  13782.     ) return natural is
  13783.  
  13784.     Count : natural := 1;
  13785.     I     : positive;
  13786.     Inx_B : natural;
  13787.     Inx_E : natural;
  13788.     Depth : natural := 1;
  13789.  
  13790. begin
  13791.  
  13792.     if not Is_Any(T, B & "") then
  13793.     return 0;
  13794.     end if;
  13795.     I := T.index;
  13796.     Forward(T);
  13797.     while Depth /= 0 loop
  13798.     if not More(T) then
  13799.         T.index := I;
  13800.         return 0;
  13801.     end if;
  13802.     String_Pkg.Mark;
  13803.     Inx_B   := String_Pkg.Match_Any(T.text, B & "", T.index);
  13804.     Inx_E   := String_Pkg.Match_Any(T.text, E & "", T.index);
  13805.     String_Pkg.Release;
  13806.     if Inx_E = 0 then
  13807.         T.index := I;
  13808.         return 0;
  13809.     end if;
  13810.     if Inx_B /= 0 and then Inx_B < Inx_E then
  13811.         Depth := Depth + 1;
  13812.     else
  13813.         Inx_B := Inx_E;
  13814.         Depth := Depth - 1;
  13815.     end if;
  13816.     T.index := Inx_B + 1;
  13817.     end loop;
  13818.     Count := T.index - I;
  13819.     T.index := I;
  13820.     return Count;
  13821.  
  13822. end Enclosed_String;
  13823.                                                      pragma Page;
  13824. function Is_Word(
  13825.     T : in Scanner
  13826.     ) return boolean is
  13827.  
  13828. begin
  13829.  
  13830.     if not More(T) then
  13831.     return false;
  13832.     else
  13833.     return not Is_Any(T, White_Space);
  13834.     end if;
  13835.  
  13836. end Is_Word;
  13837.  
  13838. ----------------------------------------------------------------
  13839.  
  13840. procedure Scan_Word(
  13841.     T      : in     Scanner;
  13842.     Found  :    out boolean;
  13843.     Result :    out String_Type;
  13844.     Skip   : in     boolean := false
  13845.     ) is
  13846.  
  13847.     S_Str : String_Type;
  13848.     N     : natural;
  13849.  
  13850. begin
  13851.  
  13852.     if Skip then
  13853.     Skip_Space(T);
  13854.     end if;
  13855.     if Is_Word(T) then
  13856.     String_Pkg.Mark;
  13857.     N := String_Pkg.Match_Any(T.text, White_Space, T.index);
  13858.     if N = 0 then
  13859.         N := String_Pkg.Length(T.text) + 1;
  13860.     end if;
  13861.     Result  := String_Pkg.Make_Persistent
  13862.            (String_Pkg.Substr(T.text, T.index, N - T.index));
  13863.     T.index := N;    
  13864.     Found   := true;
  13865.     String_Pkg.Release;
  13866.     else
  13867.     Found   := false;
  13868.     end if;
  13869.     return;
  13870.  
  13871. end Scan_Word;
  13872.                                                     pragma Page;
  13873. function Is_Number(
  13874.     T : in Scanner
  13875.     ) return boolean is
  13876.  
  13877. begin
  13878.  
  13879.     return Is_Any(T, Number_1);
  13880.  
  13881. end Is_Number;
  13882.  
  13883. ----------------------------------------------------------------
  13884.  
  13885. procedure Scan_Number(
  13886.     T      : in     Scanner;
  13887.     Found  :    out boolean;
  13888.     Result :    out String_Type;
  13889.     Skip   : in     boolean := false
  13890.     ) is
  13891.  
  13892.     C     : character;
  13893.     S_Str : String_Type;
  13894.  
  13895. begin
  13896.  
  13897.     if Skip then
  13898.     Skip_Space(T);
  13899.     end if;
  13900.     if not Is_Number(T) then
  13901.     Found := false;
  13902.     return;
  13903.     end if;
  13904.     String_Pkg.Mark;
  13905.     while Is_Number(T) loop
  13906.     Scan_Any(T, Number_1, Found, S_Str);
  13907.     if More(T) then
  13908.         C := Get(T);
  13909.         if C = '_' then
  13910.         Forward(T);
  13911.         if Is_Number(T) then
  13912.             S_Str := S_Str & "_";
  13913.         else
  13914.             Backward(T);
  13915.         end if;
  13916.         end if;
  13917.     end if;
  13918.     end loop;
  13919.     Result := String_Pkg.Make_Persistent(S_Str);
  13920.     String_Pkg.Release;
  13921.  
  13922. end Scan_Number;
  13923.  
  13924. ----------------------------------------------------------------
  13925.  
  13926. procedure Scan_Number(
  13927.     T      : in     Scanner;
  13928.     Found  :    out boolean;
  13929.     Result :    out integer;
  13930.     Skip   : in     boolean := false
  13931.     ) is
  13932.  
  13933.     F     : boolean;
  13934.     S_Str : String_Type;
  13935.  
  13936. begin
  13937.  
  13938.     Scan_Number(T, F, S_Str, Skip);
  13939.     if F then
  13940.     Result := integer'value(String_Pkg.Value(S_Str));
  13941.     end if;
  13942.     Found := F;
  13943.  
  13944. end Scan_Number;
  13945.                                                     pragma Page;
  13946. function Is_Signed_Number(
  13947.     T : in Scanner
  13948.     ) return boolean is
  13949.  
  13950.     I : positive;
  13951.     C : character;
  13952.     F : boolean;
  13953.  
  13954. begin
  13955.  
  13956.     if More(T) then
  13957.     I := T.index;
  13958.     C := Get(T);
  13959.     if C = '+' or C = '-' then
  13960.         T.index := T.index + 1;
  13961.     end if;
  13962.     F := Is_Any(T, Number_1);
  13963.     T.index := I;
  13964.     return F;
  13965.     else
  13966.     return false;
  13967.     end if;
  13968.  
  13969. end Is_Signed_Number;
  13970.  
  13971. ----------------------------------------------------------------
  13972.  
  13973. procedure Scan_Signed_Number(
  13974.     T      : in     Scanner;
  13975.     Found  :    out boolean;
  13976.     Result :    out String_Type;
  13977.     Skip   : in     boolean := false
  13978.     ) is
  13979.  
  13980.     C     : character;
  13981.     S_Str : String_Type;
  13982.  
  13983. begin
  13984.  
  13985.     if Skip then
  13986.     Skip_Space(T);
  13987.     end if;
  13988.     if Is_Signed_Number(T) then
  13989.     C := Get(T);
  13990.     if C = '+' or C = '-' then
  13991.         Forward(T);
  13992.     end if;
  13993.     Scan_Number(T, Found, S_Str);
  13994.     String_Pkg.Mark;
  13995.     if C = '+' or C = '-' then
  13996.         Result := String_Pkg.Make_Persistent(("" & C) & S_Str);
  13997.     else
  13998.         Result := String_Pkg.Make_Persistent(S_Str);
  13999.     end if;
  14000.     String_Pkg.Release;
  14001.     String_Pkg.Flush(S_Str);
  14002.     else
  14003.     Found := false;
  14004.     end if;
  14005.  
  14006. end Scan_Signed_Number;
  14007.  
  14008. ----------------------------------------------------------------
  14009.  
  14010. procedure Scan_Signed_Number(
  14011.     T      : in     Scanner;
  14012.     Found  :    out boolean;
  14013.     Result :    out integer;
  14014.     Skip   : in     boolean := false
  14015.     ) is
  14016.  
  14017.     F     : boolean;
  14018.     S_Str : String_Type;
  14019.  
  14020. begin
  14021.  
  14022.     Scan_Signed_Number(T, F, S_Str, Skip);
  14023.     if F then
  14024.     Result := integer'value(String_Pkg.Value(S_Str));
  14025.     end if;
  14026.     Found := F;
  14027.  
  14028. end Scan_Signed_Number;
  14029.                                                     pragma Page;
  14030. function Is_Space(
  14031.     T : in Scanner
  14032.     ) return boolean is
  14033.  
  14034. begin
  14035.  
  14036.     return Is_Any(T, White_Space);
  14037.  
  14038. end Is_Space;
  14039.  
  14040. ----------------------------------------------------------------
  14041.  
  14042. procedure Scan_Space(
  14043.     T      : in     Scanner;
  14044.     Found  :    out boolean;
  14045.     Result :    out String_Type
  14046.     ) is
  14047.  
  14048.     S_Str : String_Type;
  14049.  
  14050. begin
  14051.  
  14052.     String_Pkg.Mark;
  14053.     Scan_Any(T, White_Space, Found, S_Str);
  14054.     Result := String_Pkg.Make_Persistent(S_Str);
  14055.     String_Pkg.Release;
  14056.  
  14057. end Scan_Space;
  14058.  
  14059. ----------------------------------------------------------------
  14060.  
  14061. procedure Skip_Space(
  14062.     T : in Scanner
  14063.     ) is
  14064.  
  14065.     S_Str : String_Type;
  14066.     Found : boolean;
  14067.  
  14068. begin
  14069.  
  14070.     String_Pkg.Mark;
  14071.     Scan_Any(T, White_Space, Found, S_Str);
  14072.     String_Pkg.Release;
  14073.  
  14074. end Skip_Space;
  14075.                                                     pragma Page;
  14076. function Is_Ada_Id(
  14077.     T : in Scanner
  14078.     ) return boolean is
  14079.  
  14080. begin
  14081.  
  14082.     return Is_Any(T, Ada_Id_1);
  14083.  
  14084. end Is_Ada_Id;
  14085.  
  14086. ----------------------------------------------------------------
  14087.  
  14088. procedure Scan_Ada_Id(
  14089.     T      : in     Scanner;
  14090.     Found  :    out boolean;
  14091.     Result :    out String_Type;
  14092.     Skip   : in     boolean := false
  14093.     ) is
  14094.  
  14095.     C     : character;
  14096.     F     : boolean;
  14097.     S_Str : String_Type;
  14098.  
  14099. begin
  14100.  
  14101.     if Skip then
  14102.     Skip_Space(T);
  14103.     end if;
  14104.     if Is_Ada_Id(T) then
  14105.     String_Pkg.Mark;
  14106.     Next(T, C);
  14107.     Scan_Any(T, Ada_Id, F, S_Str);
  14108.     Result := String_Pkg.Make_Persistent(("" & C) & S_Str);
  14109.     Found := true;
  14110.     String_Pkg.Release;
  14111.     else
  14112.     Found := false;
  14113.     end if;
  14114.  
  14115. end Scan_Ada_Id;
  14116.                                                     pragma Page;
  14117. function Is_Quoted(
  14118.     T : in Scanner
  14119.     ) return boolean is
  14120.  
  14121. begin
  14122.  
  14123.     if Quoted_String(T) = 0 then
  14124.     return false;
  14125.     else
  14126.     return true;
  14127.     end if;
  14128.  
  14129. end Is_Quoted;
  14130.  
  14131. ----------------------------------------------------------------
  14132.  
  14133. procedure Scan_Quoted(
  14134.     T      : in     Scanner;
  14135.     Found  :    out boolean;
  14136.     Result :    out String_Type;
  14137.     Skip   : in     boolean := false
  14138.     ) is
  14139.  
  14140.     Count : integer;
  14141.  
  14142. begin
  14143.  
  14144.     if Skip then
  14145.     Skip_Space(T);
  14146.     end if;
  14147.     Count := Quoted_String(T);
  14148.     if Count /= 0 then
  14149.     Count := Count - 2;
  14150.     T.index := T.index + 1;
  14151.     if Count /= 0 then
  14152.         String_Pkg.Mark;
  14153.         Result := String_Pkg.Make_Persistent
  14154.               (String_Pkg.Substr(T.text, T.index, positive(Count)));
  14155.         String_Pkg.Release;
  14156.     else
  14157.         Result := String_Pkg.Make_Persistent("");
  14158.     end if;
  14159.     T.index := T.index + Count + 1;
  14160.     Found := true;
  14161.     else
  14162.     Found := false;
  14163.     end if;
  14164.  
  14165. end Scan_Quoted;
  14166.                                                     pragma Page;
  14167. function Is_Enclosed(
  14168.     B : in character;
  14169.     E : in character;
  14170.     T : in Scanner
  14171.     ) return boolean is
  14172.  
  14173. begin
  14174.  
  14175.     if Enclosed_String(B, E, T) = 0 then
  14176.     return false;
  14177.     else
  14178.     return true;
  14179.     end if;
  14180.  
  14181. end Is_Enclosed;
  14182.  
  14183. ----------------------------------------------------------------
  14184.  
  14185. procedure Scan_Enclosed(
  14186.     B      : in     character;
  14187.     E      : in     character;
  14188.     T      : in     Scanner;
  14189.     Found  :    out boolean;
  14190.     Result :    out String_Type;
  14191.     Skip   : in     boolean := false
  14192.     ) is
  14193.  
  14194.     Count : natural;
  14195.  
  14196. begin
  14197.  
  14198.     if Skip then
  14199.     Skip_Space(T);
  14200.     end if;
  14201.     Count := Enclosed_String(B, E, T);
  14202.     if Count /= 0 then
  14203.     Count := Count - 2;
  14204.     T.index := T.index + 1;
  14205.     if Count /= 0 then
  14206.         String_Pkg.Mark;
  14207.         Result := String_Pkg.Make_Persistent(String_Pkg.Substr(T.text, T.index, positive(Count)));
  14208.         String_Pkg.Release;
  14209.     else
  14210.         Result := String_Pkg.Make_Persistent("");
  14211.     end if;
  14212.     T.index := T.index + Count + 1;
  14213.     Found := true;
  14214.     else
  14215.     Found := false;
  14216.     end if;
  14217.  
  14218. end Scan_Enclosed;
  14219.                                                     pragma Page;
  14220. function Is_Sequence(
  14221.     Chars  : in String_Type;
  14222.     T      : in Scanner
  14223.     ) return boolean is
  14224.  
  14225. begin
  14226.  
  14227.     return Is_Any(T, String_Pkg.Value(Chars));
  14228.  
  14229. end Is_Sequence;
  14230.  
  14231. ----------------------------------------------------------------
  14232.  
  14233. function Is_Sequence(
  14234.     Chars  : in string;
  14235.     T      : in Scanner
  14236.     ) return boolean is
  14237.  
  14238. begin
  14239.  
  14240.     return Is_Any(T, Chars);
  14241.  
  14242. end Is_Sequence;
  14243.  
  14244. ----------------------------------------------------------------
  14245.  
  14246. procedure Scan_Sequence(
  14247.     Chars  : in     String_Type;
  14248.     T      : in     Scanner;
  14249.     Found  :    out boolean;
  14250.     Result :    out String_Type;
  14251.     Skip   : in     boolean := false
  14252.     ) is
  14253.  
  14254.     I     : positive;
  14255.     Count : integer := 0;
  14256.  
  14257. begin
  14258.  
  14259.     if Skip then
  14260.     Skip_Space(T);
  14261.     end if;
  14262.     if not Is_Valid(T) then
  14263.     Found := false;
  14264.     return;
  14265.     end if;
  14266.     I := T.index;
  14267.     while Is_Any(T, Value(Chars)) loop
  14268.     Forward(T);
  14269.     Count := Count + 1;
  14270.     end loop;
  14271.     if Count /= 0 then
  14272.     String_Pkg.Mark;
  14273.     Result := String_Pkg.Make_Persistent
  14274.           (String_Pkg.Substr(T.text, I, positive(Count)));
  14275.     Found  := true;
  14276.     String_Pkg.Release;
  14277.     else
  14278.     Found := false;
  14279.     end if;
  14280.  
  14281. end Scan_Sequence;
  14282.  
  14283. ----------------------------------------------------------------
  14284.  
  14285. procedure Scan_Sequence(
  14286.     Chars  : in     string;
  14287.     T      : in     Scanner;
  14288.     Found  :    out boolean;
  14289.     Result :    out String_Type;
  14290.     Skip   : in     boolean := false
  14291.     ) is
  14292.  
  14293. begin
  14294.  
  14295.     String_Pkg.Mark;
  14296.     Scan_Sequence(String_Pkg.Create(Chars), T, Found, Result, Skip);
  14297.     String_Pkg.Release;
  14298.  
  14299. end Scan_Sequence;
  14300.                                                     pragma Page;
  14301. function Is_Not_Sequence(
  14302.     Chars  : in String_Type;
  14303.     T      : in Scanner
  14304.     ) return boolean is
  14305.  
  14306.     N : natural;
  14307.  
  14308. begin
  14309.  
  14310.     if not Is_Valid(T) then
  14311.     return false;
  14312.     end if;
  14313.     String_Pkg.Mark;
  14314.     N := String_Pkg.Match_Any(T.text, Chars, T.index);
  14315.     if N = T.index then
  14316.     N := 0;
  14317.     end if;
  14318.     String_Pkg.Release;
  14319.     return N /= 0;
  14320.  
  14321. end Is_Not_Sequence;
  14322.  
  14323. ----------------------------------------------------------------
  14324.  
  14325. function Is_Not_Sequence(
  14326.     Chars  : in string;
  14327.     T      : in Scanner
  14328.     ) return boolean is
  14329.  
  14330. begin
  14331.  
  14332.     return Is_Not_Sequence(String_Pkg.Create(Chars), T);
  14333.  
  14334. end Is_Not_Sequence;
  14335.  
  14336. ----------------------------------------------------------------
  14337.  
  14338. procedure Scan_Not_Sequence(
  14339.     Chars  : in     string;
  14340.     T      : in     Scanner;
  14341.     Found  :    out boolean;
  14342.     Result :    out String_Type;
  14343.     Skip   : in     boolean := false
  14344.     ) is
  14345.  
  14346.     N     : natural;
  14347.  
  14348. begin
  14349.  
  14350.     if Skip then
  14351.     Skip_Space(T);
  14352.     end if;
  14353.     if Is_Not_Sequence(Chars, T) then
  14354.     String_Pkg.Mark;
  14355.     N := String_Pkg.Match_Any(T.text, Chars, T.index);
  14356.     Result := String_Pkg.Make_Persistent
  14357.           (String_Pkg.Substr(T.text, T.index, N - T.index));
  14358.     T.index := N;
  14359.     Found   := true;
  14360.     String_Pkg.Release;
  14361.     else
  14362.     Found := false;
  14363.     end if;
  14364.  
  14365. end Scan_Not_Sequence;
  14366.  
  14367. ----------------------------------------------------------------
  14368.  
  14369. procedure Scan_Not_Sequence(
  14370.     Chars  : in     String_Type;
  14371.     T      : in     Scanner;
  14372.     Found  :    out boolean;
  14373.     Result :    out String_Type;
  14374.     Skip   : in     boolean := false
  14375.     ) is
  14376.  
  14377. begin
  14378.  
  14379.     Scan_Not_Sequence(String_Pkg.Value(Chars), T, Found, Result, Skip);
  14380.  
  14381. end Scan_Not_Sequence;
  14382.                                                     pragma Page;
  14383. function Is_Literal(
  14384.     Chars  : in String_Type;
  14385.     T      : in Scanner
  14386.     ) return boolean is
  14387.  
  14388.     N : natural;
  14389.  
  14390. begin
  14391.  
  14392.     if not Is_Valid(T) then
  14393.     return false;
  14394.     end if;
  14395.     String_Pkg.Mark;
  14396.     N := String_Pkg.Match_S(T.text, Chars, T.index);
  14397.     if N /= T.index then
  14398.     N := 0;
  14399.     end if;
  14400.     String_Pkg.Release;
  14401.     return N /= 0;
  14402.  
  14403. end Is_Literal;
  14404.  
  14405. ----------------------------------------------------------------
  14406.  
  14407. function Is_Literal(
  14408.     Chars  : in string;
  14409.     T      : in Scanner
  14410.     ) return boolean is
  14411.  
  14412.     Found : boolean;
  14413.  
  14414. begin
  14415.  
  14416.     String_Pkg.Mark;
  14417.     Found := Is_Literal(String_Pkg.Create(Chars), T);
  14418.     String_Pkg.Release;
  14419.     return Found;
  14420.  
  14421. end Is_Literal;
  14422.  
  14423. ----------------------------------------------------------------
  14424.  
  14425. procedure Scan_Literal(
  14426.     Chars  : in     String_Type;
  14427.     T      : in     Scanner;
  14428.     Found  :    out boolean;
  14429.     Skip   : in     boolean := false
  14430.     ) is
  14431.  
  14432. begin
  14433.  
  14434.     if Skip then
  14435.     Skip_Space(T);
  14436.     end if;
  14437.     if Is_Literal(Chars, T) then
  14438.     T.index := T.index + String_Pkg.Length(Chars);
  14439.     Found   := true;
  14440.     else
  14441.     Found   := false;
  14442.     end if;
  14443.  
  14444. end Scan_Literal;
  14445.  
  14446. ----------------------------------------------------------------
  14447.  
  14448. procedure Scan_Literal(
  14449.     Chars  : in     string;
  14450.     T      : in     Scanner;
  14451.     Found  :    out boolean;
  14452.     Skip   : in     boolean := false
  14453.     ) is
  14454.  
  14455. begin
  14456.  
  14457.     String_Pkg.Mark;
  14458.     Scan_Literal(String_Pkg.Create(Chars), T, Found, Skip);
  14459.     String_Pkg.Release;
  14460.  
  14461. end Scan_Literal;
  14462.                                                     pragma Page;
  14463. function Is_Not_Literal(
  14464.     Chars : in string;
  14465.     T     : in Scanner
  14466.     ) return boolean is
  14467.  
  14468.     N     : natural;
  14469.  
  14470. begin
  14471.  
  14472.     if not Is_Valid(T) then
  14473.     return false;
  14474.     end if;
  14475.     String_Pkg.Mark;
  14476.     N := String_Pkg.Match_S(T.text, Chars, T.index);
  14477.     if N = T.index then
  14478.     N := 0;
  14479.     end if;
  14480.     String_Pkg.Release;
  14481.     return N /= 0;
  14482.  
  14483. end Is_Not_Literal;
  14484.  
  14485. ----------------------------------------------------------------
  14486.  
  14487. function Is_Not_Literal(
  14488.     Chars : in String_Type;
  14489.     T     : in Scanner
  14490.     ) return boolean is
  14491.  
  14492. begin
  14493.  
  14494.     if not More(T) then
  14495.     return false;
  14496.     end if;
  14497.     return Is_Not_Literal(String_Pkg.Value(Chars), T);
  14498.  
  14499. end Is_Not_Literal;
  14500.  
  14501. ----------------------------------------------------------------
  14502.  
  14503. procedure Scan_Not_Literal(
  14504.     Chars  : in     string;
  14505.     T      : in     Scanner;
  14506.     Found  :    out boolean;
  14507.     Result :    out String_Type;
  14508.     Skip   : in     boolean := false
  14509.     ) is
  14510.  
  14511.     N : natural;
  14512.  
  14513. begin
  14514.  
  14515.     if Skip then
  14516.     Skip_Space(T);
  14517.     end if;
  14518.     if Is_Not_Literal(Chars, T) then
  14519.     String_Pkg.Mark;
  14520.     N := String_Pkg.Match_S(T.text, Chars, T.index);
  14521.     Result := String_Pkg.Make_Persistent(String_Pkg.Substr(T.text, T.index, N - T.index));
  14522.     T.index := N;
  14523.     Found   := true;
  14524.     String_Pkg.Release;
  14525.     else
  14526.     Found := false;
  14527.     return;
  14528.     end if;
  14529.  
  14530. end Scan_Not_Literal;
  14531.  
  14532. ----------------------------------------------------------------
  14533.  
  14534. procedure Scan_Not_Literal(
  14535.     Chars  : in     String_Type;
  14536.     T      : in     Scanner;
  14537.     Found  :    out boolean;
  14538.     Result :    out String_Type;
  14539.     Skip   : in     boolean := false
  14540.     ) is
  14541.  
  14542. begin
  14543.  
  14544.     Scan_Not_Literal(String_Pkg.Value(Chars), T, Found, Result, Skip);
  14545.  
  14546. end Scan_Not_Literal;
  14547.  
  14548.  
  14549. end String_Scanner;
  14550.                                                     pragma Page;
  14551. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14552. --SORT.SPC
  14553. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14554. -- $Source: /nosc/work/abstractions/sort/RCS/sort.spc,v $
  14555. -- $Revision: 1.2 $ -- $Date: 85/01/31 16:43:49 $ -- $Author: ron $
  14556.  
  14557. -- $Source: /nosc/work/abstractions/sort/RCS/sort.spc,v $
  14558. -- $Revision: 1.2 $ -- $Date: 85/01/31 16:43:49 $ -- $Author: ron $
  14559.  
  14560. generic
  14561.     type item_type is private;
  14562.         --| Component type of array to be sorted.
  14563.     
  14564.     with function "<="(x, y: item_type) return boolean;
  14565.         --| Required to totally order item_type;
  14566.     
  14567.     type index_type is (<>);
  14568.         --| Index type of array to be sorted.
  14569.     
  14570.     type sequence is array(index_type range <>) of item_type;
  14571.         --| Type of array to be sorted.
  14572.  
  14573. procedure heap_sort(s: in out sequence);
  14574.     --| Overview:
  14575.     --| Heap sort is an O(n lg n) guaranteed time sorting algorithm.
  14576.     --| This procedure provides heap sort for arrays of arbitrary index
  14577.     --| and component type.
  14578.  
  14579.     --| Notes:
  14580.     --| Programmer: Ron Kownacki
  14581.  
  14582.     --| Effects:
  14583.     --|     Let s1 and s2 denote the value of s before and after an
  14584.     --| invocation of heap_sort.  Then s1 and s2 have the following
  14585.     --| properties:
  14586.     --|   1. For i,j in s'range, i <= j implies that s2(i) <= s2(j).
  14587.     --|   2. s2(s'first) through s2(s'last) is a permutation of
  14588.     --|      s1(s'first) through s1(s'last).
  14589.     --|
  14590.     --| Requires:
  14591.     --|     <= must form a total order over item_type.
  14592.     --|
  14593.     --| Algorithm:
  14594.     --|     The algorithm is described in Knuth, vol 3, and Aho et al,
  14595.     --| The Design and Analysis of Computer Algorithms.
  14596.  
  14597. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14598. --SORT.BDY
  14599. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14600. -- $Source: /nosc/work/abstractions/sort/RCS/sort.bdy,v $
  14601. -- $Revision: 1.2 $ -- $Date: 85/02/01 10:10:41 $ -- $Author: ron $
  14602.  
  14603. -- $Source: /nosc/work/abstractions/sort/RCS/sort.bdy,v $
  14604. -- $Revision: 1.2 $ -- $Date: 85/02/01 10:10:41 $ -- $Author: ron $
  14605.  
  14606. procedure heap_sort(s: in out sequence) is
  14607.  
  14608. --| Notes:
  14609. --| Implementation is taken directly from The Design and Analysis of
  14610. --| Computer Algorithms, by Aho, Hopcroft and Ullman.  The only change
  14611. --| of any significance is code to map between the index_type subrange
  14612. --| defined by the sequence bounds and the subrange, 1..s'length, of
  14613. --| the integers.  This mapping is necessary because the algorithm
  14614. --| represents binary trees as an array such that the sons of s(i) are
  14615. --| located at s(2i) and s(2i + 1).
  14616.  
  14617.     subtype int_range is integer range 1..s'length;
  14618.  
  14619.     function int_range_to_index(i: int_range)
  14620.         return index_type is
  14621.       --| Effects:
  14622.       --| Map 1 --> s'first, ..., s'length --> s'last.
  14623.     begin
  14624.         return index_type'val(i + index_type'pos(s'first) - 1);
  14625.     end int_range_to_index;
  14626.  
  14627.     function index_to_int_range(i: index_type)
  14628.         return int_range is
  14629.       --| Effects:
  14630.       --| Map s'first --> 1, ..., s'last --> s'length.
  14631.     begin
  14632.         return (index_type'pos(i) - index_type'pos(s'first) + 1);
  14633.     end index_to_int_range;
  14634.  
  14635.     procedure swap(i, j: index_type) is
  14636.       --| Effects:
  14637.       --| Exchange the values of s(i) and s(j).
  14638.  
  14639.         t: item_type := s(i);
  14640.     begin
  14641.         s(i) := s(j);
  14642.         s(j) := t;
  14643.     end swap;
  14644.  
  14645.     procedure heapify(root, boundary: index_type) is
  14646.       --| Effects:
  14647.       --|     Give s(root..boundary) the heap property:
  14648.       --|        s(i) > s(2i) and s(i) > s(2i + 1).
  14649.       --| (provided that 2i, 2i + 1 are less than boundary.  Note that
  14650.       --| the property is being expressed in terms of the integer range,
  14651.       --| 1..s'last.)
  14652.       --| Requires:
  14653.       --|     s(i + 1, ..., boundary) already has the heap property.
  14654.  
  14655.         max: index_type := root;
  14656.         boundary_position: int_range := index_to_int_range(boundary);
  14657.         left_son_position: integer := 2 * index_to_int_range(root);
  14658.         right_son_position: integer := 2 * index_to_int_range(root) + 1;
  14659.         left_son: index_type;
  14660.         right_son: index_type;
  14661.     begin
  14662.         -- If root is not a leaf, and if a son of root contains a larger
  14663.         -- value than the root value, then let max be the son with the
  14664.         -- largest value.
  14665.  
  14666.         if left_son_position <= boundary_position then    -- has left son?
  14667.             left_son := int_range_to_index(left_son_position);
  14668.             if s(root) <= s(left_son) then
  14669.                 max := left_son;
  14670.             end if;
  14671.         else
  14672.             return;   -- no sons, meets heap property trivially.
  14673.         end if;
  14674.  
  14675.         if right_son_position <= boundary_position then  -- has right son?
  14676.             right_son := int_range_to_index(right_son_position);
  14677.             if s(max) <= s(right_son) then              -- biggest so far?
  14678.                 max := right_son;
  14679.             end if;
  14680.         end if;
  14681.  
  14682.         if max /= root then          -- If a larger son found then
  14683.             swap(root, max);         -- carry out exchange and
  14684.             heapify(max, boundary);  -- propagate heap propery to subtree
  14685.         end if;
  14686.     end heapify;
  14687.  
  14688.     procedure build_heap is
  14689.       --| Effects:
  14690.       --| Give all of s the heap property.
  14691.  
  14692.         mid: index_type :=
  14693.                  int_range_to_index(index_to_int_range(s'last)/2);
  14694.     begin
  14695.         for i in reverse s'first..mid loop
  14696.             heapify(i, s'last);
  14697.         end loop;
  14698.     end build_heap;
  14699.  
  14700. begin
  14701.     -- Make s into a heap.  Then, repeat until sorted:
  14702.     --   1. exchange the largest element, located at the root, with the
  14703.     --      last element that has not yet been ordered, and
  14704.     --   2. reheapify the unsorted portion of s.
  14705.  
  14706.     build_heap;
  14707.     for i in reverse index_type'succ(s'first)..s'last loop
  14708.         swap(s'first, i);
  14709.         heapify(s'first, index_type'pred(i));
  14710.     end loop;
  14711.  
  14712. exception
  14713.     when constraint_error =>    -- On succ(s'first) for array of length <= 1.
  14714.         return;                 -- Such arrays are trivially sorted.
  14715. end heap_sort;
  14716.  
  14717. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14718. --STACK.SPC
  14719. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14720. -- $Source: /nosc/work/abstractions/stack/RCS/stack.spc,v $
  14721. -- $Revision: 1.5 $ -- $Date: 85/02/01 09:57:17 $ -- $Author: ron $
  14722.  
  14723. -- $Source: /nosc/work/abstractions/stack/RCS/stack.spc,v $
  14724. -- $Revision: 1.5 $ -- $Date: 85/02/01 09:57:17 $ -- $Author: ron $
  14725.  
  14726. with lists;     --| Implementation uses lists.  (private)
  14727.  
  14728. generic
  14729.     type elem_type is private;   --| Component element type.
  14730.  
  14731. package stack_pkg is
  14732.  
  14733. --| Overview:
  14734. --| This package provides the stack abstract data type.  Element type is
  14735. --| a generic formal parameter to the package.  There are no explicit
  14736. --| bounds on the number of objects that can be pushed onto a given stack.
  14737. --| All standard stack operations are provided.
  14738. --|
  14739. --| The following is a complete list of operations, written in the order
  14740. --| in which they appear in the spec.  Overloaded subprograms are followed
  14741. --| by (n), where n is the number of subprograms of that name.
  14742. --|
  14743. --| Constructors:
  14744. --|        create 
  14745. --|        push
  14746. --|        pop (2)
  14747. --|        copy
  14748. --| Query Operations:
  14749. --|        top
  14750. --|        size
  14751. --|        is_empty
  14752. --| Heap Management: 
  14753. --|        destroy
  14754.  
  14755.  
  14756. --| Notes:
  14757. --| Programmer: Ron Kownacki
  14758.  
  14759.     type stack is private;       --| The stack abstract data type.
  14760.     
  14761.   -- Exceptions:
  14762.   
  14763.     uninitialized_stack: exception;
  14764.         --| Raised on attempt to manipulate an uninitialized stack object.
  14765.     --| The initialization operations are create and copy.
  14766.  
  14767.     empty_stack: exception;
  14768.         --| Raised by some operations when empty.
  14769.  
  14770.  
  14771.   -- Constructors:
  14772.     
  14773.     function create
  14774.         return stack;
  14775.     
  14776.       --| Effects:
  14777.       --| Return the empty stack.
  14778.  
  14779.     procedure push(s: in out stack;
  14780.                    e:        elem_type);
  14781.  
  14782.       --| Raises: uninitialized_stack
  14783.       --| Effects:
  14784.       --| Push e onto the top of s.
  14785.       --| Raises uninitialized_stack iff s has not been initialized.
  14786.       
  14787.     procedure pop(s: in out stack);
  14788.       
  14789.       --| Raises: empty_stack, uninitialized_stack
  14790.       --| Effects:
  14791.       --| Pops the top element from s, and throws it away.
  14792.       --| Raises empty_stack iff s is empty.
  14793.       --| Raises uninitialized_stack iff s has not been initialized.
  14794.  
  14795.     procedure pop(s: in out stack;
  14796.           e: out    elem_type);
  14797.  
  14798.       --| Raises: empty_stack, uninitialized_stack
  14799.       --| Effects:
  14800.       --| Pops the top element from s, returns it as the e parameter.
  14801.       --| Raises empty_stack iff s is empty.
  14802.       --| Raises uninitialized_stack iff s has not been initialized.
  14803.       
  14804.     function copy(s: stack)
  14805.     return stack;
  14806.       
  14807.       --| Raises: uninitialized_stack
  14808.       --| Return a copy of s.
  14809.       --| Stack assignment and passing stacks as subprogram parameters
  14810.       --| result in the sharing of a single stack value by two stack
  14811.       --| objects; changes to one will be visible through the others.
  14812.       --| copy can be used to prevent this sharing.
  14813.       --| Raises uninitialized_stack iff s has not been initialized.
  14814.   
  14815.       
  14816.   -- Queries:
  14817.  
  14818.     function top(s: stack)
  14819.         return elem_type;
  14820.  
  14821.       --| Raises: empty_stack, uninitialized_stack
  14822.       --| Effects:
  14823.       --| Return the element on the top of s.  Raises empty_stack iff s is
  14824.       --| empty.
  14825.       --| Raises uninitialized_stack iff s has not been initialized.
  14826.       
  14827.     function size(s: stack)
  14828.         return natural;
  14829.  
  14830.       --| Raises: uninitialized_stack
  14831.       --| Effects:
  14832.       --| Return the current number of elements in s.
  14833.       --| Raises uninitialized_stack iff s has not been initialized.
  14834.  
  14835.     function is_empty(s: stack)
  14836.         return boolean;
  14837.  
  14838.       --| Raises: uninitialized_stack
  14839.       --| Effects:
  14840.       --| Return true iff s is empty.
  14841.       --| Raises uninitialized_stack iff s has not been initialized.
  14842.  
  14843.  
  14844.   -- Heap Management:
  14845.  
  14846.     procedure destroy(s: in out stack);
  14847.     
  14848.       --| Effects:
  14849.       --| Return the space consumed by s to the heap.  No effect if s is
  14850.       --| uninitialized.  In any case, leaves s in uninitialized state.
  14851.  
  14852.  
  14853. private
  14854.  
  14855.     package elem_list_pkg is new lists(elem_type);
  14856.     subtype elem_list is elem_list_pkg.list;
  14857.  
  14858.     type stack_rec is
  14859.         record
  14860.             size: natural := 0;
  14861.             elts: elem_list := elem_list_pkg.create;
  14862.         end record;
  14863.     
  14864.     type stack is access stack_rec;
  14865.  
  14866.     --| Let an instance of the representation type, r, be denoted by the
  14867.     --| pair, <size, elts>.  Dot selection is used to refer to these
  14868.     --| components.
  14869.     --|
  14870.     --| Representation Invariants:
  14871.     --|     r /= null
  14872.     --|     elem_list_pkg.length(r.elts) = r.size.
  14873.     --|
  14874.     --| Abstraction Function:
  14875.     --|     A(<size, elem_list_pkg.create>) = stack_pkg.create.
  14876.     --|     A(<size, elem_list_pkg.attach(e, l)>) = push(A(<size, l>), e).
  14877.  
  14878. end stack_pkg;
  14879.  
  14880. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14881. --STACK.BDY
  14882. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14883. -- $Source: /nosc/work/abstractions/stack/RCS/stack.bdy,v $
  14884. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:19:36 $ -- $Author: ron $
  14885.  
  14886. -- $Source: /nosc/work/abstractions/stack/RCS/stack.bdy,v $
  14887. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:19:36 $ -- $Author: ron $
  14888.  
  14889. with unchecked_deallocation;
  14890.  
  14891. package body stack_pkg is
  14892.  
  14893. --| Overview:
  14894. --| Implementation scheme is totally described by the statements of the
  14895. --| representation invariants and abstraction function that appears in
  14896. --| the package specification.  The implementation is so trivial that
  14897. --| further documentation is unnecessary.
  14898.  
  14899.     use elem_list_pkg;
  14900.     
  14901.     
  14902.   -- Constructors:
  14903.     
  14904.     function create
  14905.         return stack is
  14906.     begin
  14907.     return new stack_rec'(size => 0, elts => create);
  14908.     end create;
  14909.     
  14910.     procedure push(s: in out stack;
  14911.                    e:        elem_type) is
  14912.     begin
  14913.         s.size := s.size + 1;
  14914.         s.elts := attach(e, s.elts);
  14915.     exception
  14916.         when constraint_error =>
  14917.             raise uninitialized_stack;
  14918.     end push;
  14919.  
  14920.     procedure pop(s: in out stack) is
  14921.     begin
  14922.         DeleteHead(s.elts);
  14923.         s.size := s.size - 1;
  14924.     exception
  14925.         when EmptyList =>
  14926.             raise empty_stack;
  14927.     when constraint_error =>
  14928.         raise uninitialized_stack;
  14929.     end pop;
  14930.  
  14931.     procedure pop(s: in out stack;
  14932.                   e: out    elem_type) is
  14933.     begin
  14934.         e := FirstValue(s.elts);
  14935.         DeleteHead(s.elts);
  14936.         s.size := s.size - 1;
  14937.     exception
  14938.         when EmptyList =>
  14939.             raise empty_stack;
  14940.     when constraint_error =>
  14941.         raise uninitialized_stack;
  14942.     end pop;
  14943.     
  14944.     function copy(s: stack)
  14945.         return stack is
  14946.     begin
  14947.     if s = null then raise uninitialized_stack; end if;
  14948.     
  14949.     return new stack_rec'(size => s.size,
  14950.                   elts => copy(s.elts));
  14951.     end;
  14952.  
  14953.     
  14954.   -- Queries:
  14955.  
  14956.     function top(s: stack)
  14957.         return elem_type is
  14958.     begin
  14959.         return FirstValue(s.elts);
  14960.     exception
  14961.         when EmptyList =>
  14962.         raise empty_stack;
  14963.     when constraint_error =>
  14964.         raise uninitialized_stack;
  14965.     end top;
  14966.  
  14967.     function size(s: stack)
  14968.         return natural is
  14969.     begin
  14970.         return s.size;
  14971.     exception
  14972.         when constraint_error =>
  14973.         raise uninitialized_stack;
  14974.     end size;
  14975.  
  14976.     function is_empty(s: stack)
  14977.         return boolean is
  14978.     begin
  14979.         return s.size = 0;
  14980.     exception
  14981.         when constraint_error =>
  14982.         raise uninitialized_stack;
  14983.     end is_empty;
  14984.  
  14985.  
  14986.   -- Heap Management:
  14987.     
  14988.     procedure destroy(s: in out stack) is
  14989.         procedure free_stack is
  14990.         new unchecked_deallocation(stack_rec, stack);
  14991.     begin
  14992.     destroy(s.elts);
  14993.     free_stack(s);
  14994.     exception
  14995.         when constraint_error =>    -- stack is null
  14996.             return; 
  14997.     end destroy;
  14998.    
  14999. end stack_pkg;
  15000. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15001. --STRING.BDY
  15002. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15003. -- $Source: /nosc/work/abstractions/string/RCS/string.bdy,v $
  15004. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:58:51 $ -- $Author: ron $
  15005.  
  15006. -- $Source: /nosc/work/abstractions/string/RCS/string.bdy,v $
  15007. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:58:51 $ -- $Author: ron $
  15008.  
  15009. with unchecked_deallocation;
  15010. with lists, stack_pkg;
  15011.  
  15012. package body string_pkg is
  15013.  
  15014. --| Overview:
  15015. --| The implementation for most operations is fairly straightforward.
  15016. --| The interesting aspects involve the allocation and deallocation of
  15017. --| heap space.  This is done as follows:
  15018. --|
  15019. --|     1. A stack of accesses to lists of string_type values is set up
  15020. --|        so that the top of the stack always refers to a list of values
  15021. --|        that were allocated since the last invocation of mark.
  15022. --|        The stack is called scopes, referring to the dynamic scopes
  15023. --|        defined by the invocations of mark and release.
  15024. --|        There is an implicit invocation of mark when the
  15025. --|        package body is elaborated; this is implemented with an explicit 
  15026. --|        invocation in the package initialization code.
  15027. --|
  15028. --|     2. At each invocation of mark, a pointer to an empty list
  15029. --|        is pushed onto the stack.
  15030. --|
  15031. --|     3. At each invocation of release, all of the values in the
  15032. --|        list referred to by the pointer at the top of the stack are
  15033. --|        returned to the heap.  Then the list, and the pointer to it,
  15034. --|        are returned to the heap.  Finally, the stack is popped.
  15035.  
  15036.     package string_list_pkg is new lists(string_type);
  15037.     subtype string_list is string_list_pkg.list;
  15038.  
  15039.     type string_list_ptr is access string_list;
  15040.  
  15041.     package scope_stack_pkg is new stack_pkg(string_list_ptr);
  15042.     subtype scope_stack is scope_stack_pkg.stack;
  15043.  
  15044.     use string_list_pkg;
  15045.     use scope_stack_pkg;
  15046.  
  15047.     scopes: scope_stack;     -- See package body overview.
  15048.  
  15049.  
  15050.     -- Utility functions/procedures:
  15051.  
  15052.     function enter(s: string_type)
  15053.         return string_type;
  15054.  
  15055.       --| Raises: illegal_alloc
  15056.       --| Effects:
  15057.       --| Stores s, the address of s.all, in current scope list (top(scopes)),
  15058.       --| and returns s.  Useful for functions that create and return new
  15059.       --| string_type values.
  15060.       --| Raises illegal_alloc if the scopes stack is empty.
  15061.  
  15062.     function match_string(s1, s2: string; start: positive := 1)
  15063.         return natural;
  15064.  
  15065.       --| Raises: no_match
  15066.       --| Effects:
  15067.       --| Returns the minimum index, i, in s1'range such that
  15068.       --| s1(i..i + s2'length - 1) = s2.  Returns 0 if no such index.
  15069.       --| Requires:
  15070.       --| s1'first = 1.
  15071.  
  15072. -- Constructors:
  15073.  
  15074.     function create(s: string)
  15075.         return string_type is
  15076.         subtype constr_str is string(1..s'length);
  15077.         dec_s: constr_str := s;
  15078.     begin
  15079.           return enter(new constr_str'(dec_s));
  15080. -- DECada bug; above code (and decl of dec_s) replaces the following: 
  15081. --        return enter(new constr_str'(s));
  15082.     end create;
  15083.  
  15084.     function "&"(s1, s2: string_type)
  15085.         return string_type is
  15086.     begin
  15087.     if is_empty(s1) then return enter(make_persistent(s2)); end if;
  15088.     if is_empty(s2) then return enter(make_persistent(s1)); end if; 
  15089.         return create(s1.all & s2.all);
  15090.     end "&";
  15091.  
  15092.     function "&"(s1: string_type; s2: string)
  15093.         return string_type is
  15094.     begin
  15095.     if s1 = null then return create(s2); end if; 
  15096.     return create(s1.all & s2); 
  15097.     end "&";
  15098.  
  15099.     function "&"(s1: string; s2: string_type)
  15100.         return string_type is
  15101.     begin
  15102.     if s2 = null then return create(s1); end if; 
  15103.     return create(s1 & s2.all); 
  15104.     end "&";
  15105.     
  15106.     function substr(s: string_type; i: positive; len: natural)
  15107.         return string_type is
  15108.     begin
  15109.         if len = 0 then return null; end if; 
  15110.         return create(s(i..(i + len - 1)));
  15111.     exception
  15112.     when constraint_error =>      -- on array fetch or null deref
  15113.         raise bounds;
  15114.     end substr;
  15115.  
  15116.     function splice(s: string_type; i: positive; len: natural)
  15117.         return string_type is
  15118.     begin
  15119.         if len = 0 then return enter(make_persistent(s)); end if;
  15120.         if i + len - 1 > length(s) then raise bounds; end if; 
  15121.  
  15122.         return create(s(1..(i - 1)) & s((i + len)..length(s)));
  15123.     end splice;
  15124.  
  15125.     function insert(s1, s2: string_type; i: positive)
  15126.         return string_type is
  15127.     begin
  15128.         if i > length(s1) then raise bounds; end if;
  15129.     if is_empty(s2) then return create(s1.all); end if;
  15130.  
  15131.         return create(s1(1..(i - 1)) & s2.all & s1(i..s1'last));
  15132.     end insert;
  15133.  
  15134.     function insert(s1: string_type; s2: string; i: positive)
  15135.         return string_type is
  15136.     begin
  15137.         if i > length(s1) then raise bounds; end if;
  15138.  
  15139.         return create(s1(1..(i - 1)) & s2 & s1(i..s1'last));
  15140.     end insert;
  15141.  
  15142.     function insert(s1: string; s2: string_type; i: positive)
  15143.         return string_type is
  15144.     begin
  15145.         if not (i in s1'range) then raise bounds; end if;
  15146.     if s2 = null then return create(s1); end if; 
  15147.  
  15148.         return create(s1(s1'first..(i - 1)) & s2.all & s1(i..s1'last));
  15149.     end insert;
  15150.  
  15151.     function lower(s: string)
  15152.     return string_type is  
  15153.     s2: string_type := create(s); 
  15154.  
  15155.     procedure lc(c: in out character) is
  15156.     begin 
  15157.         if ('A' <= c) and then (c <= 'Z') then
  15158.         c := character'val(character'pos(c) - character'pos('A')
  15159.                             + character'pos('a'));
  15160.         end if; 
  15161.     end lc; 
  15162.  
  15163.     begin
  15164.     for i in s2'range loop
  15165.         lc(s2(i));
  15166.     end loop;
  15167.     return s2; 
  15168.     end lower; 
  15169.  
  15170.     function lower(s: string_type)
  15171.     return string_type is
  15172.     begin
  15173.     if s = null then return null; end if; 
  15174.     return lower(s.all);
  15175.     end lower;
  15176.  
  15177.     function upper(s: string)
  15178.     return string_type is
  15179.     s2: string_type := create(s); 
  15180.  
  15181.     procedure uc(c: in out character) is
  15182.     begin 
  15183.         if ('a' <= c) and then (c <= 'z') then
  15184.         c := character'val(character'pos(c) - character'pos('a')
  15185.                             + character'pos('A'));
  15186.         end if; 
  15187.     end uc; 
  15188.  
  15189.     begin
  15190.     for i in s2'range loop
  15191.         uc(s2(i));
  15192.     end loop;
  15193.     return s2; 
  15194.     end upper; 
  15195.  
  15196.     function upper(s: string_type)
  15197.     return string_type is
  15198.     begin
  15199.     if s = null then return null; end if; 
  15200.     return upper(s.all);
  15201.     end upper;
  15202.       
  15203.     
  15204. -- Heap Management:
  15205.  
  15206.     function make_persistent(s: string_type)
  15207.     return string_type is
  15208.         subtype constr_str is string(1..length(s));
  15209.     begin
  15210.         if s = null or else s.all = "" then return null;
  15211.         else return new constr_str'(s.all);
  15212.         end if; 
  15213.     end make_persistent; 
  15214.     
  15215.     function make_persistent(s: string)
  15216.     return string_type is
  15217.         subtype constr_str is string(1..s'length);
  15218.     begin
  15219.     if s = "" then return null; 
  15220.         else return new constr_str'(s); end if; 
  15221.     end make_persistent; 
  15222.     
  15223.     procedure real_flush is new unchecked_deallocation(string,
  15224.                                                        string_type);
  15225.       --| Effect:
  15226.       --| Return space used by argument to heap.  Does nothing if null.
  15227.       --| Notes:
  15228.       --| This procedure is actually the body for the flush procedure,
  15229.       --| but a generic instantiation cannot be used as a body for another
  15230.       --| procedure.  You tell me why.
  15231.  
  15232.     procedure flush(s: in out string_type) is
  15233.     begin
  15234.         if s /= null then real_flush(s); end if;
  15235.         -- Actually, the if isn't needed; however, DECada compiler chokes
  15236.         -- on deallocation of null.
  15237.     end flush;
  15238.  
  15239.     procedure mark is
  15240.     begin
  15241.         push(scopes, new string_list'(create));
  15242.     end mark;
  15243.  
  15244.     procedure release is
  15245.         procedure flush_list_ptr is
  15246.             new unchecked_deallocation(string_list, string_list_ptr);
  15247.         iter: string_list_pkg.ListIter;
  15248.         top_list: string_list_ptr;
  15249.         s: string_type;
  15250.     begin
  15251.         pop(scopes, top_list);
  15252.         iter := MakeListIter(top_list.all);
  15253.         while more(iter) loop
  15254.             next(iter, s);
  15255.             flush(s);             -- real_flush is bad, DECada bug
  15256. --          real_flush(s);            
  15257.         end loop;
  15258.         destroy(top_list.all);
  15259.         flush_list_ptr(top_list);
  15260.     exception
  15261.         when empty_stack =>
  15262.             raise illegal_dealloc;
  15263.     end release;
  15264.     
  15265.     
  15266. -- Queries:
  15267.  
  15268.     function is_empty(s: string_type)
  15269.         return boolean is
  15270.     begin
  15271.         return (s = null) or else (s.all = "");
  15272.     end is_empty;
  15273.  
  15274.     function length(s: string_type)
  15275.         return natural is
  15276.     begin
  15277.     if s = null then return 0; end if; 
  15278.         return(s.all'length);
  15279.     end length;
  15280.  
  15281.     function value(s: string_type)
  15282.         return string is
  15283.         subtype null_range is positive range 1..0;
  15284.         subtype null_string is string(null_range);
  15285.     begin
  15286.     if s = null then return null_string'(""); end if; 
  15287.         return s.all;
  15288.     end value;
  15289.  
  15290.     function fetch(s: string_type; i: positive)
  15291.         return character is
  15292.     begin
  15293.     if is_empty(s) or else (not (i in s'range)) then raise bounds; end if; 
  15294.         return s(i);
  15295.     end fetch;
  15296.  
  15297.     function equal(s1, s2: string_type)
  15298.         return boolean is
  15299.     begin
  15300.         if is_empty(s1) then return is_empty(s2); end if; 
  15301.         return (s2 /= null) and then (s1.all = s2.all); 
  15302. -- The above code replaces the following.  (DECada buggy)
  15303. --        return s1.all = s2.all;
  15304. --    exception
  15305. --    when constraint_error =>     -- s is null
  15306. --        return is_empty(s1) and is_empty(s2);
  15307.     end equal;
  15308.  
  15309.     function equal(s1: string_type; s2: string)
  15310.         return boolean is
  15311.     begin
  15312.     if s1 = null then return s2 = ""; end if; 
  15313.         return s1.all = s2;
  15314.     end equal;
  15315.  
  15316.     function equal(s1: string; s2: string_type)
  15317.         return boolean is
  15318.     begin
  15319.     if s2 = null then return s1 = ""; end if; 
  15320.         return s1 = s2.all;
  15321.     end equal;
  15322.  
  15323.     function "<"(s1: string_type; s2: string_type)
  15324.         return boolean is
  15325.     begin
  15326.         if is_empty(s1) then 
  15327.         return (not is_empty(s2)); 
  15328.         else 
  15329.         return (s1.all < s2); 
  15330.         end if; 
  15331. -- Got rid of the following code:  (Think that DECada is buggy)
  15332.         --return s1.all < s2.all; 
  15333.     --exception
  15334.         --when constraint_error =>   -- on null deref
  15335.         --return (not is_empty(s2)); 
  15336.            -- one of them must be empty
  15337.     end "<";
  15338.  
  15339.     function "<"(s1: string_type; s2: string)
  15340.         return boolean is 
  15341.     begin
  15342.     if s1 = null then return s2 /= ""; end if; 
  15343.         return s1.all < s2; 
  15344.     end "<";
  15345.  
  15346.     function "<"(s1: string; s2: string_type)
  15347.         return boolean is 
  15348.     begin
  15349.     if s2 = null then return false; end if; 
  15350.         return s1 < s2.all; 
  15351.     end "<";
  15352.  
  15353.     function "<="(s1: string_type; s2: string_type)
  15354.         return boolean is 
  15355.     begin
  15356.     if is_empty(s1) then return true; end if; 
  15357.     return (s1.all <= s2); 
  15358.  
  15359.     -- Replaces the following:  (I think DECada is buggy)
  15360.         --return s1.all <= s2.all; 
  15361.     --exception
  15362.         --when constraint_error =>   -- on null deref
  15363.             --return is_empty(s1);   -- one must be empty, so s1<=s2 iff s1 = ""
  15364.     end "<=";
  15365.  
  15366.     function "<="(s1: string_type; s2: string)
  15367.         return boolean is 
  15368.     begin
  15369.     if s1 = null then return true; end if; 
  15370.         return s1.all <= s2; 
  15371.     end "<=";
  15372.  
  15373.     function "<="(s1: string; s2: string_type)
  15374.         return boolean is 
  15375.     begin
  15376.     if s2 = null then return s1 = ""; end if; 
  15377.         return s1 <= s2.all; 
  15378.     end "<=";
  15379.  
  15380.     function match_c(s: string_type; c: character; start: positive := 1)
  15381.         return natural is
  15382.     begin
  15383.     if s = null then return 0; end if; 
  15384.         for i in start..s.all'last loop
  15385.             if s(i) = c then
  15386.                 return i;
  15387.             end if;
  15388.         end loop;
  15389.         return 0;
  15390.     end match_c;
  15391.  
  15392.     function match_not_c(s: string_type; c: character; start: positive := 1)
  15393.         return natural is
  15394.     begin
  15395.     if s = null then return 0; end if; 
  15396.         for i in start..s.all'last loop
  15397.         if s(i) /= c then
  15398.         return i;
  15399.         end if;
  15400.         end loop;
  15401.     return 0;
  15402.     end match_not_c;
  15403.  
  15404.     function match_s(s1, s2: string_type; start: positive := 1)
  15405.         return natural is
  15406.     begin
  15407.     if (s1 = null) or else (s2 = null) then return 0; end if; 
  15408.         return match_string(s1.all, s2.all, start);
  15409.     end match_s;
  15410.  
  15411.     function match_s(s1: string_type; s2: string; start: positive := 1)
  15412.         return natural is
  15413.     begin
  15414.     if s1 = null then return 0; end if; 
  15415.         return match_string(s1.all, s2, start);
  15416.     end match_s;
  15417.  
  15418.     function match_any(s, any: string_type; start: positive := 1)
  15419.         return natural is
  15420.     begin
  15421.     if any = null then raise any_empty; end if; 
  15422.         return match_any(s, any.all, start);
  15423.     end match_any;
  15424.  
  15425.     function match_any(s: string_type; any: string; start: positive := 1)
  15426.         return natural is
  15427.     begin
  15428.         if any = "" then raise any_empty; end if;
  15429.         if s = null then return 0; end if;
  15430.  
  15431.         for i in start..s.all'last loop
  15432.             for j in any'range loop
  15433.                 if s(i) = any(j) then
  15434.                     return i;
  15435.                 end if;
  15436.             end loop;
  15437.         end loop;
  15438.         return 0;
  15439.     end match_any;
  15440.  
  15441.     function match_none(s, none: string_type; start: positive := 1)
  15442.         return natural is
  15443.     begin
  15444.     if is_empty(s) then return 0; end if; 
  15445.     if is_empty(none) then return 1; end if; 
  15446.  
  15447.         return match_none(s, none.all, start);
  15448.     end match_none;
  15449.  
  15450.     function match_none(s: string_type; none: string; start: positive := 1)
  15451.         return natural is
  15452.         found: boolean;
  15453.     begin
  15454.     if is_empty(s) then return 0; end if; 
  15455.  
  15456.         for i in start..s.all'last loop
  15457.             found := true;
  15458.             for j in none'range loop
  15459.                 if s(i) = none(j) then
  15460.                     found := false;
  15461.                     exit;
  15462.                 end if;
  15463.             end loop;
  15464.             if found then return i; end if;
  15465.         end loop;
  15466.         return 0;
  15467.     end match_none;
  15468.  
  15469.  
  15470.     -- Utilities:
  15471.  
  15472.     function enter(s: string_type)
  15473.         return string_type is
  15474.     begin
  15475.         top(scopes).all := attach(top(scopes).all, s);
  15476.         return s;
  15477.     exception
  15478.         when empty_stack =>
  15479.             raise illegal_alloc;
  15480.     end enter;
  15481.  
  15482.     function match_string(s1, s2: string; start: positive := 1)
  15483.         return natural is
  15484.         offset: natural;
  15485.     begin
  15486.         offset := s2'length - 1;
  15487.         for i in start..(s1'last - offset) loop
  15488.             if s1(i..(i + offset)) = s2 then
  15489.                 return i;
  15490.             end if;
  15491.         end loop;
  15492.         return 0; 
  15493.     exception when constraint_error =>    -- on offset := s2'length (= 0)
  15494.         return 0; 
  15495.     end match_string;
  15496.  
  15497. begin    -- Initialize the scopes stack with an implicit mark.
  15498.     scopes := create;
  15499.     mark;
  15500. end string_pkg;
  15501.  
  15502. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15503. --BTREES.SPC
  15504. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15505.  
  15506. with Lists;
  15507. generic
  15508.  
  15509.     type ItemType is private; 
  15510.                        --| Information being contained in a node of tree
  15511.  
  15512.  
  15513.     with function "<"(X,Y: in ItemType) return boolean;
  15514.                        --| Function which defines ordering of nodes
  15515.  
  15516. package BinaryTrees is 
  15517.  
  15518.  
  15519. --| Overview
  15520. --| This package creates an ordered binary tree.  This will allow for 
  15521. --| quick insertion, and search.  
  15522. --|
  15523. --| The tree is organized such that 
  15524. --|  
  15525. --|  leftchild < root    root < rightchild
  15526. --| 
  15527. --| This means that by doing a left to right search of the tree will can
  15528. --| produce the nodes of the tree in ascending order.
  15529.  
  15530.  
  15531.  
  15532.  
  15533.  
  15534. --                             Types
  15535. --                             -----
  15536.  
  15537. type Tree is  private;     --| This is the type exported to represent the
  15538.                            --| tree.
  15539.  
  15540.  
  15541. type TreeIter is private;  --| This is the type which is used to iterate
  15542.                            --| over the set.
  15543.  
  15544. --|                          Exceptions
  15545. --|                          ----------
  15546.  
  15547. --|                          Operations
  15548. --|                          ----------
  15549. --|
  15550. --| Create           Creates a tree.
  15551. --| Deposit          Replaces the given node's information with 
  15552. --|                  the given information.
  15553. --| DestroyTree      Destroys the given tree and returns the spaces.
  15554. --| InsertNode       This inserts a node n into a tree t.
  15555. --| MakeTreeIter     This returns an iterator to the user in order to start
  15556. --|                  an iteration.
  15557. --| More             This returns true if there are more elements to iterate
  15558. --|                  over in the tree.
  15559. --| Next             This returns the information associated with the current
  15560. --|                  iterator and advances the iterator.
  15561.        
  15562.  
  15563. ---------------------------------------------------------------------------
  15564.  
  15565. function Create             --| This function creates the tree.
  15566.  
  15567. return Tree;
  15568.  
  15569. --| Effects
  15570. --| This creates a tree containing no information and no children.  An 
  15571. --| emptytree.
  15572.  
  15573. -------------------------------------------------------------------------------
  15574.  
  15575. procedure Deposit (              --| This deposits the information I in the
  15576.                                  --| root of the Tree S.
  15577.           I :in     ItemType;    --| The information being deposited.
  15578.           S :in     Tree         --| The tree where the information is being
  15579.                                  --| stored.
  15580. );
  15581.  
  15582. --| Modifies
  15583. --| This changes the information stored at the root of the tree S.
  15584.  
  15585. -------------------------------------------------------------------------------
  15586.  
  15587.  
  15588. procedure DestroyTree (         --| Destroys a tree.
  15589.           T  :in out Tree       --| Tree being destroyed.
  15590. );
  15591.  
  15592. --| Effects
  15593. --| Destroys a tree and returns the space which it is occupying.
  15594.  
  15595. --------------------------------------------------------------------------
  15596.  
  15597. Procedure Insertnode(           --| This Procedure Inserts A Node Into The 
  15598.                                 --| Specified Tree.
  15599.        N      :In Out Itemtype; --| The Information To Be Contained In The 
  15600.                                 --| Node Being Inserted.   
  15601.                               
  15602.        T      :In Out Tree;     --| Tree Being Inserted Into.
  15603.        Root   :   Out Tree;     --| Root of the subtree which Node N heads. 
  15604.                                 --| This is the position of the node N in T.
  15605.        Exists :   out boolean   --| If this node already exists in the tree
  15606.                                 --| Exists is true.  If this is the first
  15607.                                 --| insertion Exists is false.
  15608. ); 
  15609.  
  15610. --| Effects
  15611. --| This adds the node N to the tree T inserting in the proper postion.
  15612.  
  15613. --| Modifies
  15614. --| This modifies the tree T by add the node N to it.
  15615.  
  15616. ------------------------------------------------------------------------------
  15617.  
  15618. function MakeTreeIter (         --| Sets a variable to a position in the
  15619.                                 --| tree
  15620.                                 --| where the iteration is to begin.  In this 
  15621.                                 --| case the position is a pointer to the  
  15622.                                 --| the deepest leftmost leaf in the tree.
  15623.         T:in Tree               --| Tree being iterated over 
  15624. ) return TreeIter;
  15625.  
  15626.  
  15627. --| Effects
  15628.  
  15629.  
  15630. -----------------------------------------------------------------------------
  15631.  
  15632. function More (                 --| Returns true if there are more elements 
  15633.                                 --| in the tree to iterate over.
  15634.           I :in TreeIter  
  15635. ) return boolean;
  15636.  
  15637.  
  15638. -----------------------------------------------------------------------------
  15639.  
  15640. procedure Next (                --| This is the iterator operation.  Given 
  15641.                                 --| an Iter in the Tree it returns the 
  15642.                                 --| item Iter points to and updates the
  15643.                                 --| iter. If Iter is at the end of the Tree, 
  15644.                                 --| yielditer returns false otherwise it 
  15645.                                 --| returns true.
  15646.     I        :in out TreeIter;  --| The iter which marks the position in the 
  15647.                                 --| Tree.
  15648.  
  15649.     Info     :   out ItemType   --| Information being returned from a node.
  15650. );    
  15651.  
  15652.  
  15653. ---------------------------------------------------------------------------
  15654.  
  15655. private
  15656.  
  15657.    type Node;
  15658.    type Tree is access Node;
  15659.  
  15660.    type Node is 
  15661.         record
  15662.             Info           :ItemType;
  15663.             LeftChild      :Tree;
  15664.             RightChild     :Tree;
  15665.         end record;
  15666.  
  15667.    package NodeOrder is new Lists (Tree);
  15668.  
  15669.  
  15670.    type TreeIter is
  15671.       record
  15672.           NodeList :NodeOrder.List;
  15673.           State    :NodeOrder.ListIter;
  15674.       end record;
  15675.  
  15676.  
  15677. end BinaryTrees;
  15678.  
  15679. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15680. --BTREES.BDY
  15681. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15682.  
  15683. with unchecked_deallocation;
  15684.  
  15685. package body Binarytrees is
  15686.  
  15687. ----------------------------------------------------------------------------
  15688. --                   Local Subprograms
  15689. ----------------------------------------------------------------------------
  15690.  
  15691. procedure Free is new unchecked_deallocation (Node, Tree);
  15692.  
  15693. function equal (X, Y: in ItemType) return boolean is 
  15694.  
  15695. begin
  15696.  
  15697.     return (not (X < Y))  and  (not (Y < X));
  15698. end;
  15699.  
  15700. ------------------------------------------------------------------------------
  15701.  
  15702. function generate (T :in Tree ) return  Nodeorder.List is
  15703.     L : Nodeorder.List;
  15704.  
  15705. --| This routine generates a list of pointers to nodes in the tree t.
  15706. --| The list is ordered with respect to the order of the nodes in the tree.
  15707.  
  15708. --| generate does a depth first search of the tree.  
  15709. --| 1.   It first visits the leftchild of t and generates the list for that.
  15710. --| 2.   It then appends the root node of t to the list generated for the left
  15711. --|      child.
  15712. --| 3.   It then appends the list generated for the rightchild to the list
  15713. --|      generated for the leftchild and the root.
  15714. --|
  15715.  
  15716. begin 
  15717.     L := NodeOrder.Create;
  15718.     if T /= null then
  15719.         L := Generate (T.Leftchild);
  15720.         Nodeorder.Attach (L, T);
  15721.         Nodeorder.Attach (L, Generate (T.Rightchild));
  15722.     end if;
  15723.     return L;
  15724. End Generate;
  15725.  
  15726. ------------------------------------------------------------------------------
  15727.  
  15728.  
  15729.  
  15730. ------------------------------------------------------------------------------
  15731. --                    Visible Subprograms
  15732. ------------------------------------------------------------------------------
  15733.  
  15734.  
  15735.  
  15736.  
  15737.  
  15738. ------------------------------------------------------------------------------
  15739.  
  15740. function Create  return Tree is
  15741.  
  15742. begin
  15743.     return null;
  15744. end;
  15745.  
  15746. -----------------------------------------------------------------------------
  15747.  
  15748. procedure Deposit (
  15749.           I :in      ItemType;
  15750.           S :in      Tree         ) is
  15751.  
  15752. begin
  15753.     S.Info := I;
  15754. end;
  15755.  
  15756. ------------------------------------------------------------------------------
  15757.  
  15758. procedure DestroyTree ( T :in out Tree) is
  15759.  
  15760. --| This procedure recursively destroys the tree T.
  15761. --|  1.  It destroy the leftchild of T
  15762. --|  2.  It then destroys the rightchild of T.
  15763. --|  3.  It then destroy the root T and set T to be null.
  15764.  
  15765. begin
  15766.     if T.leftchild /= null then
  15767.      DestroyTree (T.leftchild);
  15768.      DestroyTree (T.rightchild);
  15769.      Free (T);
  15770. end if;
  15771. end DestroyTree;
  15772.  
  15773. ------------------------------------------------------------------------------
  15774.  
  15775. procedure InsertNode ( 
  15776.         N           :in out ItemType;    --| Node being inserted.
  15777.         T           :in out Tree;        --| Tree node is being inserted
  15778.                                          --| into.                   
  15779.         Root        :   out Tree;        --| Root of the subtree which node N
  15780.                                          --| heads.  This is the position of 
  15781.                                          --| node N in T;
  15782.         Exists      :   out boolean      --| If this node already exists in
  15783.                                          --| the tree then Exists is true. If
  15784.                                          --| If this is the first insertion 
  15785.                                          --| Exists is false.
  15786.               
  15787.                                                                        ) is
  15788. --| This inserts the node N in T.
  15789. --| 1.  If T is null then a new node is allocated and assigned to T
  15790. --| 2.  If T is not null then T is searched for the proper place to insert n.
  15791. --|     This is first done by checking whether N < rightchild 
  15792. --| 3.  If this is not true then we check to see if leftchild < N
  15793. --| 4.  If this is not true then N is in the tree.
  15794.  
  15795. begin
  15796.     if T = null then
  15797.         T := new Node ' (Info => N, leftchild => null, rightchild => null);
  15798.         Root := T;
  15799.         Exists := false;
  15800.         N := T.Info;
  15801.     elsif N < T.Info then
  15802.         InsertNode (N, T.leftchild, Root, Exists);
  15803.     elsif T.Info < N then
  15804.         InsertNode (N, T.rightchild, Root, Exists);
  15805.     else
  15806.         Root := T;
  15807.         Exists := true;
  15808.         N := T.Info;
  15809.         
  15810.     end if;
  15811. end InsertNode;
  15812.  
  15813. ------------------------------------------------------------------------------
  15814.  
  15815. function MakeTreeIter (T :in     Tree ) return TreeIter is
  15816.  
  15817.     I :TreeIter;
  15818. --| This sets up the iterator for a tree T.
  15819. --| The NodeList keeps track of the order of the nodes of T.  The NodeList
  15820. --| is computed by first invoking Generate of the leftchild then append
  15821. --| the root node to NodeList and then append the result of Generate
  15822. --| to NodeList.  Since the tree is ordered such that 
  15823. --|
  15824. --|    leftchild < root    root < rightchild 
  15825. --| 
  15826. --| NodeOrder returns the nodes in ascending order.
  15827. --|
  15828. --| Thus NodeList keeps the list alive for the duration of the iteration
  15829. --| operation.  The variable State is the a pointer into the NodeList
  15830. --| which is the current place of the iteration.
  15831.  
  15832. begin
  15833.     I.NodeList := NodeOrder.Create;
  15834.     if T /= null then
  15835.         I.NodeList := Generate (T.leftchild);
  15836.         NodeOrder.Attach (I.NodeList, T);    
  15837.         NodeOrder.Attach (I.NodeList, Generate (T.rightChild));
  15838.     end if;
  15839.     I.State := NodeOrder.MakeListIter (I.NodeList);
  15840.     return I;    
  15841. end;    
  15842.  
  15843. ------------------------------------------------------------------------------
  15844.  
  15845. function More (I :in TreeIter) return boolean is
  15846.    
  15847. begin
  15848.     return NodeOrder.More (I.State);
  15849. end;
  15850.  
  15851. ------------------------------------------------------------------------------
  15852.  
  15853. procedure Next (
  15854.           I    :in out TreeIter;
  15855.           Info :   out ItemType       ) is
  15856.   T: Tree;
  15857.     
  15858. --| Next returns the information at the current position in the iterator
  15859. --| and increments the iterator.  This is accomplished by using the iterater
  15860. --| associated with the NodeOrder list.  This returns a pointer into the Tree
  15861. --| and then the information found at this node in T is returned.
  15862.  
  15863.  
  15864. begin
  15865.     NodeOrder.Next (I.State, T);
  15866.     Info := T.Info;
  15867. end;
  15868.  
  15869. -------------------------------------------------------------------------------
  15870.  
  15871. end BinaryTrees;
  15872. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15873. --ORDSET.SPC
  15874. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15875. with BinaryTrees;
  15876.  
  15877. generic
  15878.       type ItemType is private;
  15879.         --| Information being contained a the member of the set.
  15880.     
  15881.       with function "<" (X, Y :in    ItemType) return boolean;
  15882.  
  15883. package OrderedSets is
  15884.  
  15885. --| Overview
  15886. --| This abstractions is a counted ordered set.  This means that 
  15887. --| associated with each member of the set is a count of the number of
  15888. --| times it appears in the set.  The order part means that there is
  15889. --| an ordering associated with the members.  This allows fast insertion.
  15890. --| It also makes it easy to iterate over the set in order.
  15891.  
  15892.  
  15893.  
  15894. --                    Types
  15895. --                    -----
  15896.  
  15897.       type Set is private;  --| This is the type exported to represent 
  15898.                             --| the ordered set.
  15899.  
  15900.       type SetIter is private;  --| This is the type exported whose 
  15901.                                 --| purpose is to walk over a set.
  15902.  
  15903.  
  15904. --                   Operations
  15905. --                   ----------
  15906.  
  15907. --| Cardinality              Returns cardinality of the set.
  15908. --| Create                   Creates the empty set.
  15909. --| CountMember              Returns the number of times the member appears in
  15910. --|                          the set.
  15911. --| Destroy                  Destroys a set and returns the space it occupies.
  15912. --| Insert                   Insert a member into  the set.
  15913. --| MakeSetIter              Return a SetIter which will begin an iteration.
  15914. --| More                     Are there more elements to iterate over in the 
  15915. --|                          set.
  15916. --| Next                     Return the next element in the iteration and 
  15917. --|                          bump the iterator.
  15918.  
  15919.  
  15920. ------------------------------------------------------------------------------
  15921.  
  15922. function Cardinality (   --| Return the number of members in the set.
  15923.          S     :in Set   --| The set whose members are being counted.
  15924. ) return natural;
  15925.  
  15926. ------------------------------------------------------------------------------
  15927.  
  15928.  
  15929. function Create   --| Return the empty set.
  15930. return Set;
  15931.  
  15932. ------------------------------------------------------------------------------
  15933.  
  15934. procedure Destroy (        --| Destroy a set and return its space.
  15935.           S   :in out Set  --| Set being destroyed.
  15936.  
  15937. );
  15938.  
  15939. ------------------------------------------------------------------------------
  15940.  
  15941. function GetCount (            --| This returns the count associated with 
  15942.                                --| member which corresponds to the current
  15943.                                --| iterator I.
  15944.          I :in     SetIter
  15945. ) return natural;
  15946.  
  15947. -----------------------------------------------------------------------------
  15948.  
  15949. procedure Insert (             --| Insert a member M into set S.
  15950.          M :in     ItemType;   --| Member being inserted.
  15951.          S :in out Set         --| Set being inserted into.
  15952. );
  15953.  
  15954. ------------------------------------------------------------------------------
  15955.  
  15956. function MakeSetIter (      --| Prepares a user for an iteration operation by 
  15957.                             --| by returning a SetIter.
  15958.          S :in     Set     --| Set being iterate over.
  15959. ) return SetIter;
  15960.  
  15961. ------------------------------------------------------------------------------
  15962.  
  15963. function More (             --| Returns true if there are more elements in the 
  15964.                             --| set to iterate over.
  15965.          I :in    SetIter   --| The iterator.
  15966.  
  15967. ) return boolean;
  15968.  
  15969. ------------------------------------------------------------------------------
  15970.  
  15971. procedure Next (              --| Returns the current member in the iteration
  15972.                               --| an increments the iterator.
  15973.          I :in out SetIter;   --| The iterator.
  15974.          M :   out ItemType   --| The current member being returned.
  15975. );
  15976.  
  15977. -----------------------------------------------------------------------------   
  15978.  
  15979. private 
  15980.  
  15981.    type Member is 
  15982.        record 
  15983.          Info   :ItemType;
  15984.          Count  :natural;
  15985.        end record;
  15986.  
  15987.    function "<" ( 
  15988.             X:in    Member;
  15989.             Y:in    Member
  15990.    ) return boolean;
  15991.  
  15992.    package TreePkg is new BinaryTrees ( ItemType => Member, "<" => "<" );
  15993.  
  15994.    type Set is
  15995.        record 
  15996.          SetRep :TreePkg.Tree;
  15997.        end record;
  15998.  
  15999.    type SetIter is
  16000.        record
  16001.          Place :TreePkg.TreeIter;
  16002.          Count :natural;
  16003.        end record;
  16004.  
  16005. end OrderedSets;
  16006. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16007. --ORDSET.BDY
  16008. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16009. package body OrderedSets is
  16010. -------------------------------------------------------------------------------
  16011. --                Local Subprograms
  16012. -------------------------------------------------------------------------------
  16013.  
  16014. -------------------------------------------------------------------------------
  16015.  
  16016. function "<" (     --| Implements "<" for the type member.
  16017.          X :in   Member;
  16018.          Y :in   Member 
  16019. ) return boolean is
  16020.  
  16021. begin
  16022.      return X.Info < Y.Info;
  16023. end;
  16024.  
  16025. -------------------------------------------------------------------------------
  16026.  
  16027.  
  16028. -------------------------------------------------------------------------------
  16029. --               Visible Subprograms
  16030. -------------------------------------------------------------------------------
  16031.  
  16032.  
  16033. -------------------------------------------------------------------------------
  16034.  
  16035. function Cardinality ( 
  16036.               S :in Set  --| The set whose size is being computed.
  16037. ) return natural is
  16038.  
  16039.     T        :TreePkg.TreeIter;
  16040.     M        :Member;
  16041.     count    :natural := 0;
  16042. begin
  16043.     T := TreePkg.MakeTreeIter (S.SetRep);
  16044.     while TreePkg.More (T) loop
  16045.         TreePkg.Next (T, M);
  16046.         count := count + 1;
  16047.     end loop;
  16048.     return count;
  16049. end Cardinality;            
  16050.  
  16051. -------------------------------------------------------------------------------
  16052.  
  16053. function Create
  16054.  
  16055. return Set is
  16056.     S :Set;
  16057. begin
  16058.     S.SetRep := TreePkg.Create;
  16059.     return S;
  16060. end Create;
  16061.  
  16062. ------------------------------------------------------------------------------
  16063.  
  16064. procedure Destroy ( 
  16065.          S :in out Set
  16066. ) is
  16067.  
  16068. begin
  16069.     TreePkg.DestroyTree (S.SetRep);
  16070. end Destroy;
  16071.  
  16072. -----------------------------------------------------------------------------
  16073.  
  16074. function GetCount (
  16075.          I :in    SetIter
  16076. ) return natural is
  16077.  
  16078. begin
  16079.      return I.Count;
  16080. end;
  16081.  
  16082. -----------------------------------------------------------------------------
  16083. procedure Insert(
  16084.           M :in     ItemType;
  16085.           S :in out Set
  16086. ) is
  16087.     Subtree       :TreePkg.Tree;
  16088.     Exists        :boolean;
  16089.     MemberToEnter :Member := ( Info => M, count => 1);
  16090. begin
  16091.     --| If NewMember doesn't exist in SetRep it is added.  If it does exist
  16092.     --| Exists comes back true and then M's count is updated.  Since the
  16093.     --| first argument of TreePkg.Insert is in out, after Insert 
  16094.     --| MemberToEnter has the value stored in the tree.  Thus if we
  16095.     --| need to update the count we can simple bump the count in MemberToEnter.
  16096.  
  16097.     TreePkg.InsertNode (MemberToEnter, S.SetRep, SubTree, Exists);    
  16098.     if Exists then 
  16099.         MemberToEnter.Count := MemberToEnter.Count + 1;
  16100.         TreePkg.Deposit (MemberToEnter, SubTree);
  16101.     end if;        
  16102. end Insert;
  16103.  
  16104. ------------------------------------------------------------------------------
  16105.  
  16106. function MakeSetIter (   
  16107.          S :in Set
  16108. )        return SetIter is
  16109.  
  16110.     I :SetIter;
  16111. begin
  16112.     I.Place := TreePkg.MakeTreeIter (S.SetRep);
  16113.     I.Count := 0;
  16114.     return I;
  16115. end;
  16116.  
  16117.  ------------------------------------------------------------------------------
  16118.  
  16119. function More ( 
  16120.           I :in     SetIter
  16121. )         return boolean is
  16122.  
  16123. begin
  16124.     return TreePkg.More (I.Place);
  16125. end;
  16126.     
  16127. ------------------------------------------------------------------------------
  16128.  
  16129. procedure Next (
  16130.          I :in out SetIter;
  16131.          M :   out ItemType
  16132. ) is
  16133.     TempMember :Member;
  16134. begin
  16135.     TreePkg.Next (I.Place, TempMember);
  16136.     M := TempMember.Info;
  16137.     I.Count := TempMember.Count;
  16138. end;
  16139.  
  16140. ------------------------------------------------------------------------------
  16141.  
  16142. end OrderedSets;
  16143. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16144. --LEX.BDY
  16145. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16146.  
  16147. ----------------------------------------------------------------------
  16148.  
  16149. with Host_Dependencies;         -- Host dependents constants
  16150. with Lex_Identifier_Token_Value;
  16151.                                 -- contains data structures and subprogram
  16152.                                 --    to distinguish identifiers from
  16153.                                 --    reserved words
  16154. with Lexical_Error_Message;     -- outputs error messages.
  16155. with ParseTables;               -- tables from parser generator
  16156. use ParseTables;
  16157. with Grammar_Constants;         -- constants from the parser generator
  16158. use Grammar_Constants;
  16159. with TEXT_IO;
  16160.  
  16161.  
  16162. package body Lex is
  16163.  
  16164. --| Overview
  16165. --| 
  16166. --| Package Lex is implemented as a state machine via case statements.
  16167. --| The implementation is optimized to minimize the number of times
  16168. --| each character is handled.  Each character is handled twice: once
  16169. --| on input and once on lexing based on the character.
  16170. --| 
  16171. --| The algorithm depends on having an End_Of_Line_Character
  16172. --| terminate each source file line.  This concludes the final token
  16173. --| on the line for the case statement scanners.
  16174.  
  16175. --| Notes
  16176. --| 
  16177. --| Abbreviations Used:
  16178. --|
  16179. --| Char : Character
  16180. --| CST  : Current_Source_Token
  16181. --| gram : grammar
  16182. --| sym  : symbol
  16183. --| val  : value
  16184. --| RW   : Reserved Word
  16185. --| 
  16186.  
  16187.     use ParserDeclarations;
  16188.     package LEM  renames Lexical_Error_Message;
  16189.     package PT   renames ParseTables;
  16190.     package GC   renames Grammar_Constants;
  16191.     -- other package renames are in the package spec
  16192.  
  16193.     ------------------------------------------------------------------
  16194.     -- Character Types
  16195.     ------------------------------------------------------------------
  16196.  
  16197.     subtype Graphic_Character
  16198.         is character range ' ' .. ASCII.TILDE;
  16199.  
  16200.     subtype Upper_Case_Letter
  16201.         is character range 'A'..'Z';
  16202.  
  16203.     subtype Lower_Case_Letter
  16204.         is character range ASCII.LC_A .. ASCII.LC_Z;
  16205.  
  16206.     subtype Digit
  16207.         is character range '0'..'9';
  16208.  
  16209.     subtype Valid_Base_Range is GC.ParserInteger
  16210.         range 2..16;
  16211.  
  16212.     subtype End_Of_Line_Character
  16213.         is character range ASCII.LF .. ASCII.CR;
  16214.  
  16215.     ------------------------------------------------------------------
  16216.     -- Source position management
  16217.     ------------------------------------------------------------------
  16218.  
  16219.     Current_Column :  HD.Source_Column := 1;
  16220.     Current_Line   :  HD.Source_Line   := 1;
  16221.     --| the position of Next_Char in the source file.
  16222.     --| Visible so the Lexical_Error_message package can use them.
  16223.  
  16224.     ------------------------------------------------------------------
  16225.     -- Source Input Buffers and their Management
  16226.     ------------------------------------------------------------------
  16227.  
  16228.     Next_Char : character := ' ';    --| input buffer for next character
  16229.                                      --| to scan from source file
  16230.  
  16231.     End_Of_Line_Buffer :             --| character that signals end of
  16232.                                      --| line buffer
  16233.         constant character := End_Of_Line_Character'First;
  16234.  
  16235.     subtype Line_Buffer_Range is
  16236.         positive range 1..(( HD.Source_Column'Last) + 2);
  16237.     --| The first extra element is needed to hold the End_Of_Line_Buffer
  16238.     --| character. The second extra element allows Line_Buffer_Index
  16239.     --| to exceed Line_Buffer_Last.
  16240.  
  16241.     Line_Buffer : string (Line_Buffer_Range) := (-- 1 =>
  16242.         End_Of_Line_Buffer, others => ' ');
  16243.     --| input buffer containing source file line being lexed.
  16244.  
  16245.     Line_Buffer_Last : HD.Source_Column := Line_Buffer'First;
  16246.     --| length of source file line being lexed.
  16247.  
  16248.     Line_Buffer_Index : Line_Buffer_Range;
  16249.     --| index of character being lexed.
  16250.  
  16251.     End_Of_File_Reached : boolean := false;
  16252.     --| true when end of the input source has been reached
  16253.  
  16254.     ------------------------------------------------------------------
  16255.     -- Token to be Returned and its Management
  16256.     ------------------------------------------------------------------
  16257.  
  16258.     CST : PD.ParseStackElement;    --| token being assembled for return by
  16259.                                    --| subprogram GetNextSourceToken
  16260.  
  16261.     subtype CST_Initialization_Type is PD.ParseStackElement;
  16262.  
  16263.     CST_Initializer : CST_Initialization_Type;
  16264.     --| short cut to initializing discriminants properly
  16265.  
  16266.     End_Of_File_Token : CST_Initialization_Type;
  16267.  
  16268.     ------------------------------------------------------------------
  16269.     -- Other objects
  16270.     ------------------------------------------------------------------
  16271.  
  16272.     Exit_After_Get_Next_Char : boolean := false;
  16273.     --| true; call Get_Next_Char before exiting, so that
  16274.     --| Next_Char contains the next character to be scanned.
  16275.     --| This object is not located in subprogram GetNextSourceToken,
  16276.     --| to save the time of re-elaboration on each call.
  16277.  
  16278.     Previous_Token_Value : PT.TokenRange := PT.StringTokenValue;
  16279.     --| used to resolve tick use as a token in T'('a') versus
  16280.     --| use as a delimiter in a character literal.
  16281.  
  16282.     Source_File : TEXT_IO.FILE_TYPE;
  16283.  
  16284.     ------------------------------------------------------------------
  16285.     -- Declarations for Scan_Numeric_Literal and Scan_Comment
  16286.     ------------------------------------------------------------------
  16287.  
  16288.     Temp_Source_Text : PD.Source_Text; --| temporary to hold value of
  16289.                                        --| Source_Text
  16290.  
  16291.     ------------------------------------------------------------------
  16292.  
  16293.     subtype Work_String_Range_Plus_Zero is
  16294.         natural range 0 .. natural(HD.Source_Column'Last);
  16295.  
  16296.     Work_String        : string (1..Work_String_Range_Plus_Zero'Last);
  16297.  
  16298.     Work_String_Length : Work_String_Range_Plus_Zero;
  16299.     -- Must initialize to 0 before each use.
  16300.  
  16301.     ------------------------------------------------------------------
  16302.     -- Declarations for Procedures:
  16303.     --
  16304.     -- Scan_Exponent, Scan_Based_Integer, Scan_Integer,
  16305.     -- and Scan_Numeric_Literal
  16306.     ------------------------------------------------------------------
  16307.  
  16308.     Seen_Radix_Point : boolean := false;
  16309.     --| true  : real
  16310.     --| false : integer
  16311.  
  16312.     ------------------------------------------------------------------
  16313.     -- Subprogram Specifications Local to Package Lex
  16314.     ------------------------------------------------------------------
  16315.  
  16316.     procedure Get_Next_Char;          --| Obtains next character
  16317.  
  16318.     --| Requires
  16319.     --|
  16320.     --| This subprogram requires an opened source file, and
  16321.     --| Current Column > Line_Buffer_Last on its first call to initialize
  16322.     --| the input buffers Next_Char and Line_Buffer correctly.
  16323.     --|
  16324.  
  16325.     --| Effects
  16326.     --|
  16327.     --| This subprogram places the next character from the source file
  16328.     --| in Next_Char and updates the source file position.
  16329.     --| Subprogram Get_Next_Line sets End_Of_File_Reached true, and causes
  16330.     --| Next_Char to be set to the last character in Line_Buffer.
  16331.     --|
  16332.  
  16333.     --| Modifies
  16334.     --|
  16335.     --| Current_Column
  16336.     --| Current_Line
  16337.     --| Next_Char
  16338.     --| Line_Buffer
  16339.     --| Line_Buffer_Last
  16340.     --| Line_Buffer_Index
  16341.     --| End_Of_File_Reached
  16342.     --|
  16343.  
  16344.     ------------------------------------------------------------------
  16345.  
  16346.     procedure Get_Next_Line;      --| gets next source file line to lex
  16347.  
  16348.     --| Requires
  16349.     --|
  16350.     --| This subprogram requires the source file to be open.
  16351.     --|
  16352.  
  16353.     --| Effects
  16354.     --|
  16355.     --| This subprogram gets next source line from input file.
  16356.     --| Sets Current_Column and Line_Buffer_Index to 1, and
  16357.     --| increments Current_Line.
  16358.     --| If the End of File is detected,
  16359.     --| End_Of_File_Reached is set true,
  16360.     --| End_Of_File_Token is set up,
  16361.     --| and Next_Char is set to End_Of_Line_Buffer.
  16362.     --|
  16363.  
  16364.     --| Modifies
  16365.     --|
  16366.     --| Current_Line
  16367.     --| End_Of_File_Reached
  16368.     --| End_Of_File_Token - only when the end of file is reached.
  16369.     --| Line_Buffer
  16370.     --| Line_Buffer_Last
  16371.     --|
  16372.  
  16373.     ------------------------------------------------------------------
  16374.  
  16375.     function Look_Ahead(        --| Return character n columns ahead
  16376.                                 --| in current in current line.
  16377.         In_Columns_Ahead :      --| Number of columns ahead to get
  16378.             in HD.Source_Column --| return character from.
  16379.         ) return character;
  16380.  
  16381.     --| Requires
  16382.     --|
  16383.     --| Line_Buffer
  16384.     --| Line_Buffer_Last
  16385.     --|
  16386.  
  16387.     --| Effects
  16388.     --|
  16389.     --| Return character In_Columns_Ahead in Line_Buffer.
  16390.     --| If this character is off the end of Line_Buffer,
  16391.     --| End_Of_Line_Buffer character is returned.
  16392.     --|
  16393.  
  16394.     ------------------------------------------------------------------
  16395.  
  16396.     procedure Set_CST_Gram_Sym_Val(  --| Sets gram_sym_val for current
  16397.                                      --| token.
  16398.         In_Token_Value : in PT.TokenRange); --| value of token
  16399.  
  16400.     --| Effects
  16401.     --|
  16402.     --| This subprogram fills in gram_sym_val for the current token.
  16403.     --|
  16404.  
  16405.     ------------------------------------------------------------------
  16406.  
  16407.     procedure Set_CST_Source_Rep(    --| Saves the symbol representation
  16408.                                      --| in the current token.
  16409.         In_String : in string);      --| string holding symbol.
  16410.  
  16411.     --| Effects
  16412.     --|
  16413.     --| This subprogram fills in lexed_token.symrep for the current token.
  16414.     --|
  16415.  
  16416.     ------------------------------------------------------------------
  16417.  
  16418.     procedure Initialize_CST;        --| Sets lx_srcpos for current token.
  16419.  
  16420.     --| Requires
  16421.     --|
  16422.     --| This subprogram requires Current_Column and Current_Line.
  16423.     --|
  16424.  
  16425.     --| Effects
  16426.     --|
  16427.     --| This subprogram sets common fields in CST.
  16428.     --|
  16429.  
  16430.     ------------------------------------------------------------------
  16431.  
  16432.     procedure Add_Next_Char_To_Source_Rep;
  16433.                                 --| appends Next_Char to growing
  16434.                                 --| source representation
  16435.  
  16436.     --| Requires
  16437.     --|
  16438.     --| Next_Char
  16439.     --|
  16440.  
  16441.     --| Effects
  16442.     --|
  16443.     --| This subprogram appends Next_Char to the growing source
  16444.     --| representation.
  16445.     --|
  16446.  
  16447.     --| Modifies
  16448.     --|
  16449.     --| Work_String
  16450.     --| Work_String_Length
  16451.     --|
  16452.  
  16453.     ------------------------------------------------------------------
  16454.  
  16455.     procedure Check_For_Consecutive_Underlines;
  16456.                                 --| Issues an error message if
  16457.                                 --| consecutive underlines occur.
  16458.  
  16459.     --| Requires
  16460.     --|
  16461.     --| Work_String
  16462.     --| Work_String_Length
  16463.     --|
  16464.  
  16465.     --| Effects
  16466.     --|
  16467.     --| Issues an error message if consecutive underlines occur.
  16468.     --|
  16469.  
  16470.     ------------------------------------------------------------------
  16471.  
  16472.     procedure Check_For_Terminal_Underline;
  16473.                                 --| Issues an error message if
  16474.                                 --| a terminal underline occurs.
  16475.  
  16476.     --| Requires
  16477.     --|
  16478.     --| Work_String
  16479.     --| Work_String_Length
  16480.     --|
  16481.  
  16482.     --| Effects
  16483.     --|
  16484.     --| This subprogram issues an error message if a terminal underline
  16485.     --| occurs.
  16486.  
  16487.     ------------------------------------------------------------------
  16488.  
  16489.     procedure Scan_Comment;       --| Scans comments.
  16490.  
  16491.     --| Requires
  16492.     --|
  16493.     --| This subprogram requires an opened source file.
  16494.     --|
  16495.  
  16496.     --| Effects
  16497.     --|
  16498.     --| This subprogram scans the rest of a comment.
  16499.     --|
  16500.  
  16501.     --| Modifies
  16502.     --|
  16503.     --| CST
  16504.     --|
  16505.  
  16506.     ------------------------------------------------------------------
  16507.  
  16508.     procedure Scan_Identifier_Including_RW;
  16509.                                 --| Scans identifiers including
  16510.                                 --| reserved words
  16511.  
  16512.     --| Requires
  16513.     --|
  16514.     --| This subprogram requires an opened source file.
  16515.     --|
  16516.  
  16517.     --| Effects
  16518.     --|
  16519.     --| This subprogram scans the rest of the identifier,
  16520.     --| and determines if its a reserved word.
  16521.     --|
  16522.  
  16523.     --| Modifies
  16524.     --|
  16525.     --| CST
  16526.     --|
  16527.  
  16528.     ------------------------------------------------------------------
  16529.  
  16530.     procedure Scan_Exponent;    --| Scans exponent field in
  16531.                                 --| appropriate numeric_literals
  16532.  
  16533.     --| Requires
  16534.     --|
  16535.     --| This subprogram requires an opened source file.
  16536.     --|
  16537.  
  16538.     --| Effects
  16539.     --|
  16540.     --| This subprogram scans the end of numeric_literals which
  16541.     --| contain exponents.
  16542.     --|
  16543.  
  16544.     --| Modifies
  16545.     --|
  16546.     --| Work_String
  16547.     --| Work_String_Length
  16548.     --|
  16549.  
  16550.     ------------------------------------------------------------------
  16551.  
  16552.     procedure Scan_Based_Integer(  --| scans a based integer field of
  16553.                                    --| a numeric literal
  16554.         In_Base_To_Use :           --| the base to use for lexing.
  16555.             in Valid_Base_Range);
  16556.  
  16557.     --| Requires
  16558.     --|
  16559.     --| This subprogram requires an opened source file.
  16560.  
  16561.     --| Effects
  16562.     --|
  16563.     --| This subprogram scans a based integer field in a numeric literal,
  16564.     --| verifying that is lexically correct.
  16565.     --|
  16566.  
  16567.     --| Modifies
  16568.     --|
  16569.     --| Work_String
  16570.     --| Work_String_Length
  16571.     --|
  16572.  
  16573.     --| Notes
  16574.     --|
  16575.     --| This subprogram and Scan_Integer are nearly identical.
  16576.     --| They are separate to save the overhead of:
  16577.     --|
  16578.     --| - passing a base in for decimal literals; and
  16579.     --|
  16580.     --| - distinguishing the extended digit 'E' from the exponent
  16581.     --| delimiter 'E'.
  16582.     --|
  16583.  
  16584.     ------------------------------------------------------------------
  16585.  
  16586.     procedure Scan_Integer;     --| scans an integer field of
  16587.                                 --|  a numeric literal
  16588.  
  16589.     --| Requires
  16590.     --|
  16591.     --| This subprogram requires an opened source file.
  16592.     --| 
  16593.     
  16594.     --| Effects
  16595.     --| 
  16596.     --| This subprogram scans an integer field in a numeric literal,
  16597.     --| verifying it is lexically correct.
  16598.     --| 
  16599.     
  16600.     --| Modifies
  16601.     --|
  16602.     --| Work_String
  16603.     --| Work_String_Length
  16604.     --| 
  16605.     
  16606.     --| Notes
  16607.     --| 
  16608.     --| This subprogram and Scan_Based_Integer are nearly identical.
  16609.     --| They are separate to save the overhead of:
  16610.     --| 
  16611.     --| - passing a base in for decimal literals; and
  16612.     --| 
  16613.     --| - distinguishing the extended digit 'E' from the exponent
  16614.     --| delimiter 'E'.
  16615.     --| 
  16616.     
  16617.     ------------------------------------------------------------------
  16618.  
  16619.     procedure Scan_Numeric_Literal;   --| Scans numbers
  16620.  
  16621.     --| Requires
  16622.     --|
  16623.     --| This subprogram requires an opened source file, and the
  16624.     --| Universal Arithmetic package to handle conversions.
  16625.     --|
  16626.    
  16627.     --| Effects
  16628.     --|
  16629.     --| This subprogram scans the rest of the numeric literal and converts
  16630.     --| it to internal universal number format.
  16631.     --|
  16632.    
  16633.     --| Modifies
  16634.     --|
  16635.     --| CST
  16636.     --|
  16637.    
  16638.     -------------------------------------------------------------------
  16639.  
  16640.     procedure Scan_String_Literal;   --| Scans string literals
  16641.  
  16642.     --| Requires
  16643.     --| 
  16644.     --| This subprogram requires an opened source file.
  16645.     --| 
  16646.     
  16647.     --| Effects
  16648.     --| 
  16649.     --| This subprogram scans the rest of the string literal.
  16650.     --| 
  16651.     
  16652.     --| Modifies
  16653.     --|
  16654.     --| CST
  16655.     --|
  16656.     
  16657.     ------------------------------------------------------------------
  16658.     -- Subprogram Bodies Global to Package Lex
  16659.     -- (declared in package specification).
  16660.     ------------------------------------------------------------------
  16661.  
  16662.     procedure Initialization is
  16663.  
  16664.     begin
  16665.  
  16666.     End_Of_File_Reached := false;
  16667.         -- forces Get_Next_Char to call Get_Next_Line
  16668.     Current_Column := Line_Buffer_Last + 1;
  16669.         Get_Next_Char;
  16670.  
  16671.     end Initialization;
  16672.  
  16673.     ------------------------------------------------------------------
  16674.  
  16675.     function GetNextNonCommentToken return PD.ParseStackElement is
  16676.         separate;
  16677.  
  16678.     ------------------------------------------------------------------
  16679.  
  16680.     function GetNextSourceToken return PD.ParseStackElement is
  16681.  
  16682.     --| Overview
  16683.     --|
  16684.     --| Note the following LRM Sections:
  16685.     --|     LRM Section 2.2  - Lexical Elements, Separators and Delimiters
  16686.     --|     LRM Section 2.2  - Notes
  16687.     --|     LRM Section 2.5  - Character Literals
  16688.     --|     LRM Section 2.7  - Comments
  16689.     --|     LRM Section 2.7  - Note
  16690.     --|     LRM Section 2.10 - Allowed Replacements of Characters
  16691.     --|
  16692.  
  16693.     begin
  16694.  
  16695.         if (End_Of_File_Reached) then
  16696.             CST := End_Of_File_Token;
  16697.         else -- this else terminates
  16698.              -- shortly before the return statement
  16699.  
  16700.         -- This loop performs the following functions:
  16701.         --
  16702.         -- 1) It scans for and ignores repeated separators.
  16703.         -- 2) It reports illegal characters between tokens.
  16704.         -- 3) It identifies and lexes tokens.
  16705.         --    Delimiters and character literals are handled
  16706.         --    by code inside this loop.
  16707.         --    Complex tokens: identifiers, string and
  16708.         --    numeric literals are lexed by called
  16709.         --    subprograms.
  16710.         -- 4) It recognizes and processes comments that
  16711.         --    occur before the first token found.  Comments
  16712.         --    after tokens are processed by a separate loop
  16713.         --    after this one.
  16714.  
  16715.             Scan_For_Token: loop
  16716.                 case Next_Char is
  16717.                     when Upper_Case_Letter |
  16718.                         Lower_Case_Letter =>
  16719.                         Initialize_CST;
  16720.                         Scan_Identifier_Including_RW;
  16721.                         exit Scan_For_Token;
  16722.                         -- Next_Char already updated
  16723.  
  16724.                     when Digit =>
  16725.                         Initialize_CST;
  16726.                         Scan_Numeric_Literal;
  16727.                         exit Scan_For_Token;
  16728.                         -- Next_Char already updated
  16729.  
  16730.                     when ASCII.QUOTATION |  -- '"'
  16731.                         ASCII.PERCENT  => -- '%'
  16732.                         Initialize_CST;
  16733.                         Scan_String_Literal;
  16734.                         exit Scan_For_Token;
  16735.                         -- Next_Char already updated
  16736.  
  16737.                     when ''' =>
  16738.                         Initialize_CST;
  16739.                         if ((GC."="(Previous_Token_Value,
  16740.                                     PT.IdentifierTokenValue))
  16741.                             or else (GC."="(Previous_Token_Value,
  16742.                                             PT.AllTokenValue))
  16743.                             or else (GC."="(Previous_Token_Value,
  16744.                                             PT.StringTokenValue))
  16745.                             or else (GC."="(Previous_Token_Value,
  16746.                                             PT.CharacterTokenValue))
  16747.                             or else (GC."="(Previous_Token_Value,
  16748.                                      PT.RightParen_TokenValue)) ) then
  16749.                             --  CST is a ' delimiter
  16750.                             Set_CST_Gram_Sym_Val(
  16751.                                 PT.Apostrophe_TokenValue);
  16752.                         elsif (Look_Ahead(2) = ''') then
  16753.                             -- CST is a character literal
  16754.                             CST.gram_sym_val := PT.CharacterTokenValue;
  16755.                             Get_Next_Char;
  16756.                             if not (Next_Char in Graphic_Character) then
  16757.                                 -- flag as an error
  16758.                                 LEM.Output_Message(
  16759.                                     Current_Line
  16760.                                     , Current_Column
  16761.                                     , Integer'Image(
  16762.                                         Character'Pos(Next_Char))
  16763.                                     -- convert to string
  16764.                                     , LEM.Character_Is_Non_Graphic);
  16765.                             end if;
  16766.                             -- save the source representation.
  16767.                             Set_CST_Source_Rep ("'" & Next_Char);
  16768.                             Get_Next_Char;  -- pass by the closing
  16769.                                             -- single quote
  16770.                         else
  16771.                             -- flag single quote use as illegal
  16772.                             LEM.Output_Message(
  16773.                                 Current_Line
  16774.                                 , Current_Column
  16775.                                 , LEM.Illegal_Use_Of_Single_Quote);
  16776.                                 --  assume CST is a ' delimiter;
  16777.                             Set_CST_Gram_Sym_Val(
  16778.                                 PT.Apostrophe_TokenValue);
  16779.                         end if;
  16780.                         Exit_After_Get_Next_Char := true;
  16781.  
  16782.  
  16783.                     when ASCII.AMPERSAND =>    -- '&'
  16784.                         Initialize_CST;
  16785.                         Set_CST_Gram_Sym_Val(PT.Ampersand_TokenValue);
  16786.                         Exit_After_Get_Next_Char := true;
  16787.  
  16788.                     when '(' =>
  16789.                         Initialize_CST;
  16790.                         Set_CST_Gram_Sym_Val(PT.LeftParen_TokenValue);
  16791.                         Exit_After_Get_Next_Char := true;
  16792.  
  16793.                     when ')' =>
  16794.                         Initialize_CST;
  16795.                         Set_CST_Gram_Sym_Val(PT.RightParen_TokenValue);
  16796.                         Exit_After_Get_Next_Char := true;
  16797.  
  16798.                     when '*' =>
  16799.                         Initialize_CST;
  16800.                         Get_Next_Char;
  16801.                         case Next_Char is
  16802.                             when '*' =>
  16803.                                 Set_CST_Gram_Sym_Val(
  16804.                                     PD.Exponentiation_TokenValue);
  16805.                                 Exit_After_Get_Next_Char := true;
  16806.                             when others =>
  16807.                                 Set_CST_Gram_Sym_Val(PT.Star_TokenValue);
  16808.                                 exit Scan_For_Token;
  16809.                                 -- Next_Char already updated
  16810.                         end case;
  16811.  
  16812.                     when '+' =>
  16813.                         Initialize_CST;
  16814.                         Set_CST_Gram_Sym_Val(PT.Plus_TokenValue);
  16815.                         Exit_After_Get_Next_Char := true;
  16816.                 
  16817.                     when ',' =>
  16818.                         Initialize_CST;
  16819.                         Set_CST_Gram_Sym_Val(PT.Comma_TokenValue);
  16820.                         Exit_After_Get_Next_Char := true;
  16821.                 
  16822.                     when '-' =>                -- Minus_Sign or Hyphen
  16823.                            Initialize_CST;
  16824.                            Get_Next_Char;
  16825.                            case Next_Char is
  16826.                             when '-' =>     -- Minus_Sign or Hyphen
  16827.                                 -- two hyphens indicate a comment
  16828.                                 Set_CST_Gram_Sym_Val(
  16829.                                     PT.Comment_TokenValue);
  16830.                                 Scan_Comment;
  16831.                                 Exit_After_Get_Next_Char := true;
  16832.                             when others =>
  16833.                                 Set_CST_Gram_Sym_Val(PT.Minus_TokenValue);
  16834.                                 exit Scan_For_Token;
  16835.                                 -- Next_Char already updated
  16836.                         end case;
  16837.  
  16838.                     when '.' =>
  16839.                         Initialize_CST;
  16840.                         Get_Next_Char;
  16841.                         case Next_Char is
  16842.                             when '.' =>
  16843.                                 Set_CST_Gram_Sym_Val(
  16844.                                     PT.DotDot_TokenValue);
  16845.                                 Exit_After_Get_Next_Char := true;
  16846.                             when others =>
  16847.                                 Set_CST_Gram_Sym_Val(PT.Dot_TokenValue);
  16848.                                 exit Scan_For_Token;
  16849.                                 -- Next_Char already updated
  16850.                         end case;
  16851.  
  16852.                     when '/' =>
  16853.                         Initialize_CST;
  16854.                         Get_Next_Char;
  16855.                         case Next_Char is
  16856.                             when '=' =>
  16857.                                 Set_CST_Gram_Sym_Val(
  16858.                                     PD.NotEquals_TokenValue);
  16859.                                 Exit_After_Get_Next_Char := true;
  16860.                             when others =>
  16861.                                 Set_CST_Gram_Sym_Val(
  16862.                                     PT.Slash_TokenValue);
  16863.                                 exit Scan_For_Token;
  16864.                                 -- Next_Char already updated
  16865.                         end case;
  16866.  
  16867.                     when ASCII.COLON =>        -- ':'
  16868.                         Initialize_CST;
  16869.                         Get_Next_Char;
  16870.                         case Next_Char is
  16871.                             when '=' =>
  16872.                                 Set_CST_Gram_Sym_Val(
  16873.                                     PD.Assignment_TokenValue);
  16874.                                 Exit_After_Get_Next_Char := true;
  16875.                             when others =>
  16876.                                 Set_CST_Gram_Sym_Val(PT.Colon_TokenValue);
  16877.                                 exit Scan_For_Token;
  16878.                                 -- Next_Char already updated
  16879.                         end case;
  16880.  
  16881.                     when ASCII.SEMICOLON =>    -- ';'
  16882.                         Initialize_CST;
  16883.                         Set_CST_Gram_Sym_Val(PT.SemiColon_TokenValue);
  16884.                         Exit_After_Get_Next_Char := true;
  16885.  
  16886.                     when '<' =>
  16887.                         Initialize_CST;
  16888.                         Get_Next_Char;
  16889.                         case Next_Char is
  16890.                             when '=' =>
  16891.                                 Set_CST_Gram_Sym_Val(PT.LTEQ_TokenValue);
  16892.                                 Exit_After_Get_Next_Char := true;
  16893.                             when '<' =>
  16894.                                 Set_CST_Gram_Sym_Val(
  16895.                                     PD.StartLabel_TokenValue);
  16896.                                 Exit_After_Get_Next_Char := true;
  16897.                             when '>' =>
  16898.                                 Set_CST_Gram_Sym_Val(PD.Box_TokenValue);
  16899.                                 Exit_After_Get_Next_Char := true;
  16900.                             when others =>
  16901.                                 Set_CST_Gram_Sym_Val(PT.LT_TokenValue);
  16902.                                 exit Scan_For_Token;
  16903.                                 -- Next_Char already updated
  16904.                         end case;
  16905.  
  16906.                     when '=' =>
  16907.                         Initialize_CST;
  16908.                         Get_Next_Char;
  16909.                         case Next_Char is
  16910.                             when '>' =>
  16911.                                 Set_CST_Gram_Sym_Val(PD.Arrow_TokenValue);
  16912.                                 Exit_After_Get_Next_Char := true;
  16913.                             when others =>
  16914.                                 Set_CST_Gram_Sym_Val(PT.EQ_TokenValue);
  16915.                                 exit Scan_For_Token;
  16916.                                 -- Next_Char already updated
  16917.                         end case;
  16918.  
  16919.                     when '>' =>
  16920.                         Initialize_CST;
  16921.                         Get_Next_Char;
  16922.                         case Next_Char is
  16923.                             when '=' =>
  16924.                                 Set_CST_Gram_Sym_Val(PT.GTEQ_TokenValue);
  16925.                                 Exit_After_Get_Next_Char := true;
  16926.                             when '>' =>
  16927.                                 Set_CST_Gram_Sym_Val(
  16928.                                     PD.EndLabel_TokenValue);
  16929.                                 Exit_After_Get_Next_Char := true;
  16930.                             when others =>
  16931.                                 Set_CST_Gram_Sym_Val(PT.GT_TokenValue);
  16932.                                 exit Scan_For_Token;
  16933.                                 -- Next_Char already updated
  16934.                         end case;
  16935.  
  16936.                     when ASCII.BAR    |  -- '|'
  16937.                         ASCII.EXCLAM => -- '!'
  16938.                         -- vertical bar and its alternative
  16939.                         Initialize_CST;
  16940.                         Set_CST_Gram_Sym_Val(PT.Bar_TokenValue);
  16941.                         Exit_After_Get_Next_Char := true;
  16942.  
  16943.                     when ASCII.HT =>   -- Horizontal Tab
  16944.                         -- a lexical unit separator - skip it.
  16945.                         -- position Current_Column properly. This is done
  16946.                         --     here to save the cost of a test on every
  16947.                         --     character in Get_Next_Char.
  16948.  
  16949.                         Current_Column :=
  16950.                             HD.FindTabColumn(Current_Column);
  16951.  
  16952.                     when ' ' | End_Of_Line_Character =>
  16953.                         -- rest of the lexical unit separators
  16954.  
  16955.                         if (End_Of_File_Reached) then
  16956.                             return End_Of_File_Token;
  16957.                         end if;
  16958.                 
  16959.                 
  16960.                     when ASCII.UNDERLINE =>    -- '_'
  16961.                         case Look_Ahead(1) is
  16962.                             when Upper_Case_Letter | Lower_Case_Letter =>
  16963.                                 -- flag illegal leading under line
  16964.                                 LEM.Output_Message(
  16965.                                     Current_Line
  16966.                                     , Current_Column
  16967.                                     , LEM.Leading_Underline);
  16968.                                 Initialize_CST;
  16969.                                 Scan_Identifier_Including_RW;
  16970.                                 exit Scan_For_Token;
  16971.                                 -- Next_Char already updated
  16972.                             when Digit =>
  16973.                                 -- flag illegal leading under line
  16974.                                 LEM.Output_Message(
  16975.                                     Current_Line
  16976.                                     , Current_Column
  16977.                                     , LEM.Leading_Underline);
  16978.                                 Initialize_CST;
  16979.                                 Scan_Numeric_Literal;
  16980.                                 exit Scan_For_Token;
  16981.                                 -- Next_Char already updated
  16982.                             when others =>
  16983.                                 -- flag illegal character for start
  16984.                                 -- of token
  16985.                                 LEM.Output_Message(
  16986.                                     Current_Line
  16987.                                     , Current_Column
  16988.                                     , "_"
  16989.                                     , LEM.Character_Can_Not_Start_Token);
  16990.                         end case;
  16991.  
  16992.  
  16993.                     when ASCII.SHARP           |  -- '#'
  16994.                          ASCII.DOLLAR          |  -- '$'
  16995.                          ASCII.QUERY           |  -- '?'
  16996.                          ASCII.AT_SIGN         |  -- '@'
  16997.                          ASCII.L_BRACKET       |  -- '['
  16998.                          ASCII.BACK_SLASH      |  -- '\'
  16999.                          ASCII.R_BRACKET       |  -- ']'
  17000.                          ASCII.CIRCUMFLEX      |  -- '^'
  17001.                          ASCII.GRAVE           |  -- '`'
  17002.                          ASCII.L_BRACE         |  -- '{'
  17003.                          ASCII.R_BRACE         |  -- '}'
  17004.                          ASCII.TILDE           => -- '~'
  17005.                             -- flag illegal character for start of token
  17006.                             LEM.Output_Message(
  17007.                                 Current_Line
  17008.                                 , Current_Column
  17009.                                 , Next_Char & ""  -- convert to string
  17010.                                 , LEM.Character_Can_Not_Start_Token);
  17011.  
  17012.                     when ASCII.NUL ..          -- Null to
  17013.                                 ASCII.BS  |    --  Back Space
  17014.                          ASCII.SO ..           -- Shift Out to
  17015.                                 ASCII.US  |    --  Unit Separator
  17016.                          ASCII.DEL        =>   -- Delete
  17017.                             -- flag as non-graphic ASCII control character
  17018.                         LEM.Output_Message(
  17019.                             Current_Line
  17020.                             , Current_Column
  17021.                             , Integer'Image(Character'Pos(Next_Char))
  17022.                                                   -- convert to string
  17023.                             , LEM.Character_Is_Non_Graphic);
  17024.  
  17025.                     when others =>
  17026.                         -- should never happen due to 's
  17027.                         -- definition of CHARACTER. flag as illegal anyhow
  17028.                         LEM.Output_Message(
  17029.                             Current_Line
  17030.                             , Current_Column
  17031.                             , LEM.Character_Is_Non_ASCII);
  17032.                 end case;
  17033.  
  17034.                 Get_Next_Char;    -- for next time through loop.
  17035.  
  17036.                 if (Exit_After_Get_Next_Char) then
  17037.                     Exit_After_Get_Next_Char := false;
  17038.                     exit Scan_For_Token;
  17039.                 end if;
  17040.  
  17041.             end loop Scan_For_Token;    -- Next_Char already updated
  17042.  
  17043.             Previous_Token_Value := CST.gram_sym_val;
  17044.             -- for resolving T'('c')
  17045.  
  17046.         end if; -- (End_Of_File_Reached)
  17047.  
  17048.         return CST;
  17049.  
  17050.         -- On leaving: object Next_Char should contain character
  17051.         -- to scan on next call of this function.
  17052.  
  17053.     end GetNextSourceToken;
  17054.  
  17055.     ------------------------------------------------------------------
  17056.     -- Subprogram Bodies Local to Package Lex
  17057.     ------------------------------------------------------------------
  17058.  
  17059.     procedure Get_Next_Char is
  17060.     
  17061.     begin
  17062.     
  17063.     --| Algorithm
  17064.     --| 
  17065.     --| Source File is scanned returning each character until the
  17066.     --| end of the file is found. Proper column positioning for a tab
  17067.     --| character is done in GetNextSourceToken for speed.
  17068.     --| 
  17069.     
  17070.     -- The End_Of_Line_Character that Get_Next_Line
  17071.     -- inserts needs to be seen by the scanning
  17072.     -- case statements to terminate tokens correctly.
  17073.     
  17074.         Current_Column    := Current_Column    + 1;
  17075.         Line_Buffer_Index := Line_Buffer_Index + 1;
  17076.         Next_Char := Line_Buffer (Line_Buffer_Index);
  17077.  
  17078.         if (Line_Buffer_Index > Line_Buffer_Last) then
  17079.             Get_Next_Line;
  17080.             -- Current_Column and Line_Buffer_Index are handled there.
  17081.             Next_Char := Line_Buffer (Line_Buffer_Index);
  17082.         end if;
  17083.     
  17084.     end Get_Next_Char; -- procedure
  17085.     
  17086.     ------------------------------------------------------------------
  17087.  
  17088.     procedure Get_Next_Line is
  17089.     
  17090.     begin
  17091.     
  17092.         -- Get next source line from CURRENT_INPUT. Update column and
  17093.         -- line counts
  17094.         Current_Column := 1;
  17095.         Line_Buffer_Index := 1;
  17096.  
  17097.         Ignore_Null_Line:
  17098.         loop
  17099.             -- do NOT move next statement out of loop
  17100.             if (Current_Line < HD.Source_Line'Last) then
  17101.                 begin  -- block
  17102.                     Current_Line := HD.Source_Line  -- type conversion
  17103.                         (TEXT_IO.LINE(FILE => TEXT_IO.CURRENT_INPUT));
  17104.                     if (Current_Line >= HD.Source_Line'Last) then
  17105.                         raise CONSTRAINT_ERROR;
  17106.                     end if;
  17107.                 exception
  17108.                     when others =>
  17109.                         Current_Line := HD.Source_Line'Last;
  17110.                         LEM.Output_Message(
  17111.                             Current_Line
  17112.                             , Current_Column
  17113.                             , HD.Source_Line'IMAGE(HD.Source_Line'Last)
  17114.                             , LEM.Source_Line_Maximum_Exceeded);
  17115.                 end; -- block
  17116.             end if;
  17117.             TEXT_IO.GET_LINE(
  17118.                 FILE => TEXT_IO.CURRENT_INPUT,
  17119.                 ITEM => Line_Buffer(1..(Line_Buffer'Last - 1)),
  17120.                 LAST => Line_Buffer_Last);
  17121.                 -- flag a line that is too long as an error
  17122.                 if (Line_Buffer_Last >= Line_Buffer'Last - 1) and then
  17123.                    (TEXT_IO.END_OF_LINE(FILE => TEXT_IO.CURRENT_INPUT) )
  17124.                 then
  17125.                     LEM.Output_Message(
  17126.                         Current_Line
  17127.                         , Current_Column
  17128.                         , LEM.Source_Line_Too_Long);
  17129.                 end if;
  17130.         Write_Line;
  17131.                 exit Ignore_Null_Line when
  17132.                     (Line_Buffer_Last /= (Line_Buffer'First - 1));
  17133.         end loop Ignore_Null_Line;
  17134.  
  17135.         Line_Buffer_Last              := Line_Buffer_Last + 1;
  17136.         Line_Buffer(Line_Buffer_Last) := End_Of_Line_Buffer;
  17137.         
  17138.     exception
  17139.         -- when end of file is reached
  17140.         when TEXT_IO.END_ERROR =>
  17141.             -- save that state for GetNextSourceToken
  17142.             End_Of_File_Reached := true;
  17143.  
  17144.             -- update column and line counts
  17145.             Line_Buffer_Last  := 1;
  17146.             Line_Buffer(Line_Buffer_Last) := End_Of_Line_Buffer;
  17147.             Line_Buffer_Index := 1;
  17148.             Current_Column    := 1;
  17149.             -- Current_Line is ok.
  17150.             -- Last call to GET_LINE advanced it one.
  17151.  
  17152.             -- set the value of End_Of_File_Token
  17153.             -- the discriminants were set up by the object declaration
  17154.             End_Of_File_Token.gram_sym_val := PT.EOF_TokenValue;
  17155.             End_Of_File_Token.lexed_token := (
  17156.                 srcpos_line     => Current_Line,
  17157.                 srcpos_column   => Current_Column,
  17158.                 text            => PD.Null_Source_Text);
  17159.  
  17160.     end Get_Next_Line;
  17161.  
  17162.     ------------------------------------------------------------------
  17163.  
  17164.     function Look_Ahead(
  17165.         In_Columns_Ahead : in HD.Source_Column) return character is
  17166.  
  17167.     ------------------------------------------------------------------
  17168.     -- Declarations for subprogram Look_Ahead
  17169.     ------------------------------------------------------------------
  17170.     
  17171.     Position_To_Try : Integer := Integer   --type conversion
  17172.                                         ( Line_Buffer_Index
  17173.                                     + In_Columns_Ahead);
  17174.     
  17175.     ------------------------------------------------------------------
  17176.     
  17177.     begin
  17178.         
  17179.         -- if request is past the end of line
  17180.         if (Position_To_Try > Integer(Line_Buffer_Last) ) then
  17181.                                    -- type conversion
  17182.             -- return the end_of_line character
  17183.             return End_Of_Line_Buffer;
  17184.         else
  17185.             -- else return the requested character
  17186.             return Line_Buffer(Position_To_Try);
  17187.         end if;
  17188.         
  17189.     end Look_Ahead; -- function
  17190.  
  17191.     ------------------------------------------------------------------
  17192.  
  17193.     procedure Set_CST_Gram_Sym_Val(
  17194.         In_Token_Value : in PT.TokenRange) is
  17195.  
  17196.     begin
  17197.     
  17198.         CST.gram_sym_val := In_Token_Value;
  17199.     
  17200.     end Set_CST_Gram_Sym_Val;
  17201.     
  17202.     ----------------------------------------------------------------------
  17203.     
  17204.     procedure Set_CST_Source_Rep(
  17205.         In_String : in string) is
  17206.     
  17207.     begin
  17208.     
  17209.         -- store the representation
  17210.         PD.Put_Source_Text(
  17211.             In_String,
  17212.             CST.lexed_token.text);
  17213.     
  17214.     end Set_CST_Source_Rep;
  17215.  
  17216.     ------------------------------------------------------------------
  17217.  
  17218.     procedure Initialize_CST is
  17219.     
  17220.     begin
  17221.     
  17222.         -- Set up discriminants, and source position properly
  17223.         -- Set other CST fields to null values
  17224.         CST := CST_Initializer;
  17225.     
  17226.         CST.lexed_token := (
  17227.             srcpos_line     => Current_Line,
  17228.             srcpos_column   => Current_Column,
  17229.             text            => PD.Null_Source_Text);
  17230.     
  17231.     end Initialize_CST;
  17232.  
  17233.     ------------------------------------------------------------------
  17234.  
  17235.     procedure Add_Next_Char_To_Source_Rep is
  17236.     
  17237.     begin
  17238.     
  17239.         -- append the character to growing source representation
  17240.         Work_String_Length              := Work_String_Length + 1;
  17241.         Work_String(Work_String_Length) := Next_Char;
  17242.     
  17243.     end Add_Next_Char_To_Source_Rep;
  17244.  
  17245.     ------------------------------------------------------------------
  17246.  
  17247.     procedure Check_For_Consecutive_Underlines is
  17248.  
  17249.     begin
  17250.  
  17251.         -- flag consecutive underlines as an error (leading
  17252.         -- underlines are handled in GetNextSourceToken).
  17253.         if (Work_String(Work_String_Length) = ASCII.UNDERLINE)
  17254.         then
  17255.             LEM.Output_Message(
  17256.                 Current_Line
  17257.                 , Current_Column
  17258.                 , LEM.Consecutive_Underlines);
  17259.         end if;
  17260.         
  17261.     end Check_For_Consecutive_Underlines; -- procedure
  17262.  
  17263.     ------------------------------------------------------------------
  17264.  
  17265.     procedure Check_For_Terminal_Underline is
  17266.  
  17267.     begin
  17268.  
  17269.         -- flag a trailing underline as an error.
  17270.         -- trailing underlines are saved for the same
  17271.         -- reason as leading ones.
  17272.         -- See comment in GetNextSourceToken.
  17273.         
  17274.         if (Work_String(Work_String_Length) = ASCII.UNDERLINE)
  17275.         -- check the preceeding character
  17276.         then
  17277.             LEM.Output_Message(
  17278.                 Current_Line
  17279.                 , Current_Column
  17280.                 , LEM.Terminal_Underline);
  17281.         end if;
  17282.         
  17283.     end Check_For_Terminal_Underline;
  17284.  
  17285.     ------------------------------------------------------------------
  17286.  
  17287.     procedure Scan_Comment is
  17288.     
  17289.     --| Overview
  17290.     --|
  17291.     --| Note the following LRM Sections:
  17292.     --|     LRM Section 2.7  - Comments
  17293.     --|     LRM Section 2.7  - Note
  17294.     --|
  17295.     
  17296.     begin
  17297.     
  17298.         -- get to the beginning of the comment
  17299.         Get_Next_Char;
  17300.         Set_CST_Source_Rep(
  17301.             Line_Buffer(Line_Buffer_Index .. Line_Buffer_Last - 1));  
  17302.         -- subtract 1 so that the carridge return is not also returned.
  17303.     
  17304.         Line_Buffer_Index := Line_Buffer_Last + 1;
  17305.         -- force next call to Get_Next_Char to call Get_Next_Line
  17306.     
  17307.     end Scan_Comment;
  17308.  
  17309.     ------------------------------------------------------------------
  17310.  
  17311.     procedure Scan_Identifier_Including_RW is
  17312.     
  17313.     --| Overview
  17314.     --|
  17315.     --| Note the following LRM Sections:
  17316.     --|     LRM Section 2.3 - Identifiers
  17317.     --|     LRM Section 2.3 - Note
  17318.     --|     LRM Section 2.9 - Reserved Words
  17319.     --|     LRM Section 2.9 - Notes
  17320.     --|
  17321.     
  17322.     ------------------------------------------------------------------
  17323.     
  17324.     begin
  17325.     
  17326.         Work_String_Length := 0;
  17327.     
  17328.         -- scan source file for rest of token
  17329.         -- note that first character of the token is stored first
  17330.         Scan_For_Identifier_Including_RW: loop
  17331.             Add_Next_Char_To_Source_Rep;
  17332.  
  17333.             -- set up for processing next characte
  17334.             Get_Next_Char;
  17335.     
  17336.             case Next_Char is
  17337.                 when Upper_Case_Letter | Lower_Case_Letter | Digit =>
  17338.                     -- action is at start of next loop cycle
  17339.                     null;
  17340.                 when ASCII.UNDERLINE =>        -- '_'
  17341.                     Check_For_Consecutive_Underlines;
  17342.                 when others =>
  17343.                     Check_For_Terminal_Underline;
  17344.  
  17345.                     -- token is terminated by any character except letter
  17346.                     --     digit, or underline;
  17347.                     exit Scan_For_Identifier_Including_RW; -- this loop
  17348.             end case;
  17349.  
  17350.         end loop Scan_For_Identifier_Including_RW;
  17351.  
  17352.         -- find out what kind of token it is
  17353.         Lex_Identifier_Token_Value.Find(
  17354.             In_Identifier       =>
  17355.                 Work_String(1..Work_String_Length),
  17356.             Out_Token_Value     => CST.gram_sym_val);
  17357.         
  17358.         -- store the source representation of the token found
  17359.         Set_CST_Source_Rep(Work_String(1..Work_String_Length) );
  17360.         
  17361.     end Scan_Identifier_Including_RW;
  17362.  
  17363.     ------------------------------------------------------------------
  17364.  
  17365.     procedure Scan_Exponent is
  17366.     
  17367.     --| Overview
  17368.     --|
  17369.     --| Note the following LRM Sections:
  17370.     --|     LRM Section 2.4.1 - Decimal Literals
  17371.     --|     LRM Section 2.4.1 - Notes
  17372.     --|     LRM Section 2.4.2 - Based Literals
  17373.     --|
  17374.  
  17375.     begin
  17376.     
  17377.         -- Check for missing 'E' or 'e',
  17378.         -- and for existence of the exponent
  17379.         case Next_Char is
  17380.             when 'E' | 'e' =>
  17381.                 null;    -- normal case
  17382.             when others =>
  17383.                 return;  -- no exponent to process
  17384.         end case;
  17385.         -- add first character to growing literal
  17386.         Add_Next_Char_To_Source_Rep;
  17387.         
  17388.         
  17389.         -- scan source file for rest of the exponent
  17390.         -- verify that next character is legal for an integer field
  17391.         Get_Next_Char;
  17392.         
  17393.         case Next_Char is
  17394.             when '+' =>
  17395.                 -- add sign character to growing literal
  17396.                 Add_Next_Char_To_Source_Rep;
  17397.  
  17398.                 Get_Next_Char;
  17399.             when '-' =>     -- Minus_Sign
  17400.                 if not (Seen_Radix_Point) then
  17401.                     -- flag negative exponent as illegal in an integer
  17402.                     LEM.Output_Message(
  17403.                         Current_Line
  17404.                         , Current_Column
  17405.                         , LEM.Negative_Exponent_Illegal_In_Integer);
  17406.                 end if;
  17407.  
  17408.                 -- add sign character to growing literal
  17409.                 Add_Next_Char_To_Source_Rep;
  17410.  
  17411.                 Get_Next_Char;
  17412.             when others =>
  17413.                 null;
  17414.         end case;
  17415.  
  17416.         case Next_Char is
  17417.             when Digit =>
  17418.                 -- scan the integer field of the exponent
  17419.                 Scan_Integer;
  17420.             when ASCII.UNDERLINE =>        -- '_'
  17421.                 if (Look_Ahead(1) in Digit) then
  17422.                     -- flag illegal leading under line
  17423.                     LEM.Output_Message(
  17424.                         Current_Line
  17425.                         , Current_Column
  17426.                         , LEM.Leading_Underline);
  17427.                     -- scan the integer field of the exponent
  17428.                     Scan_Integer;
  17429.                 else
  17430.                     -- issue error message that integer field is missing
  17431.                     LEM.Output_Message(
  17432.                     Current_Line
  17433.                         , Current_Column
  17434.                         , LEM.Exponent_Missing_Integer_Field);
  17435.                 end if;
  17436.             when others =>
  17437.                 -- issue an error message that integer field is missing
  17438.                 LEM.Output_Message(
  17439.                     Current_Line
  17440.                     , Current_Column
  17441.                     , LEM.Exponent_Missing_Integer_Field);
  17442.         end case;
  17443.         
  17444.     end Scan_Exponent;
  17445.  
  17446.     ------------------------------------------------------------------
  17447.  
  17448.     procedure Scan_Based_Integer(
  17449.         In_Base_To_Use : in Valid_Base_Range) is
  17450.  
  17451.     --| Overview
  17452.     --|
  17453.     --| Note the following LRM Sections:
  17454.     --|     LRM Section 2.4   - Numeric Literals
  17455.     --|     LRM Section 2.4.2 - Based Literals
  17456.     --|
  17457.     
  17458.     ------------------------------------------------------------------
  17459.     -- Declarations for Procedure Scan_Based_Integer
  17460.     ------------------------------------------------------------------
  17461.     
  17462.     BAD : constant GC.ParserInteger := GC.ParserInteger'Last;
  17463.         --| an integer value greater than 15 to use as a flag to indicate
  17464.         --| illegal values.
  17465.  
  17466.     Transform : constant array(CHARACTER) of GC.ParserInteger :=
  17467.     
  17468.     -------- ( nul,  soh,  stx,  etx,     eot,  enq,  ack,  bel,
  17469.              ( BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17470.     --------   bs,   ht,   lf,   vt,      ff,   cr,   so,   si,
  17471.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17472.     --------   dle,  dc1,  dc2,  dc3,     dc4,  nak,  syn,  etb,
  17473.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17474.     --------   can,  em,   sub,  esc,     fs,   gs,   rs,   us,
  17475.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17476.  
  17477.     --------   ' ',  '!',  '"',  '#',     '$',  '%',  '&',  ''',
  17478.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17479.     --------   '(',  ')',  '*',  '+',     ',',  '-',  '.',  '/',
  17480.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17481.     --------   '0',  '1',  '2',  '3',     '4',  '5',  '6',  '7',
  17482.                 0 ,   1 ,   2 ,   3 ,      4 ,   5 ,   6 ,   7 ,
  17483.     --------   '8',  '9',  ':',  ';',     '<',  '=',  '>',  '?',
  17484.                 8 ,   9 ,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17485.     
  17486.     --------   '@',  'A',  'B',  'C',     'D',  'E',  'F',  'G',
  17487.                BAD,  10 ,  11 ,  12 ,     13 ,  14 ,  15 ,  BAD,
  17488.     --------   'H',  'I',  'J',  'K',     'L',  'M',  'N',  'O',
  17489.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17490.     --------   'P',  'Q',  'R',  'S',     'T',  'U',  'V',  'W',
  17491.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17492.     --------   'X',  'Y',  'Z',  '[',     '\',  ']',  '^',  '_',
  17493.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17494.     
  17495.     --------   '`',  'a',  'b',  'c',     'd',  'e',  'f',  'g',
  17496.                BAD,  10 ,  11 ,  12 ,     13 ,  14 ,  15 ,  BAD,
  17497.     --------   'h',  'i',  'j',  'k',     'l',  'm',  'n',  'o',
  17498.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17499.     --------   'p',  'q',  'r',  's',     't',  'u',  'v',  'w',
  17500.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD,
  17501.     --------   'x',  'y',  'z',  '{',     '|',  '}',  '~',   del);
  17502.                BAD,  BAD,  BAD,  BAD,     BAD,  BAD,  BAD,  BAD );
  17503.     --| used to transform a character value to an integer value for
  17504.     --| purpose of checking that a digit is within the legal range
  17505.     --| for the base passed in via In_Base_To_Use.
  17506.  
  17507.     ------------------------------------------------------------------
  17508.  
  17509.     begin
  17510.  
  17511.         -- check that first character, if not an under line,
  17512.         -- is a valid digit for base being used.
  17513.         if (Next_Char /= ASCII.UNDERLINE) and then
  17514.            (Transform(Next_Char) >= In_Base_To_Use)
  17515.         then
  17516.             -- flag digit as invalid for base
  17517.             LEM.Output_Message(
  17518.                 Current_Line
  17519.                 , Current_Column
  17520.                 , Next_Char & ""  -- convert to string
  17521.                 , LEM.Digit_Invalid_For_Base);
  17522.         end if;
  17523.  
  17524.         -- scan source file for rest of the field
  17525.         -- note that first character of the field is stored first
  17526.         Scan_For_Based_Integer: loop
  17527.         
  17528.             Add_Next_Char_To_Source_Rep;
  17529.         
  17530.             -- set up for processing next character
  17531.             Get_Next_Char;
  17532.         
  17533.             case Next_Char is
  17534.                 when 'A' .. 'F' | 'a' .. 'f' | Digit =>
  17535.                     -- check if Next_Char is in valid base range
  17536.                     if (Transform(Next_Char) >= In_Base_To_Use) then
  17537.                         -- flag digit as invalid for base
  17538.                         LEM.Output_Message(
  17539.                             Current_Line
  17540.                             , Current_Column
  17541.                             , Next_Char & ""  -- convert to string
  17542.                             , LEM.Digit_Invalid_For_Base);
  17543.                     end if;
  17544.                     -- rest of action is at start of next loop cycle
  17545.                 when ASCII.UNDERLINE =>    -- '_'
  17546.                     Check_For_Consecutive_Underlines;
  17547.                 when others =>
  17548.                     Check_For_Terminal_Underline;
  17549.                     -- field is terminated by any character except
  17550.                     -- extended digit (letters a to f and digits),
  17551.                     -- or underline
  17552.                     exit Scan_For_Based_Integer; -- this loop
  17553.             end case;
  17554.  
  17555.         end loop Scan_For_Based_Integer;
  17556.         -- Next_Char already updated
  17557.  
  17558.     end Scan_Based_Integer;
  17559.  
  17560.     ------------------------------------------------------------------
  17561.  
  17562.     procedure Scan_Integer is
  17563.     
  17564.     --| Overview
  17565.     --|
  17566.     --| Note the following LRM Sections:
  17567.     --|     LRM Section 2.4   - Numeric Literals
  17568.     --|     LRM Section 2.4.1 - Decimal Literals
  17569.     --|     LRM Section 2.4.1 - Notes
  17570.     --|
  17571.     
  17572.     begin
  17573.     
  17574.         -- scan source file for rest of the field
  17575.         -- note that first character of the field is stored first
  17576.         Scan_For_Integer: loop
  17577.     
  17578.             Add_Next_Char_To_Source_Rep;
  17579.     
  17580.             -- set up for processing next character
  17581.             Get_Next_Char;
  17582.     
  17583.             case Next_Char is
  17584.                 when Digit =>
  17585.                     -- rest of action is at start of next loop cycle
  17586.                     null;
  17587.                 when ASCII.UNDERLINE =>    -- '_'
  17588.                     Check_For_Consecutive_Underlines;
  17589.                 when others =>
  17590.                     Check_For_Terminal_Underline;
  17591.  
  17592.                     -- field is terminated by any character except
  17593.                     --     digit, or underline
  17594.                     exit Scan_For_Integer; -- this loop
  17595.             end case;
  17596.  
  17597.         end loop Scan_For_Integer; -- Next_Char already updated
  17598.  
  17599.     end Scan_Integer;
  17600.  
  17601.     ------------------------------------------------------------------
  17602.  
  17603.     procedure Scan_Numeric_Literal is
  17604.     
  17605.     --| Overview
  17606.     --|
  17607.     --| Note the following LRM Sections:
  17608.     --|     LRM Section 2.4   - Numeric Literals
  17609.     --|     LRM Section 2.4.1 - Decimal Literals
  17610.     --|     LRM Section 2.4.1 - Notes
  17611.     --|     LRM Section 2.4.2 - Based Literals
  17612.     --|     LRM Section 2.10  - Allowed Replacements of Characters
  17613.     --|
  17614.     
  17615.     ------------------------------------------------------------------
  17616.     -- Declarations for Scan_Numeric_Literal
  17617.     ------------------------------------------------------------------
  17618.  
  17619.     Based_Literal_Delimiter : character;
  17620.         --| holds value of first based_literal delimeter:
  17621.         --| ASCII.COLON (':') or ASCII.SHARP ('#');
  17622.         --| so the second one can be checked to be identical.
  17623.     
  17624.     Base_Being_Used : GC.ParserInteger;
  17625.         --| base value to be passed to Scan_Based_Literal.
  17626.     
  17627.     ------------------------------------------------------------------
  17628.     
  17629.     begin
  17630.     
  17631.         CST.gram_sym_val := PT.NumericTokenValue;
  17632.  
  17633.         Work_String_Length := 0;
  17634.         -- also used by sub-scanners called from this subprogram.
  17635.  
  17636.         -- Scan first field
  17637.         Scan_Integer;
  17638.  
  17639.         -- Now, scan rest of literal dependent on what Next_char is
  17640.         case Next_Char is
  17641.  
  17642.             -- have a decimal_literal
  17643.             when '.' =>
  17644.                 if (Look_Ahead(1) = '.') then
  17645.                     -- next token is a range double delimiter.
  17646.                     -- finished with numeric_literal.
  17647.                     Seen_Radix_Point := false;  -- have an integer_literal
  17648.                     -- already set_up for next scanner,
  17649.                     -- no call to Get_Next_Char.
  17650.                 else
  17651.                     Seen_Radix_Point := true;
  17652.                     Add_Next_Char_To_Source_Rep;
  17653.                     Get_Next_Char;
  17654.                     case Next_Char is
  17655.                         when Digit =>
  17656.                             Scan_Integer;
  17657.                             -- check and flag multiple radix points
  17658.                             while (Next_Char = '.') and then
  17659.                                 (Look_Ahead(1) in digit) loop
  17660.                                     LEM.Output_Message
  17661.                                         ( Current_Line
  17662.                                         , Current_Column
  17663.                                         , LEM.Too_Many_Radix_Points);
  17664.                                     Add_Next_Char_To_Source_Rep;
  17665.                                     Get_Next_Char;
  17666.                                     Scan_Integer;
  17667.                             end loop;
  17668.                         when ASCII.UNDERLINE =>        -- '_'
  17669.                             -- flag illegal leading under line
  17670.                             LEM.Output_Message(
  17671.                                 Current_Line
  17672.                                 , Current_Column
  17673.                                 , LEM.Leading_Underline);
  17674.                             Scan_Integer;
  17675.                             -- not flagging an integer consisting of a
  17676.                             -- single underline as a trailing radix
  17677.                             -- point case.  Check and flag multiple radix
  17678.                             -- points.
  17679.                             while (Next_Char = '.') and then
  17680.                                 (Look_Ahead(1) in digit) loop
  17681.                                 LEM.Output_Message(
  17682.                                     Current_Line
  17683.                                     , Current_Column
  17684.                                     , LEM.Too_Many_Radix_Points);
  17685.                                 Add_Next_Char_To_Source_Rep;
  17686.                                 Get_Next_Char;
  17687.                                 Scan_Integer;
  17688.                             end loop;
  17689.                         when others =>
  17690.                             -- flag trailing radix point as an error
  17691.                             LEM.Output_Message(
  17692.                                 Current_Line
  17693.                                 , Current_Column
  17694.                                 , LEM.Digit_Needed_After_Radix_Point);
  17695.                     end case;
  17696.  
  17697.                     Scan_Exponent;  -- check for and process exponent
  17698.  
  17699.                 end if;
  17700.  
  17701.             -- have a based_literal
  17702.             when ASCII.SHARP |     -- '#'
  17703.                  ASCII.COLON =>    -- ':'
  17704.                 Based_Literal_Delimiter := Next_Char;
  17705.                 Base_Being_Used := GC.ParserInteger'VALUE
  17706.                                 (Work_String(1..Work_String_Length));
  17707.                 if (Base_Being_Used not in Valid_Base_Range) then
  17708.                     -- flag illegal bases as errors
  17709.                     LEM.Output_Message(
  17710.                         Current_Line
  17711.                         , Current_Column
  17712.                         , Work_String(1..Work_String_Length)
  17713.                         , LEM.Base_Out_Of_Legal_Range_Use_16);
  17714.                     Base_Being_Used := 16;
  17715.                     -- we use the maximum base to pass all the
  17716.                     -- extended_digits as legal.
  17717.                 end if;
  17718.         
  17719.                 Add_Next_Char_To_Source_Rep;  -- save the base delimiter
  17720.                 Get_Next_Char;
  17721.             
  17722.                 case Next_Char is
  17723.                     when 'A' .. 'F' | 'a' .. 'f' | Digit =>
  17724.                         Scan_Based_Integer(Base_Being_Used);
  17725.                     when ASCII.UNDERLINE =>    -- '_'
  17726.                         -- flag illegal leading under line
  17727.                     LEM.Output_Message(
  17728.                         Current_Line
  17729.                         , Current_Column
  17730.                         , LEM.Leading_Underline);
  17731.                     -- not flagging an integer consisting of a single
  17732.                     -- under line as a trailing radix point case.
  17733.                     Scan_Based_Integer(Base_Being_Used);
  17734.                     when '.' =>
  17735.                         -- flag leading radix point as an error
  17736.                         LEM.Output_Message(
  17737.                             Current_Line
  17738.                             , Current_Column
  17739.                             , LEM.Digit_Needed_Before_Radix_Point);
  17740.                     when ASCII.SHARP |         -- '#'
  17741.                          ASCII.COLON =>        -- ':'
  17742.                         -- flag missing field as an error
  17743.                         LEM.Output_Message(
  17744.                             Current_Line
  17745.                             , Current_Column
  17746.                             , LEM.No_Integer_In_Based_Number);
  17747.                 
  17748.                         -- based_literal_delimiter_mismatch handled in
  17749.                         -- next case statement.
  17750.                     when others =>
  17751.                         -- flag missing field as an error
  17752.                         LEM.Output_Message(
  17753.                             Current_Line
  17754.                             , Current_Column
  17755.                             , LEM.No_Integer_In_Based_Number);
  17756.                 end case;
  17757.                 
  17758.                 case Next_Char is
  17759.                     when '.' =>
  17760.                         Seen_Radix_Point := true;  -- have a real_literal
  17761.                         Add_Next_Char_To_Source_Rep;
  17762.                 
  17763.                         Get_Next_Char;
  17764.                         case Next_Char is
  17765.                             when 'A' .. 'F' | 'a' .. 'f' | Digit =>
  17766.                                 Scan_Based_Integer(Base_Being_Used);
  17767.                                 -- check and flag multiple radix points
  17768.                                 while (Next_Char = '.') and then
  17769.                                     ((Look_Ahead(1) in digit) or
  17770.                                     (Look_Ahead(1) in 'A' .. 'F') or
  17771.                                     (Look_Ahead(1) in 'a' .. 'f')) loop
  17772.                                     LEM.Output_Message(
  17773.                                         Current_Line
  17774.                                         , Current_Column
  17775.                                         , LEM.Too_Many_Radix_Points);
  17776.                                     Add_Next_Char_To_Source_Rep;
  17777.                                     Get_Next_Char;
  17778.                                     Scan_Based_Integer(Base_Being_Used);
  17779.                                 end loop;
  17780.                             when ASCII.UNDERLINE =>        -- '_'
  17781.                                 -- flag illegal leading under lined
  17782.                                 LEM.Output_Message(
  17783.                                     Current_Line
  17784.                                     , Current_Column
  17785.                                     , LEM.Leading_Underline);
  17786.                                 -- not flagging an integer consisting of
  17787.                                 -- a single underline as a trailing
  17788.                                 -- radix point case.
  17789.                                 Scan_Based_Integer(Base_Being_Used);
  17790.                             when others =>
  17791.                                 -- flag trailing radix point as an error
  17792.                                 LEM.Output_Message(
  17793.                                     Current_Line
  17794.                                     , Current_Column
  17795.                                     , LEM.Digit_Needed_After_Radix_Point);
  17796.                         end case;
  17797.  
  17798.                         case Next_Char is
  17799.                             when ASCII.SHARP |         -- '#'
  17800.                                  ASCII.COLON =>        -- ':'
  17801.                 
  17802.                                 Add_Next_Char_To_Source_Rep;
  17803.                                 -- save the base delimiter
  17804.  
  17805.                                 if (Next_Char /= Based_Literal_Delimiter)
  17806.                                 then
  17807.                                     -- flag based_literal delimiter
  17808.                                     -- mismatch as an error
  17809.                                     LEM.Output_Message(
  17810.                                         Current_Line
  17811.                                         , Current_Column
  17812.                                         ,   "Opener: "
  17813.                                         & Based_Literal_Delimiter
  17814.                                         & " Closer: " & Next_Char
  17815.                                         , LEM.Based_Literal_Delimiter_Mismatch);
  17816.                                 end if;
  17817.  
  17818.                                 Get_Next_Char; -- after base delimiter
  17819.                                 -- check for and process exponent
  17820.                                 Scan_Exponent;
  17821.                 
  17822.                             when others =>
  17823.                                 -- flag missing second
  17824.                                 -- based_literal delimiter as an error
  17825.                                 LEM.Output_Message(
  17826.                                     Current_Line
  17827.                                     , Current_Column
  17828.                                     , LEM.Missing_Second_Based_Literal_Delimiter);
  17829.                         end case;
  17830.  
  17831.                     when ASCII.SHARP |         -- '#'
  17832.                          ASCII.COLON =>        -- ':'
  17833.                         -- have an integer_literal
  17834.                         Seen_Radix_Point := false;
  17835.                         -- save the base delimiter
  17836.                         Add_Next_Char_To_Source_Rep;
  17837.                 
  17838.                         if (Next_Char /= Based_Literal_Delimiter) then
  17839.                         -- flag based_literal delimiter mismatch error
  17840.                             LEM.Output_Message(
  17841.                                 Current_Line
  17842.                                 , Current_Column
  17843.                                 ,   "Opener: "  & Based_Literal_Delimiter
  17844.                                   & " Closer: " & Next_Char
  17845.                                 , LEM.Based_Literal_Delimiter_Mismatch);
  17846.                         end if;
  17847.                 
  17848.                         Get_Next_Char;  -- get character after base delimiter
  17849.                         Scan_Exponent;  -- check for and process exponent
  17850.                 
  17851.                     when others =>
  17852.                         -- assume an integer_literal
  17853.                         Seen_Radix_Point := false;
  17854.                         -- flag missing second
  17855.                         -- based_literal delimiter as an error
  17856.                         LEM.Output_Message(
  17857.                             Current_Line
  17858.                             , Current_Column
  17859.                             , LEM.Missing_Second_Based_Literal_Delimiter);
  17860.                 end case;
  17861.                 
  17862.             --we have an integer_literal
  17863.             when others =>
  17864.                 Seen_Radix_Point := false;  -- have an integer_literal
  17865.                 Scan_Exponent;  -- check for and process exponent
  17866.         end case;
  17867.                 
  17868.         -- one last error check
  17869.         if (Next_Char in Upper_Case_Letter) or
  17870.            (Next_Char in Lower_Case_Letter) then
  17871.             -- flag missing space between numeric_literal and
  17872.             -- identifier (including RW) as an error.
  17873.             LEM.Output_Message
  17874.                 ( Current_Line
  17875.                 , Current_Column
  17876.                 , LEM.Space_Must_Separate_Num_And_Ids);
  17877.         end if;
  17878.  
  17879.         -- now store the source representation of the token found.
  17880.         Set_CST_Source_Rep(Work_String(1..Work_String_Length));
  17881.  
  17882.     end Scan_Numeric_Literal;
  17883.  
  17884.     ------------------------------------------------------------------
  17885.     
  17886.     procedure Scan_String_Literal is
  17887.     
  17888.     --| Overview
  17889.     --|
  17890.     --| Note the following LRM Sections:
  17891.     --|     LRM Section 2.6  - String Literals
  17892.     --|     LRM Section 2.6  - Note
  17893.     --|     LRM Section 2.10 - Allowed Replacements of Characters
  17894.     --|
  17895.     
  17896.         String_Delimiter : character := Next_Char;
  17897.     
  17898.     begin
  17899.     
  17900.         Work_String_Length := 0;
  17901.         
  17902.         CST.gram_sym_val := PT.StringTokenValue;
  17903.         
  17904.         -- scan until matching string delimiter or end of line is found
  17905.         Scan_For_String: loop
  17906.             Get_Next_Char;
  17907.         
  17908.             if (Next_Char = String_Delimiter) then
  17909.                 Get_Next_Char;
  17910.                 if (Next_Char = String_Delimiter) then
  17911.                     -- add one string delimiter to growing string
  17912.                     Add_Next_Char_To_Source_Rep;
  17913.                 else     -- string is ended
  17914.                     exit Scan_For_String;
  17915.                 end if;
  17916.             elsif (Next_Char in Graphic_Character) then
  17917.                 -- add graphic character to growing string
  17918.                 Add_Next_Char_To_Source_Rep;
  17919.             elsif (Next_Char in End_Of_Line_Character) then
  17920.                 -- string is ended. flag the error.
  17921.                 LEM.Output_Message(
  17922.                     Current_Line
  17923.                     , Current_Column
  17924.                     , LEM.No_Ending_String_Delimiter);
  17925.                 exit Scan_For_String;
  17926.             else    -- flag non-graphic characters as errors
  17927.                 LEM.Output_Message(
  17928.                     Current_Line
  17929.                     , Current_Column
  17930.                     , Integer'Image(Character'Pos(Next_Char))
  17931.                                       -- convert to string
  17932.                     , LEM.Only_Graphic_Characters_In_Strings);
  17933.             end if;
  17934.  
  17935.         end loop Scan_For_String;    -- Next_Char already updated
  17936.  
  17937.         -- now store the source representation found without the
  17938.         -- string delimiters
  17939.         Set_CST_Source_Rep(Work_String(1..Work_String_Length));
  17940.  
  17941.         return;
  17942.  
  17943.     end Scan_String_Literal;
  17944.  
  17945.     ------------------------------------------------------------------
  17946.  
  17947.     function Show_Current_Line
  17948.     return HD.Source_Line is
  17949.  
  17950.     --| Overview
  17951.     --| Return current line number
  17952.  
  17953.     begin
  17954.  
  17955.     return Current_Line;
  17956.  
  17957.     end Show_Current_Line;
  17958.  
  17959.     ------------------------------------------------------------------
  17960.  
  17961.     procedure Write_Line is separate;
  17962.  
  17963.     ------------------------------------------------------------------
  17964. end Lex;
  17965.  
  17966. ----------------------------------------------------------------------
  17967.  
  17968. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17969. --WRITELINE.SUB
  17970. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17971. separate (Lex)
  17972. procedure Write_Line is
  17973.     begin
  17974.     null;
  17975.     end Write_Line;
  17976.  
  17977.