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

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --CISC.SPC
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. package case_insensitive_string_comparison is
  5.  
  6. --| Overview
  7. --| This package provides a complete set of comparison functions on strings
  8. --| where case is NOT important ("a" = "A").
  9.  
  10. --| Standard_Renaming: CISC or simply SC
  11. --| Programmer: M. Gordon
  12.  
  13. ------------------------------------------------------------------------
  14.  
  15. function toUpper(    --| Return upper case equivalent of C.
  16.     C: character
  17.     ) return character;
  18.  
  19. --| Effects: If C is in 'a'..'z' return the corresponding upper case
  20. --| character.  Otherwise, return C.  This is implemented by a table
  21. --| lookup for speed.
  22.  
  23. --| N/A: Raises, Requires, Modifies
  24.  
  25.  
  26. procedure upCase(    --| Convert all characters in S to upper case
  27.     S: in out String
  28.     );
  29.  
  30. --| Effects: Convert all characters in S to upper case.
  31. --| N/A: Raises, Requires, Modifies
  32.  
  33.     pragma inline(upCase);
  34.  
  35.  
  36. function upCase(    --| Return copy of S with all characters upper case
  37.     S: String
  38.     ) return String;
  39.  
  40. --| Effects: Make a copy of S, convert all lower case characters to upper
  41. --| case and return the copy.
  42.  
  43. --| N/A: Raises, Requires, Modifies
  44.  
  45. ------------------------------------------------------------------------
  46.  
  47. function toLower(    --| Return lower case equivalent of C.
  48.     C: character
  49.     ) return character;
  50.  
  51. --| Effects: If C is in 'A'..'Z' return the corresponding lower case
  52. --| character.  Otherwise, return C.  This is implemented by a table
  53. --| lookup for speed.
  54.  
  55. --| N/A: Raises, Requires, Modifies
  56.  
  57.  
  58. procedure downCase(    --| Convert all characters in S to lower case
  59.     S: in out String
  60.     );
  61.  
  62. --| Effects: Convert all characters in S to lower case.
  63. --| N/A: Raises, Requires, Modifies
  64.  
  65.     pragma inline(downCase);
  66.  
  67.  
  68. function downCase(    --| Return copy of S with all characters lower case
  69.     S: String
  70.     ) return String;
  71.  
  72. --| Effects: Make a copy of S, convert all lower case characters to lower
  73. --| case and return the copy.
  74.  
  75. --| N/A: Raises, Requires, Modifies
  76.  
  77. ------------------------------------------------------------------------
  78.  
  79. function compare(    --| Compare two strings
  80.     P, Q: String
  81.     ) return integer;
  82.  
  83. --| Effects: Return an integer less than zero if P < Q, zero if P = Q, and
  84. --| an integer greater than zero if P > Q.
  85.  
  86. --| N/A: Raises, Requires, Modifies
  87.  
  88. ------------------------------------------------------------------------
  89.  
  90. function equal(        --| Return True iff P = Q.
  91.     P, Q: String
  92.     ) return boolean;
  93.  
  94. --| N/A: Raises, Requires, Modifies, Effects
  95.  
  96. function less(        --| Return True iff P < Q.
  97.     P, Q: String
  98.     ) return boolean;
  99. --| N/A: Raises, Requires, Modifies, Effects
  100.  
  101.  
  102. function less_or_equal(    --| Return True iff P <= Q.
  103.     P, Q: String
  104.     ) return boolean;
  105.  
  106. --| N/A: Raises, Requires, Modifies, Effects
  107.  
  108.  
  109. function greater(    --| Return True iff P > Q.
  110.     P, Q: String
  111.     ) return boolean;
  112.  
  113. --| N/A: Raises, Requires, Modifies, Effects
  114.  
  115.  
  116. function greater_or_equal(    --| Return True iff P >= Q.
  117.     P, Q: String
  118.     ) return boolean;
  119.  
  120. --| N/A: Raises, Requires, Modifies, Effects
  121.  
  122. ------------------------------------------------------------------------
  123.  
  124. private
  125.     pragma inline(equal, less, less_or_equal, greater, greater_or_equal);
  126.     pragma inline(toUpper, toLower);
  127.  
  128. end case_insensitive_string_comparison;
  129. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  130. --CSSC.SPC
  131. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  132. package case_sensitive_string_comparison is
  133.  
  134. --| Overview
  135. --| This package provides a complete set of comparison functions on strings
  136. --| where case is important ("a" /= "A").  In most cases these have the same
  137. --| effect as the Ada predefined operators.  However, using this package
  138. --| makes it easier to substitute case-insensitive comparison later
  139.  
  140. --| Standard_Renaming: CSSC or simply SC
  141. --| Programmer: M. Gordon
  142.  
  143. ------------------------------------------------------------------------
  144.  
  145. function compare(    --| Compare two strings
  146.     P, Q: String
  147.     ) return integer;
  148.  
  149. --| Effects: Return an integer less than zero if P < Q, zero if P = Q, and
  150. --| an integer greater than zero if P > Q.
  151.  
  152. --| N/A: Raises, Requires, Modifies
  153.  
  154. ------------------------------------------------------------------------
  155.  
  156. function equal(        --| Return True iff P = Q.
  157.     P, Q: String
  158.     ) return boolean;
  159.  
  160. --| N/A: Raises, Requires, Modifies, Effects
  161.  
  162. function less(        --| Return True iff P < Q.
  163.     P, Q: String
  164.     ) return boolean;
  165. --| N/A: Raises, Requires, Modifies, Effects
  166.  
  167.  
  168. function less_or_equal(    --| Return True iff P <= Q.
  169.     P, Q: String
  170.     ) return boolean;
  171.  
  172. --| N/A: Raises, Requires, Modifies, Effects
  173.  
  174. function greater(    --| Return True iff P > Q.
  175.     P, Q: String
  176.     ) return boolean;
  177.  
  178. --| N/A: Raises, Requires, Modifies, Effects
  179.  
  180.  
  181. function greater_or_equal(    --| Return True iff P >= Q.
  182.     P, Q: String
  183.     ) return boolean;
  184.  
  185. --| N/A: Raises, Requires, Modifies, Effects
  186.  
  187. ------------------------------------------------------------------------
  188.  
  189. private
  190.     pragma inline(equal, less, less_or_equal, greater, greater_or_equal);
  191.  
  192. end case_sensitive_string_comparison;
  193. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  194. --CISC.BDY
  195. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  196. package body case_insensitive_string_comparison is
  197.  
  198. --| Overview
  199. --| Strings are compared one character at a time, stopping as soon as
  200. --| possible. 
  201.  
  202. --| Programmer: M. Gordon
  203.  
  204. ------------------------------------------------------------------------
  205.  
  206. Up_ConvertArray: array(Character) of Character;
  207. Down_ConvertArray: array(Character) of Character;
  208. Difference: constant := Character'pos('a') - Character'pos('A');
  209.  
  210. function toUpper(C: character) return character is
  211. begin
  212.     return Up_ConvertArray(C);
  213.  
  214. end toUpper;
  215.  
  216.  
  217. function upCase(    --| Return copy of S with all characters lower case
  218.     S: String
  219.     ) return String
  220. is
  221.     R: String(S'Range) := S;
  222.  
  223. begin
  224.     for i in R'Range loop
  225.     R(i) := toUpper(R(i));
  226.     end loop;
  227.     return R;
  228.  
  229. end upCase;
  230.  
  231.  
  232. procedure upCase(    --| Convert all characters in S to lower case
  233.     S: in out String
  234.     ) is
  235.  
  236. begin
  237.     for i in S'Range loop
  238.     S(i) := toUpper(S(i));
  239.     end loop;
  240.  
  241. end upCase;
  242.  
  243. ------------------------------------------------------------------------
  244.  
  245. function toLower(C: character) return character is
  246. begin
  247.     return Down_ConvertArray(C);
  248.  
  249. end toLower;
  250.  
  251.  
  252. function downCase(    --| Return copy of S with all characters lower case
  253.     S: String
  254.     ) return String
  255. is
  256.     R: String(S'Range) := S;
  257.  
  258. begin
  259.     for i in R'Range loop
  260.     R(i) := toLower(R(i));
  261.     end loop;
  262.     return R;
  263.  
  264. end downCase;
  265.  
  266. procedure downCase(    --| Convert all characters in S to lower case
  267.     S: in out String
  268.     ) is
  269.  
  270. begin
  271.     for i in S'Range loop
  272.     S(i) := toLower(S(i));
  273.     end loop;
  274.  
  275. end downCase;
  276.  
  277. ------------------------------------------------------------------------
  278.  
  279. function compare(    --| Compare two strings
  280.     P, Q: String
  281.     ) return integer
  282. is
  283.     PI, QI: natural;
  284.     PC, QC: character;
  285.  
  286. begin
  287.     QI := Q'First;
  288.     for PI in P'First .. P'Last loop
  289.       if QI > Q'Last then
  290.     return 1;    -- Q ran out before P did.
  291.       end if;
  292.       PC := toUpper(P(PI));
  293.       QC := toUpper(Q(QI));
  294.       if PC /= QC then
  295.     return character'pos(PC) - character'pos(QC);
  296.       end if;
  297.       QI := QI + 1;
  298.     end loop;
  299.     return P'Length - Q'Length;    -- Equal so far: longer string is greater
  300.  
  301. end compare;
  302.  
  303. ------------------------------------------------------------------------
  304.  
  305. function equal(
  306.     P, Q: String
  307.     ) return boolean is
  308. begin
  309.     return compare(P, Q) = 0;
  310.  
  311. end equal;
  312.  
  313. ------------------------------------------------------------------------
  314.  
  315. function less(
  316.     P, Q: String
  317.     ) return boolean is
  318. begin
  319.     return compare(P, Q) < 0;
  320. end less;
  321.  
  322.  
  323. function less_or_equal(
  324.     P, Q: String
  325.     ) return boolean is
  326. begin
  327.     return compare(P, Q) <= 0;
  328. end less_or_equal;
  329.  
  330.  
  331. ------------------------------------------------------------------------
  332.  
  333. function greater(
  334.     P, Q: String
  335.     ) return boolean is
  336. begin
  337.     return compare(P, Q) > 0;
  338. end greater;
  339.  
  340. function greater_or_equal(
  341.     P, Q: String
  342.     ) return boolean is
  343. begin
  344.     return compare(P, Q) >= 0;
  345. end greater_or_equal;
  346.  
  347. ------------------------------------------------------------------------
  348.  
  349. begin
  350.  
  351.   for I in Character loop
  352.     case I is
  353.       when 'a' .. 'z' => 
  354.         Up_ConvertArray(I) := Character'val(Character'pos(I) - Difference);
  355.       when others =>
  356.         Up_ConvertArray(I) := I;
  357.     end case;
  358.   end loop;
  359.  
  360.   for I in Character loop
  361.     case I is
  362.       when 'A' .. 'Z' => 
  363.         Down_ConvertArray(I) := Character'val(Character'pos(I) + Difference);
  364.       when others =>
  365.         Down_ConvertArray(I) := I;
  366.     end case;
  367.   end loop;
  368.  
  369. end case_insensitive_string_comparison;
  370. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  371. --CSSC.BDY
  372. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  373. package body case_sensitive_string_comparison is
  374.  
  375. --| Overview
  376. --| Strings are compared one character at a time, stopping as soon as
  377. --| possible. 
  378.  
  379. --| Programmer: M. Gordon
  380.  
  381. ------------------------------------------------------------------------
  382.  
  383. function compare(    --| Compare two strings
  384.     P, Q: String
  385.     ) return integer
  386. is
  387.     PI, QI: natural;
  388.  
  389. begin
  390.     QI := Q'First;
  391.     for PI in P'First .. P'Last loop
  392.       if QI > Q'Last then
  393.     return 1;    -- Q ran out before P did.
  394.       end if;
  395.       if P(PI) /= Q(QI) then
  396.     return character'pos(P(PI)) - character'pos(Q(QI));
  397.       end if;
  398.       QI := QI + 1;
  399.     end loop;
  400.     return P'Length - Q'Length;    -- Equal so far: longer string is greater
  401.  
  402. end  compare;
  403.  
  404. ------------------------------------------------------------------------
  405.  
  406. function equal(
  407.     P, Q: String
  408.     ) return boolean is
  409. begin
  410.     return P = Q;
  411.  
  412. end equal;
  413.  
  414. ------------------------------------------------------------------------
  415.  
  416. function less(
  417.     P, Q: String
  418.     ) return boolean is
  419. begin
  420.     return P < Q;
  421. end less;
  422.  
  423.  
  424. function less_or_equal(
  425.     P, Q: String
  426.     ) return boolean is
  427. begin
  428.     return P <= Q;
  429. end less_or_equal;
  430.  
  431.  
  432. ------------------------------------------------------------------------
  433.  
  434. function greater(
  435.     P, Q: String
  436.     ) return boolean is
  437. begin
  438.     return P > Q;
  439. end greater;
  440.  
  441. function greater_or_equal(
  442.     P, Q: String
  443.     ) return boolean is
  444. begin
  445.     return P >= Q;
  446. end greater_or_equal;
  447.  
  448. ------------------------------------------------------------------------
  449.  
  450. end case_sensitive_string_comparison;
  451. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  452. --BINTREE.SPC
  453. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  454. generic
  455.     type Value_Type is private;    --| Type of values stored in the tree.
  456.  
  457.     with function Difference(P, Q: Value_Type) return integer is <>;
  458.     --| Must return a value > 0 if P > Q, 0 if P = Q, and less than
  459.     --| zero otherwise.
  460.  
  461. package binary_trees_pkg is    --| Efficient implementation of binary trees.
  462.  
  463. --| OVERVIEW
  464.  
  465. --| This package is an efficient implementation of unbalanced binary trees.
  466. --| These trees have the following properties:
  467. --|-
  468. --|  1. Inserting a value is cheap (log n Differences per insertion).
  469. --|  2. Finding a value is cheap (log n Differences per querey).
  470. --|  3. Can iterate over the values in sorted order in linear time.
  471. --|  4. Space overhead is moderate (2 "pointers" per value stored).
  472. --|+
  473. --| They are thus useful both for sorting sequences of indeterminate size
  474. --| and for lookup tables.
  475. --| 
  476. --| OPERATIONS
  477. --| 
  478. --|-The following operations are provided:
  479. --| 
  480. --| Insert        Insert a node into a tree
  481. --| Insert_if_not_Found    Insert a node into a tree if not there already
  482. --| Replace_if_Found    Replace a node if duplicate exists, else insert.
  483. --| Destroy        Destroy a tree
  484. --| Destroy_Deep*    Destroy a tree and its contents
  485. --| Balanced_Tree*    Create a balanced tree from values supplied in order
  486. --| Copy*        Copy a tree.  The copy is balanced.
  487. --| 
  488. --| Queries:
  489. --|   Is_Empty        Return TRUE iff a tree is empty.
  490. --|   Find        Search tree for a node
  491. --|   Is_Found        Return TRUE iff tree contains specified value.
  492. --|   Size        Return number of nodes in the tree.
  493. --| 
  494. --| Iterators:
  495. --|   Visit*        Apply a procedure to every node in specified order
  496. --|   Make_Iter        Create an iterator for ordered scan
  497. --|   More        Test for exhausted iterator
  498. --|   Next        Bump an iterator to the next element
  499. --| 
  500. --| * Indicates generic subprogram
  501. --| 
  502. --| USAGE
  503. --| 
  504. --| The following example shows how to use this package where nodes in
  505. --| the tree are labeled with a String_Type value (for which a natural
  506. --| Difference function is not available).
  507. --|-
  508. --|     package SP renames String_Pkg;
  509. --| 
  510. --|     type my_Value is record
  511. --|       label: SP.string_type;
  512. --|       value: integer;
  513. --|     end record;
  514. --| 
  515. --|     function differ_label(P, Q: SP.string_type) return integer is
  516. --|     begin
  517. --|       if SP."<"(P, Q) then return -1;
  518. --|       elsif SP."<"(Q, P) then return 1;
  519. --|       else return 0;
  520. --|       end if;
  521. --|     end differ_label;
  522. --| 
  523. --|     package my_Tree is new Binary_Trees_pkg(my_Value, differ_Label);
  524. --| 
  525. --| Note that the required Difference function may be easily written in terms
  526. --| of "<" if that is available, but that frequently two comparisons must
  527. --| be done for each Difference.  However, both comparisons would have
  528. --| to be done internally by this package for every instantiation if the
  529. --| generic parameter were "<" instead of Difference.
  530. --| 
  531. --| PERFORMANCE
  532. --|
  533. --| Every node can be visited in the tree in linear time.  The cost
  534. --| of creating an iterator is small and independent of the size
  535. --| of the tree.
  536. --| 
  537. --| Recognizing that comparing values can be expensive, this package
  538. --| takes a Difference function as a generic parameter.  If it took
  539. --| a comparison function such as "<", then two comparisons would be
  540. --| made per node visited during a search of the tree.  Of course this
  541. --| is more costly when "<" is a trivial operation, but in those cases,
  542. --| Difference can be bound to "-" and the overhead in negligable.
  543. --| 
  544. --| Two different kinds of iterators are provided.  The first is the 
  545. --| commonly used set of functions Make_Iter, More, and Next.  The second
  546. --| is a generic procedure called Visit.  The generic parameter to Visit is
  547. --| a procedure which is called once for each value in the tree.  Visit
  548. --| is more difficult to use and results in code that is not quite as clear,
  549. --| but its overhead is about 20% of the More/Next style iterator.  It
  550. --| is therefore recommended for use only in time critical inner loops.
  551.  
  552.  
  553. ----------------------------------------------------------------------------
  554.                 -- Exceptions --
  555. ----------------------------------------------------------------------------
  556.  
  557. Duplicate_Value: exception;
  558. --| Raised on attempt to insert a duplicate node into a tree.
  559.  
  560. Not_Found: exception;
  561. --| Raised on attempt to find a node that is not in a tree.
  562.  
  563. No_More: exception;
  564. --| Raised on attempt to bump an iterator that has already scanned the
  565. --| entire tree.
  566.  
  567. Out_Of_Order: exception;
  568. --| Raised if a problem in the ordering of a tree is detected.
  569.  
  570. Invalid_Tree: exception;
  571. --| Value is not a tree or was not properly initialized.
  572.  
  573. ----------------------------------------------------------------------------
  574.                 -- Types --
  575. ----------------------------------------------------------------------------
  576.  
  577. type Scan_Kind is (inorder, preorder, postorder);
  578. --| Used to specify the order in which values should be scanned from a tree:
  579. --|-
  580. --| inorder: Left, Node, Right (nodes visited in increasing order)
  581. --| preorder: Node, Left, Right (top down)
  582. --| postorder: Left, Right, Node (bottom up)
  583.  
  584. type Tree is private;
  585. type Iterator is private;
  586.  
  587. ----------------------------------------------------------------------------
  588.                 -- Operations --
  589. ----------------------------------------------------------------------------
  590.  
  591. Function Create        --| Return an empty tree.
  592.     return Tree;
  593.  
  594. --| Effects: Create and return an empty tree.  Note that this allocates
  595. --| a small amount of storage which can only be reclaimed through 
  596. --| a call to Destroy.
  597.  
  598. ----------------------------------------------------------------------------
  599.  
  600. Procedure Insert(    --| Insert a value into a tree.
  601.     V: Value_Type;    --| Value to be inserted
  602.     T: Tree        --| Tree to contain the new value
  603.     );
  604. --| Raises: Duplicate_Value, Invalid_Tree.
  605.  
  606. --| Effects: Insert V into T in the proper place.  If a value equal
  607. --| to V (according to the Difference function) is already contained
  608. --| in the tree, the exception Duplicate_Value is raised.
  609. --| Caution: Since this package does not attempt to balance trees as
  610. --| values are inserted, it is important to remember that inserting
  611. --| values in sorted order will create a degenerate tree, where search
  612. --| and insertion is proportional to the N instead of to Log N.  If
  613. --| this pattern is common, use the Balanced_Tree function below.
  614.  
  615. ----------------------------------------------------------------------------
  616.  
  617. procedure Insert_if_not_Found(
  618. --| Insert a value into a tree, provided a duplicate value is not already there
  619.     V: Value_Type;    --| Value to be inserted
  620.     T: Tree;        --| Tree to contain the new value
  621.     Found: out boolean;    --| Becomes True iff V already in tree
  622.     Duplicate: out Value_Type    --| the duplicate value, if there is one
  623.     ); --| Raises: Invalid_Tree.
  624.  
  625. --| Effects: Insert V into T in the proper place.  If a value equal
  626. --| to V (according to the Difference function) is already contained
  627. --| in the tree, Found will be True and Duplicate will be the duplicate
  628. --| value.  This might be a sequence of values with the same key, and
  629. --| V can then be added to the sequence.
  630.  
  631. ----------------------------------------------------------------------------
  632.  
  633. procedure Replace_if_Found(
  634. --| Replace a value if label exists, otherwise insert it.
  635.     V: Value_Type;    --| Value to be inserted
  636.     T: Tree;        --| Tree to contain the new value
  637.     Found: out boolean;    --| Becomes True iff L already in tree
  638.     Old_Value: out Value_Type    --| the duplicate value, if there is one
  639.     ); --| Raises: Invalid_Tree.
  640.  
  641. --| Effects: Search for V in T.  If found, replace the old value with V,
  642. --| and return Found => True, Old_Value => the old value.  Otherwise,
  643. --| simply insert V into T and return Found => False.
  644.  
  645. ----------------------------------------------------------------------------
  646.  
  647. procedure Destroy(    --| Free space allocated to a tree.
  648.     T: in out Tree    --| The tree to be reclaimed.
  649.     );
  650.  
  651. --| Effects: The space allocated to T is reclaimed.  The space occupied by
  652. --| the values stored in T is not however, recovered.
  653.  
  654. ----------------------------------------------------------------------------
  655.  
  656. generic
  657.     with procedure free_Value(V: in out Value_Type) is <>;
  658.  
  659. procedure Destroy_Deep(    --| Free all space allocated to a tree.
  660.     T: in out Tree    --| The tree to be reclaimed.
  661.     );
  662.  
  663. --| Effects: The space allocated to T is reclaimed.  The values stored
  664. --| in T are reclaimed using Free_Value, and the tree nodes themselves
  665. --| are then reclaimed (in a single walk of the tree).
  666.  
  667. ----------------------------------------------------------------------------
  668.  
  669. generic
  670.     with function next_Value return Value_Type is <>;
  671.     --| Each call to this procedure should return the next value to be
  672.     --| inserted into the balanced tree being created.  If necessary,
  673.     --| this function should check that each value is greater than the
  674.     --| previous one, and raise Out_of_Order if necessary.  If values
  675.     --| are not returned in strictly increasing order, the results are
  676.     --| unpredictable.
  677.  
  678. Function Balanced_Tree(    
  679.     Count: natural
  680.     ) return Tree;
  681.  
  682. --| Effects: Create a balanced tree by calling next_Value Count times.
  683. --| Each time Next_Value is called, it must return a value that compares
  684. --| greater than the preceeding value.  This function is useful for balancing
  685. --| an existing tree (next_Value iterates over the unbalanced tree) or
  686. --| for creating a balanced tree when reading data from a file which is
  687. --| already sorted.
  688.  
  689. ----------------------------------------------------------------------------
  690.  
  691. generic
  692.     with function Copy_Value(V: Value_Type) return Value_Type is <>;
  693.     --| This function is called to copy a value from the old tree to the
  694.     --| new tree.
  695.  
  696. Function Copy_Tree(
  697.     T: Tree
  698.     ) return Tree; --| Raises Invalid_Tree.
  699.  
  700. --| Effects: Create a balanced tree that is a copy of the tree T.
  701. --| The exception Invalid_Tree is raised if T is not a valid tree.
  702.  
  703. ----------------------------------------------------------------------------
  704.  
  705. Function Is_Empty(    --| Check for an empty tree.
  706.     T: Tree
  707.     ) return boolean;
  708.  
  709. --| Effects: Return TRUE iff T is an empty tree or if T was not initialized.
  710.  
  711. ----------------------------------------------------------------------------
  712.  
  713. Function Find(        --| Search a tree for a value.
  714.     V: Value_Type;    --| Value to be located
  715.     T: Tree        --| Tree to be searched
  716.     ) return Value_Type; --| Raises: Not_Found, Invalid_Tree.
  717.  
  718. --| Effects: Search T for a value that matches V.  The matching value is
  719. --| returned.  If no matching value is found, the exception Not_Found
  720. --| is raised.
  721.  
  722.  
  723. Procedure Find(            --| Search a tree for a value.
  724.     V: Value_Type;        --| Value to be located
  725.     T: Tree;            --| Tree to be searched
  726.     Found: out Boolean;        --| TRUE iff a match was found
  727.     Match: out Value_Type    --| Matching value found in the tree
  728.     ); --| Raises: Invalid_Tree;
  729.  
  730. --| Effects: Search T for a value that matches V.  On return, if Found is
  731. --| TRUE then the matching value is returned in Match.  Otherwise, Found
  732. --| is FALSE and Match is undefined.
  733.  
  734. ----------------------------------------------------------------------------
  735.  
  736. function is_Found(    --| Check a tree for a value.
  737.     V: Value_Type;    --| Value to be located
  738.     T: Tree        --| Tree to be searched
  739.     ) return Boolean; --| Raises: Invalid_Tree;
  740.  
  741. --| Effects: Return TRUE iff V is found in T.
  742.  
  743. ----------------------------------------------------------------------------
  744.  
  745. function Size(        --| Return the count of values in T.
  746.     T: Tree        --| a tree
  747.     ) return natural; 
  748.  
  749. --| Effects: Return the number of values stored in T.
  750.  
  751. ----------------------------------------------------------------------------
  752.  
  753. generic
  754.     with procedure Process(V: Value_Type) is <>;
  755.  
  756. procedure Visit(
  757.     T: Tree;
  758.     Order: Scan_Kind
  759.     ); --| Raises: Invalid_Tree;
  760.  
  761. --| Effects: Invoke Process(V) for each value V in T.  The nodes are visited
  762. --| in the order specified by Order.  Although more limited than using
  763. --| an iterator, this function is also much faster.
  764.  
  765. ----------------------------------------------------------------------------
  766.  
  767. function Make_Iter(    --| Create an iterator over a tree
  768.     T: Tree
  769.     ) return Iterator; --| Raises: Invalid_Tree;
  770.  
  771. ----------------------------------------------------------------------------
  772.  
  773. function More(        --| Test for exhausted iterator
  774.     I: Iterator        --| The iterator to be tested
  775.     ) return boolean;
  776.  
  777. --| Effects: Return TRUE iff unscanned nodes remain in the tree being
  778. --| scanned by I.
  779.  
  780.  
  781. ----------------------------------------------------------------------------
  782.  
  783. procedure Next(        --| Scan the next value in I
  784.     I: in out Iterator;    --| an active iterator
  785.     V: out Value_Type    --| Next value scanned
  786.     ); --| Raises: No_More.
  787.  
  788. --| Effects: Return the next value in the tree being scanned by I.
  789. --| The exception No_More is raised if there are no more values to scan.
  790.  
  791. ----------------------------------------------------------------------------
  792.  
  793. private
  794.  
  795. type Node;
  796. type Node_Ptr is access Node;
  797.  
  798. type Node is 
  799.     record
  800.     Value: Value_Type;
  801.     Less: Node_Ptr;
  802.     More: Node_Ptr;
  803.     end record;
  804.  
  805. type Tree_Header is 
  806.     record
  807.     Count: natural := 0;
  808.     Root: Node_Ptr := Null;
  809.     end record;
  810.  
  811. type Tree is access Tree_Header;
  812.  
  813. type Iter_State is (Left, Middle, Right, Done);
  814.  
  815. type Iterator_Record;
  816. type Iterator is access Iterator_Record;
  817.  
  818. type Iterator_Record is
  819.     record
  820.     State: Iter_State;
  821.     Parent: Iterator;
  822.     subtree: Node_Ptr;
  823.     end record;
  824.  
  825.  
  826. end binary_trees_pkg;
  827. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  828. --BINTREE.BDY
  829. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  830. with unchecked_deallocation;
  831.  
  832. Package body Binary_Trees_Pkg is
  833. --| Efficient implementation of binary trees.
  834.  
  835.  
  836. ----------------------------------------------------------------------------
  837.             -- Local Operations --
  838. ----------------------------------------------------------------------------
  839.  
  840. procedure Free_Node is 
  841.     new unchecked_deallocation(Node, Node_Ptr);
  842.  
  843. procedure Free_Tree is 
  844.     new unchecked_deallocation(Tree_Header, Tree);
  845.  
  846. procedure Free_Iterator is 
  847.     new unchecked_deallocation(Iterator_Record, Iterator);
  848.  
  849. ----------------------------------------------------------------------------
  850.             -- Visible Operations --
  851. ----------------------------------------------------------------------------
  852.  
  853. Function Create        --| Return an empty tree.
  854.     return Tree is
  855.  
  856. begin
  857.     return new Tree_Header'(0, Null);
  858.  
  859. end Create;
  860.  
  861. ----------------------------------------------------------------------------
  862.  
  863. Procedure Insert_Node(
  864.     V: Value_Type;
  865.     N: in out Node_Ptr;
  866.     Found: out boolean;
  867.     Duplicate: out Value_Type
  868.     ) 
  869. is
  870.     D: integer;
  871.  
  872. begin
  873.     Found := False;
  874.     if N = null then
  875.        N := new Node'(V, Null, Null);
  876.     else
  877.       D := Difference(V, N.Value);
  878.       if D < 0 then
  879.         Insert_Node(V, N.Less, Found, Duplicate);
  880.       elsif D > 0 then
  881.         Insert_Node(V, N.More, Found, Duplicate);
  882.       else
  883.     Found := True;
  884.     Duplicate := N.Value;
  885.       end if;
  886.     end if;
  887. end Insert_Node;
  888.  
  889. Procedure Replace_Node(
  890.     V: Value_Type;
  891.     N: in out Node_Ptr;
  892.     Found: out boolean;
  893.     Duplicate: out Value_Type
  894.     ) 
  895. is
  896.     D: integer;
  897.  
  898. begin
  899.     Found := False;
  900.     if N = null then
  901.        N := new Node'(V, Null, Null);
  902.     else
  903.       D := Difference(V, N.Value);
  904.       if D < 0 then
  905.         Replace_Node(V, N.Less, Found, Duplicate);
  906.       elsif D > 0 then
  907.         Replace_Node(V, N.More, Found, Duplicate);
  908.       else
  909.     Found := True;
  910.     Duplicate := N.Value;
  911.     N.Value := V;
  912.       end if;
  913.     end if;
  914. end Replace_Node;
  915.  
  916.  
  917. Procedure Insert(    --| Insert a value into a tree.
  918.     V: Value_Type;    --| Value to be inserted
  919.     T: Tree        --| Tree to contain the new value
  920.     ) --| Raises: Duplicate_Value, Invalid_Tree.
  921. is
  922.     Found: boolean;
  923.     Duplicate: Value_Type;
  924.  
  925. begin
  926.     if T = null then
  927.     raise Invalid_Tree;
  928.     end if;
  929.     Insert_Node(V, T.Root, Found, Duplicate);
  930.     if Found then
  931.         raise Duplicate_Value;
  932.     end if;
  933.     T.Count := T.Count + 1;
  934. end Insert;
  935.  
  936.  
  937. Procedure Insert_if_not_Found(
  938. --| Insert a value into a tree, provided a duplicate value is not already there
  939.     V: Value_Type;    --| Value to be inserted
  940.     T: Tree;        --| Tree to contain the new value
  941.     Found: out boolean;
  942.     Duplicate: out Value_Type
  943.     ) --| Raises: Invalid_Tree.
  944. is
  945.     was_Found: boolean;
  946.  
  947. begin
  948.     if T = null then
  949.     raise Invalid_Tree;
  950.     end if;
  951.     Insert_Node(V, T.Root, was_Found, Duplicate);
  952.     Found := was_Found;
  953.     if not was_Found then
  954.     T.Count := T.Count + 1;
  955.     end if;
  956.  
  957. end Insert_if_Not_Found;
  958.  
  959. procedure Replace_if_Found(
  960. --| Replace a value if label exists, otherwise insert it.
  961.     V: Value_Type;    --| Value to be inserted
  962.     T: Tree;        --| Tree to contain the new value
  963.     Found: out boolean;    --| Becomes True iff L already in tree
  964.     Old_Value: out Value_Type    --| the duplicate value, if there is one
  965.     ) --| Raises: Invalid_Tree.
  966.  
  967. is
  968.     was_Found: boolean;
  969.     Duplicate: Value_Type;
  970.  
  971. begin
  972.     if T = null then
  973.     raise Invalid_Tree;
  974.     end if;
  975.     Replace_Node(V, T.Root, was_Found, Duplicate);
  976.     Found := was_Found;
  977.     if was_Found then
  978.     Old_Value := Duplicate;
  979.     else
  980.     T.Count := T.Count + 1;
  981.     end if;
  982.  
  983. end Replace_if_Found;
  984.  
  985. ----------------------------------------------------------------------------
  986.  
  987. procedure Destroy_Nodes(
  988.     N: in out Node_Ptr
  989.     ) is
  990. begin
  991.     if N /= null then
  992.         Destroy_Nodes(N.Less);
  993.         Destroy_Nodes(N.More);
  994.         Free_Node(N);
  995.     end if;
  996. end Destroy_Nodes;
  997.  
  998. procedure Destroy(    --| Free space allocated to a tree.
  999.     T: in out Tree    --| The tree to be reclaimed.
  1000.     ) is
  1001.  
  1002. begin
  1003.     if T /= Null then
  1004.       Destroy_Nodes(T.Root);
  1005.       Free_Tree(T);
  1006.     end if;
  1007.  
  1008. end Destroy;
  1009.  
  1010. ----------------------------------------------------------------------------
  1011.  
  1012. procedure Destroy_Deep(    --| Free all space allocated to a tree.
  1013.     T: in out Tree    --| The tree to be reclaimed.
  1014.     )
  1015. is
  1016.     procedure Destroy_Nodes(
  1017.     N: in out node_Ptr
  1018.     ) is
  1019.     begin
  1020.     if N /= null then
  1021.         Free_Value(N.Value);
  1022.             Destroy_Nodes(N.Less);
  1023.         Destroy_Nodes(N.More);
  1024.         Free_Node(N);
  1025.     end if;
  1026.     end Destroy_Nodes;
  1027.  
  1028. begin
  1029.     if T /= Null then
  1030.       Destroy_Nodes(T.Root);
  1031.       Free_Tree(T);
  1032.     end if;
  1033.  
  1034. end Destroy_Deep;
  1035.  
  1036. ----------------------------------------------------------------------------
  1037.  
  1038. Function Balanced_Tree(    
  1039.     Count: natural
  1040.     ) return Tree
  1041.  
  1042. is
  1043.     new_Tree: Tree := Create;
  1044.  
  1045.     procedure subtree(Count: natural; N: in out Node_Ptr)
  1046.     is
  1047.     new_Node: Node_Ptr;
  1048.  
  1049.     begin
  1050.     if Count = 1 then
  1051.       new_Node := new Node'(next_Value, Null, Null);
  1052.     elsif Count > 1 then
  1053.       new_node := new Node;
  1054.       subtree(Count/2, new_Node.Less);        -- Half are less
  1055.       new_Node.Value := next_Value;            -- Median value
  1056.       subtree(Count - Count/2 - 1, new_Node.More);    -- Other half are more
  1057.     end if;
  1058.     N := new_Node;
  1059.     end subtree;
  1060.  
  1061. begin
  1062.     new_Tree.Count := Count;
  1063.     subtree(Count, new_Tree.Root);
  1064.     return new_Tree;
  1065.  
  1066. end Balanced_Tree;
  1067.  
  1068. ----------------------------------------------------------------------------
  1069.  
  1070. Function Copy_Tree(
  1071.     T: Tree
  1072.     ) return Tree
  1073. is
  1074.     I: Iterator;
  1075.  
  1076.     function next_Val return Value_type 
  1077.     is
  1078.     V: Value_Type;
  1079.  
  1080.     begin
  1081.     Next(I, V);
  1082.     return copy_Value(V);
  1083.     end next_Val;
  1084.  
  1085.     function copy_Balanced is new Balanced_Tree(next_Val);
  1086.  
  1087. begin
  1088.     I := Make_Iter(T);    -- Will raise Invalid_Tree if necessary
  1089.     return copy_Balanced(Size(T));
  1090.  
  1091. end Copy_Tree;
  1092.  
  1093. ----------------------------------------------------------------------------
  1094.  
  1095. Function Is_Empty(    --| Check for an empty tree.
  1096.     T: Tree
  1097.     ) return boolean is
  1098. begin
  1099.     return T = Null or else T.Root = Null;
  1100.  
  1101. end Is_Empty;
  1102.  
  1103. ----------------------------------------------------------------------------
  1104.  
  1105. procedure Find_Node(
  1106.     V: Value_Type;        --| Value to be located
  1107.     N: Node_Ptr;        --| subtree to be searched
  1108.     Match: out Value_Type;    --| Matching value found in the tree
  1109.     Found: out Boolean        --| TRUE iff a match was found
  1110.     )
  1111. is
  1112.     D: integer;
  1113.  
  1114. begin
  1115.     if N = null then
  1116.         Found := False;
  1117.     return;
  1118.     end if;
  1119.     D := Difference(V, N.Value);
  1120.     if D < 0 then
  1121.         Find_Node(V, N.Less, Match, Found);
  1122.     elsif D > 0 then
  1123.         Find_Node(V, N.More, Match, Found);
  1124.     else
  1125.         Match := N.Value;
  1126.     Found := TRUE;
  1127.     end if;
  1128. end Find_Node;
  1129.  
  1130. Function Find(        --| Search a tree for a value.
  1131.     V: Value_Type;    --| Value to be located
  1132.     T: Tree        --| Tree to be searched
  1133.     ) return Value_Type --| Raises: Not_Found.
  1134. is
  1135.     Found: Boolean;
  1136.     Match: Value_Type;
  1137.  
  1138. begin
  1139.     if T = Null then
  1140.     raise Invalid_Tree;
  1141.     end if;
  1142.     Find_Node(V, T.Root, Match, Found);
  1143.     if Found then
  1144.     return Match;
  1145.     else
  1146.     raise Not_Found;
  1147.     end if;
  1148. end Find;
  1149.  
  1150. Procedure Find(            --| Search a tree for a value.
  1151.     V: Value_Type;        --| Value to be located
  1152.     T: Tree;            --| Tree to be searched
  1153.     Found: out Boolean;        --| TRUE iff a match was found
  1154.     Match: out Value_Type    --| Matching value found in the tree
  1155.     ) is
  1156. begin
  1157.     if T = Null then
  1158.     raise Invalid_Tree;
  1159.     end if;
  1160.     Find_Node(V, T.Root, Match, Found);
  1161. end Find;
  1162.  
  1163. ----------------------------------------------------------------------------
  1164.  
  1165. function is_Found(    --| Check a tree for a value.
  1166.     V: Value_Type;    --| Value to be located
  1167.     T: Tree        --| Tree to be searched
  1168.     ) return Boolean
  1169. is
  1170.     Found: Boolean;
  1171.     Match: Value_Type;
  1172.  
  1173. begin
  1174.     if T = Null then
  1175.     raise Invalid_Tree;
  1176.     end if;
  1177.     Find_Node(V, T.Root, Match, Found);
  1178.     return Found;
  1179.  
  1180. end is_Found;
  1181.  
  1182. ----------------------------------------------------------------------------
  1183.  
  1184. function Size(        --| Return the count of values in T.
  1185.     T: Tree        --| a tree
  1186.     ) return natural is
  1187.  
  1188. begin
  1189.     if T = Null then
  1190.     Return 0;
  1191.     else
  1192.         Return T.Count;
  1193.     end if;
  1194.  
  1195. end Size;
  1196.  
  1197. ----------------------------------------------------------------------------
  1198.  
  1199. procedure Visit(
  1200.     T: Tree;
  1201.     Order: Scan_Kind
  1202.     ) is
  1203.  
  1204.     procedure visit_Inorder(N: Node_Ptr) is
  1205.     begin
  1206.     if N.Less /= null then
  1207.       visit_Inorder(N.Less);
  1208.     end if;
  1209.     Process(N.Value);
  1210.     if N.More /= null then
  1211.       visit_Inorder(N.More);
  1212.     end if;
  1213.     end visit_Inorder;
  1214.  
  1215.     procedure visit_preorder(N: Node_Ptr) is
  1216.     begin
  1217.     Process(N.Value);
  1218.     if N.Less /= null then
  1219.       visit_preorder(N.Less);
  1220.     end if;
  1221.     if N.More /= null then
  1222.       visit_preorder(N.More);
  1223.     end if;
  1224.     end visit_preorder;
  1225.  
  1226.     procedure visit_postorder(N: Node_Ptr) is
  1227.     begin
  1228.     if N.Less /= null then
  1229.       visit_postorder(N.Less);
  1230.     end if;
  1231.     if N.More /= null then
  1232.       visit_postorder(N.More);
  1233.     end if;
  1234.     Process(N.Value);
  1235.     end visit_postorder;
  1236.  
  1237. begin
  1238.     if T = Null then
  1239.     raise Invalid_Tree;
  1240.     else
  1241.       case Order is
  1242.     when inorder =>
  1243.       Visit_Inorder(T.Root);
  1244.     when preorder =>
  1245.       Visit_preorder(T.Root);
  1246.     when postorder =>
  1247.       Visit_postorder(T.Root);
  1248.       end case;
  1249.     end if;
  1250. end Visit;
  1251.  
  1252. ----------------------------------------------------------------------------
  1253.  
  1254. function subtree_Iter(    --| Create an iterator over a subtree
  1255.     N: Node_Ptr;
  1256.     P: Iterator
  1257.     ) return Iterator is
  1258.  
  1259. begin
  1260.     if N = Null then
  1261.       return new Iterator_Record'(State => Done, Parent => P, subtree => N);
  1262.     elsif N.Less = Null then
  1263.       return new Iterator_Record'(State => Middle, Parent => P, subtree => N);
  1264.     else
  1265.       return new Iterator_Record'(State => Left, Parent => P, subtree => N);
  1266.     end if;
  1267.  
  1268. end subtree_Iter;
  1269.  
  1270. function Make_Iter(    --| Create an iterator over a tree
  1271.     T: Tree
  1272.     ) return Iterator is
  1273.  
  1274. begin
  1275.     if T = Null then
  1276.     raise Invalid_Tree;
  1277.     end if;
  1278.     return subtree_Iter(T.Root, Null);
  1279.  
  1280. end Make_Iter;
  1281.  
  1282. ----------------------------------------------------------------------------
  1283.  
  1284. function More(        --| Test for exhausted iterator
  1285.     I: Iterator        --| The iterator to be tested
  1286.     ) return boolean is
  1287.  
  1288. begin
  1289.     if I = Null then
  1290.     return False;
  1291.     elsif I.Parent = Null then
  1292.     return I.State /= Done and I.subtree /= Null;
  1293.     elsif I.State = Done then
  1294.     return More(I.Parent);
  1295.     else 
  1296.     return True;
  1297.     end if;
  1298.  
  1299. end More;
  1300.  
  1301. ----------------------------------------------------------------------------
  1302.  
  1303. procedure pop_Iterator(
  1304.     I: in out Iterator
  1305.     ) 
  1306. is
  1307.     NI: Iterator;
  1308. begin
  1309.     loop
  1310.       NI := I;
  1311.       I := I.Parent;
  1312.       Free_Iterator(NI);
  1313.       exit when I = Null;
  1314.       exit when I.State /= Done;
  1315.     end loop;
  1316. end pop_Iterator;
  1317.  
  1318. procedure Next(        --| Scan the next value in I
  1319.     I: in out Iterator;    --| an active iterator
  1320.     V: out Value_Type    --| Next value scanned
  1321.     ) --| Raises: No_More.
  1322. is
  1323.     NI: Iterator;
  1324.  
  1325. begin
  1326.     if I = Null or I.State = Done then
  1327.     raise No_More;
  1328.     end if;
  1329.     case I.State is
  1330.       when Left =>    -- Return the leftmost value
  1331.     while I.subtree.Less /= Null loop    -- Find leftmost subtree
  1332.       I.State := Middle;    -- Middle is next at this level
  1333.       I := subtree_Iter(I.subtree.Less, I);
  1334.     end loop;
  1335.     V := I.subtree.Value;
  1336.     if I.subtree.More /= Null then    -- There will be more...
  1337.       I.State := Right;        -- ... coming from the right
  1338.     else                -- Nothing else here
  1339.       pop_Iterator(I);        -- Pop up to parent iterator
  1340.     end if;
  1341.       when Middle =>
  1342.     V := I.subtree.Value;
  1343.     if I.subtree.More /= Null then    -- There will be more...
  1344.       I.State := Right;        -- ... coming from the right
  1345.     else                -- Nothing else here so...
  1346.       pop_Iterator(I);        -- ... Pop up to parent iterator
  1347.     end if;
  1348.       when Right =>    -- Return the value on the right
  1349.     I.State := Done;    -- No more at this level
  1350.     I := subtree_Iter(I.subtree.More, I);
  1351.     Next(I, V);
  1352.       when Done =>
  1353.     pop_Iterator(I);
  1354.     Next(I, V);
  1355.     end case;
  1356.  
  1357. end Next;
  1358.  
  1359. ----------------------------------------------------------------------------
  1360.  
  1361.  
  1362. end binary_trees_pkg;
  1363. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1364. --LBINTREE.SPC
  1365. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1366. with Binary_Trees_Pkg;
  1367.  
  1368. generic
  1369.     type Label_Type is private;    --| Type for labels stored in the tree.
  1370.     type Value_Type is private;    --| Type for values stored in the tree.
  1371.  
  1372.     with function Difference(P, Q: Label_Type) return integer is <>;
  1373.     --| Must return a value > 0 if P > Q, 0 if P = Q, and less than
  1374.     --| zero otherwise, where P and Q are labels.
  1375.  
  1376. package labeled_binary_trees_pkg is
  1377. --| Efficient implementation of labeled binary trees.
  1378.  
  1379. --| OVERVIEW
  1380.  
  1381. --| This package provides labeled binary trees, which are the same as
  1382. --| unlabeled binary trees except that when searching for or inserting
  1383. --| a value into the tree, only the label field is compared.
  1384. --| 
  1385. --| OPERATIONS
  1386. --| 
  1387. --|-The following operations are provided:
  1388. --| 
  1389. --| Insert        Insert a node into a tree
  1390. --| Destroy        Destroy a tree
  1391. --| Destroy_Deep*    Destroy a tree and its contents
  1392. --| Balanced_Tree*    Create a balanced tree from values supplied in order
  1393. --| Copy*        Copy a tree.  The copy is balanced.
  1394. --| 
  1395. --| Queries:
  1396. --|   Is_Empty        Return TRUE iff a tree is empty.
  1397. --|   Find        Search tree for a node
  1398. --|   Is_Found        Return TRUE iff tree contains specified value.
  1399. --|   Size        Return number of nodes in the tree.
  1400. --| 
  1401. --| Iterators:
  1402. --|   Visit*        Apply a procedure to every node in specified order
  1403. --|   Make_Iter        Create an iterator for ordered scan
  1404. --|   More        Test for exhausted iterator
  1405. --|   Next        Bump an iterator to the next element
  1406. --| 
  1407. --| * Indicates generic subprogram
  1408. --| 
  1409. --| USAGE: (See Overview of Binary_Trees_Package)
  1410. --| 
  1411. --| PERFORMANCE: (See Overview of Binary_Trees_Package)
  1412.  
  1413.  
  1414. ----------------------------------------------------------------------------
  1415. -- This should be private (but cannot be)
  1416.  
  1417. type Label_Value_Pair is 
  1418.     record
  1419.     Label: Label_Type;
  1420.     Value: Value_Type;
  1421.     end record;
  1422.  
  1423. function LV_Differ(P, Q: Label_Value_Pair) return integer;
  1424. package LVT is new Binary_Trees_Pkg(Label_Value_Pair, LV_Differ);
  1425.  
  1426. ----------------------------------------------------------------------------
  1427.                 -- Exceptions --
  1428. ----------------------------------------------------------------------------
  1429.  
  1430. Duplicate_Value: exception renames LVT.Duplicate_Value;
  1431. --| Raised on attempt to insert a duplicate label into a tree.
  1432.  
  1433. Not_Found: exception renames LVT.Not_Found;
  1434. --| Raised on attempt to find a label that is not in a tree.
  1435.  
  1436. No_More: exception renames LVT.No_More;
  1437. --| Raised on attempt to bump an iterator that has already scanned the
  1438. --| entire tree.
  1439.  
  1440. Out_Of_Order: exception renames LVT.Out_Of_Order;
  1441. --| Raised if a problem in the ordering of a tree is detected.
  1442.  
  1443. Invalid_Tree: exception renames LVT.Invalid_Tree;
  1444. --| Value is not a tree or was not properly initialized.
  1445.  
  1446. ----------------------------------------------------------------------------
  1447.                 -- Types --
  1448. ----------------------------------------------------------------------------
  1449.  
  1450. subtype Scan_Kind is LVT.Scan_Kind;
  1451.  
  1452. --? function InOrder return LVT.Scan_Kind renames LVT.InOrder;
  1453.  
  1454. InOrder: constant Scan_Kind := LVT.InOrder;
  1455. PreOrder: constant Scan_Kind := LVT.PreOrder;
  1456. PostOrder: constant Scan_Kind := LVT.PostOrder;
  1457.  
  1458. --| is (inorder, preorder, postorder);
  1459. --| Used to specify the order in which values should be scanned from a tree:
  1460. --|-
  1461. --| inorder: Left, Node, Right (nodes visited in increasing order)
  1462. --| preorder: Node, Left, Right (top down)
  1463. --| postorder: Left, Right, Node (bottom up)
  1464.  
  1465. subtype Tree is LVT.Tree;
  1466. subtype Iterator is LVT.Iterator;
  1467.  
  1468. ----------------------------------------------------------------------------
  1469.                 -- Operations --
  1470. ----------------------------------------------------------------------------
  1471.  
  1472. Function Create        --| Return an empty tree.
  1473.     return Tree renames LVT.Create;
  1474.  
  1475. --| Effects: Create and return an empty tree.  Note that this allocates
  1476. --| a small amount of storage which can only be reclaimed through 
  1477. --| a call to Destroy.
  1478.  
  1479. ----------------------------------------------------------------------------
  1480.  
  1481. Procedure Insert(    --| Insert a label/value into a tree.
  1482.     L: Label_Type;    --| Label to be associated with a value
  1483.     V: Value_Type;    --| Value to be inserted
  1484.     T: Tree        --| Tree to contain the new value
  1485.     );
  1486. --| Raises: Duplicate_Value, Invalid_Tree.
  1487.  
  1488. --| Effects: Insert (L, V) into T in the proper place.  If a label equal
  1489. --| to L (according to the Difference function) is already contained
  1490. --| in the tree, the exception Duplicate_Label is raised.
  1491. --| Caution: Since this package does not attempt to balance trees as
  1492. --| values are inserted, it is important to remember that inserting
  1493. --| labels in sorted order will create a degenerate tree, where search
  1494. --| and insertion is proportional to the N instead of to Log N.  If
  1495. --| this pattern is common, use the Balanced_Tree function below.
  1496.  
  1497. ----------------------------------------------------------------------------
  1498.  
  1499. procedure Insert_if_not_Found(
  1500. --| Insert a value into a tree, provided a duplicate value is not already there
  1501.     L: Label_Type;    --| Label to look for
  1502.     V: Value_Type;    --| Value to be inserted
  1503.     T: Tree;        --| Tree to contain the new value
  1504.     Found: out boolean;    --| Becomes True iff L already in tree
  1505.     Duplicate: out Value_Type    --| the duplicate value, if there is one
  1506.     ); --| Raises: Invalid_Tree.
  1507.  
  1508. --| Effects: Insert V into T in the proper place.  If a value equal
  1509. --| to V (according to the Difference function) is already contained
  1510. --| in the tree, Found will be True and Duplicate will be the duplicate
  1511. --| value.  This might be a sequence of values with the same key, and
  1512. --| V can then be added to the sequence.
  1513.  
  1514. ----------------------------------------------------------------------------
  1515.  
  1516. procedure Replace_if_Found(
  1517. --| Replace a value if label exists, otherwise insert it.
  1518.     L: Label_Type;    --| Label to look for
  1519.     V: Value_Type;    --| Value to be inserted
  1520.     T: Tree;        --| Tree to contain the new value
  1521.     Found: out boolean;    --| Becomes True iff L already in tree
  1522.     Old_Value: out Value_Type    --| the duplicate value, if there is one
  1523.     ); --| Raises: Invalid_Tree.
  1524.  
  1525. --| Effects: Search for L in T.  If found, replace the old value with V,
  1526. --| and return Found => True, Old_Value => the old value.  Otherwise,
  1527. --| simply insert the L, V pair into T and return Found => False.
  1528.  
  1529. ----------------------------------------------------------------------------
  1530.  
  1531. procedure Destroy(    --| Free space allocated to a tree.
  1532.     T: in out Tree    --| The tree to be reclaimed.
  1533.     ) renames LVT.Destroy;
  1534.  
  1535. --| Effects: The space allocated to T is reclaimed.  The space occupied by
  1536. --| the values stored in T is not however, recovered.
  1537.  
  1538. ----------------------------------------------------------------------------
  1539.  
  1540. generic
  1541.     with procedure free_Value(V: in out Value_Type) is <>;
  1542.     with procedure free_Label(L: in out Label_Type) is <>;
  1543.  
  1544. procedure Destroy_Deep(    --| Free all space allocated to a tree.
  1545.     T: in out Tree    --| The tree to be reclaimed.
  1546.     );
  1547.  
  1548. --| Effects: The space allocated to T is reclaimed.  The values and
  1549. --| labels stored it T are reclaimed using Free_Label and
  1550. --| Free_Value, and the tree nodes themselves
  1551. --| are then reclaimed (in a single walk of the tree).
  1552.  
  1553. ----------------------------------------------------------------------------
  1554.  
  1555. generic
  1556.     with Procedure Next_Pair(
  1557.     L: in out Label_Type;
  1558.     V: in out Value_Type
  1559.     )
  1560.     is <>;
  1561.  
  1562.     --| Each call to this procedure should return the next (Label, Value)
  1563.     --| pair to be
  1564.     --| inserted into the balanced tree being created.  If necessary,
  1565.     --| this function should check that each value is greater than the
  1566.     --| previous one, and raise Out_of_Order if necessary.  If values
  1567.     --| are not returned in strictly increasing order, the results are
  1568.     --| unpredictable.
  1569.  
  1570. Function Balanced_Tree(    
  1571.     Count: natural
  1572.     ) return Tree;
  1573.  
  1574. --| Effects: Create a balanced tree by calling next_Pair Count times.
  1575. --| Each time Next_Pair is called, it must return a label that compares
  1576. --| greater than the preceeding label.  This function is useful for balancing
  1577. --| an existing tree (next_Pair iterates over the unbalanced tree) or
  1578. --| for creating a balanced tree when reading data from a file which is
  1579. --| already sorted.
  1580.  
  1581. ----------------------------------------------------------------------------
  1582.  
  1583. generic
  1584.     with function Copy_Label(L: Label_Type) return Label_Type is <>;
  1585.     with function Copy_Value(V: Value_Type) return Value_Type is <>;
  1586.     --| This function is called to copy a value from the old tree to the
  1587.     --| new tree.
  1588.  
  1589. Function Copy_Tree(
  1590.     T: Tree
  1591.     ) return Tree; --| Raises Invalid_Tree.
  1592.  
  1593. --| Effects: Create a balanced tree that is a copy of the tree T.
  1594. --| The exception Invalid_Tree is raised if T is not a valid tree.
  1595.  
  1596. ----------------------------------------------------------------------------
  1597.  
  1598. Function Is_Empty(    --| Check for an empty tree.
  1599.     T: Tree
  1600.     ) return boolean renames LVT.Is_Empty;
  1601.  
  1602. --| Effects: Return TRUE iff T is an empty tree or if T was not initialized.
  1603.  
  1604. ----------------------------------------------------------------------------
  1605.  
  1606. Function Find(        --| Search a tree for a value.
  1607.     L: Label_Type;    --| Label to be located
  1608.     T: Tree        --| Tree to be searched
  1609.     ) return Value_Type; --| Raises: Not_Found, Invalid_Tree.
  1610.  
  1611. --| Effects: Search T for a label that matches L.  The corresponding value
  1612. --| is returned.  If no matching label is found, the exception Not_Found
  1613. --| is raised.
  1614.  
  1615.  
  1616. Procedure Find(            --| Search a tree for a value.
  1617.     L: Label_Type;        --| Label to be located
  1618.     T: Tree;            --| Tree to be searched
  1619.     Found: out Boolean;        --| TRUE iff a match was found
  1620.     Match: out Value_Type    --| Matching value found in the tree
  1621.     ); --| Raises: Invalid_Tree;
  1622.  
  1623. --| Effects: Search T for a label that matches L.  On return, if Found is
  1624. --| TRUE then the corresponding value is returned in Match.  Otherwise,
  1625. --| Found is FALSE and Match is undefined.
  1626.  
  1627. ----------------------------------------------------------------------------
  1628.  
  1629. function is_Found(    --| Check a tree for a value.
  1630.     L: Label_Type;    --| Label to be located
  1631.     T: Tree        --| Tree to be searched
  1632.     ) return Boolean; --| Raises: Invalid_Tree;
  1633.  
  1634. --| Effects: Return TRUE iff L is found in T.
  1635.  
  1636. ----------------------------------------------------------------------------
  1637.  
  1638. function Size(        --| Return the count of values in T.
  1639.     T: Tree        --| a tree
  1640.     ) return natural renames LVT.Size; 
  1641.  
  1642. --| Effects: Return the number of values stored in T.
  1643.  
  1644. ----------------------------------------------------------------------------
  1645.  
  1646. generic
  1647.     with procedure Process(L: Label_Type; V: Value_Type) is <>;
  1648.  
  1649. procedure Visit(
  1650.     T: Tree;
  1651.     Order: Scan_Kind
  1652.     ); --| Raises: Invalid_Tree;
  1653.  
  1654. --| Effects: Invoke Process(V) for each value V in T.  The nodes are visited
  1655. --| in the order specified by Order.  Although more limited than using
  1656. --| an iterator, this function is also much faster.
  1657.  
  1658. ----------------------------------------------------------------------------
  1659.  
  1660. function Make_Iter(    --| Create an iterator over a tree
  1661.     T: Tree
  1662.     ) return Iterator renames LVT.Make_Iter; --| Raises: Invalid_Tree;
  1663.  
  1664. ----------------------------------------------------------------------------
  1665.  
  1666. function More(        --| Test for exhausted iterator
  1667.     I: Iterator        --| The iterator to be tested
  1668.     ) return boolean renames LVT.More;
  1669.  
  1670. --| Effects: Return TRUE iff unscanned nodes remain in the tree being
  1671. --| scanned by I.
  1672.  
  1673.  
  1674. ----------------------------------------------------------------------------
  1675.  
  1676. procedure Next(        --| Scan the next value in I
  1677.     I: in out Iterator;    --| an active iterator
  1678.     L: out Label_Type;    --| Next label scanned
  1679.     V: out Value_Type    --| Next value scanned
  1680.     ); --| Raises: No_More.
  1681.  
  1682. --| Effects: Return the next value in the tree being scanned by I.
  1683. --| The exception No_More is raised if there are no more values to scan.
  1684.  
  1685. ----------------------------------------------------------------------------
  1686.  
  1687. end labeled_binary_trees_pkg;
  1688. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1689. --LBINTREE.BDY
  1690. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1691. package body labeled_binary_trees_pkg is
  1692. --| Efficient implementation of labeled binary trees.
  1693.  
  1694. --| OVERVIEW
  1695.  
  1696. --| Implemented using Binary_Trees_Pkg.
  1697.  
  1698. ----------------------------------------------------------------------------
  1699.                 -- Implementation --
  1700. ----------------------------------------------------------------------------
  1701. -- For the pseudo-private part
  1702.  
  1703. function LV_Differ(P, Q: Label_Value_Pair) return integer is
  1704. begin
  1705.     return Difference(P.Label, Q.Label);
  1706.  
  1707. end LV_Differ;
  1708.  
  1709. ----------------------------------------------------------------------------
  1710.  
  1711. Procedure Insert(    --| Insert a label/value into a tree.
  1712.     L: Label_Type;    --| Label to be associated with a value
  1713.     V: Value_Type;    --| Value to be inserted
  1714.     T: Tree        --| Tree to contain the new value
  1715.     ) is
  1716.  
  1717. begin
  1718.     LVT.Insert(Label_Value_Pair'(L, V), T);
  1719.  
  1720. end Insert;
  1721.  
  1722. ----------------------------------------------------------------------------
  1723.  
  1724. Procedure Insert_if_not_Found(
  1725. --| Insert a value into a tree, provided a duplicate value is not already there
  1726.     L: Label_Type;    --| Label to look for
  1727.     V: Value_Type;    --| Value to be inserted
  1728.     T: Tree;        --| Tree to contain the new value
  1729.     Found: out boolean;
  1730.     Duplicate: out Value_Type
  1731.     ) --| Raises: Invalid_Tree.
  1732. is
  1733.     was_Found: boolean;
  1734.     Match: Label_Value_Pair;
  1735.  
  1736. begin
  1737.     LVT.Insert_If_Not_Found(Label_Value_Pair'(L, V), T, was_Found, Match);
  1738.     Found := was_Found;
  1739.     if was_Found then
  1740.     Duplicate := Match.Value;
  1741.     end if;
  1742.  
  1743. end Insert_if_Not_Found;
  1744.  
  1745. ----------------------------------------------------------------------------
  1746.  
  1747. procedure Replace_if_Found(
  1748. --| Replace a value if label exists, otherwise insert it.
  1749.     L: Label_Type;    --| Label to look for
  1750.     V: Value_Type;    --| Value to be inserted
  1751.     T: Tree;        --| Tree to contain the new value
  1752.     Found: out boolean;    --| Becomes True iff L already in tree
  1753.     Old_Value: out Value_Type    --| the duplicate value, if there is one
  1754.     ) --| Raises: Invalid_Tree.
  1755. is
  1756.     was_Found: boolean;
  1757.     Match: Label_Value_Pair;
  1758.  
  1759. begin
  1760.     LVT.Replace_if_Found(Label_Value_Pair'(L, V), T, was_Found, Match);
  1761.     Found := was_Found;
  1762.     if was_Found then
  1763.     Old_Value := Match.Value;
  1764.     end if;
  1765.  
  1766. end Replace_if_Found;
  1767.  
  1768. ----------------------------------------------------------------------------
  1769.  
  1770. procedure Destroy_Deep(    --| Free all space allocated to a tree.
  1771.     T: in out Tree    --| The tree to be reclaimed.
  1772.     ) is
  1773.  
  1774.     procedure Destroy_Pair(P: in out Label_Value_Pair) is
  1775.     begin
  1776.     free_Value(P.Value);
  1777.     free_Label(P.Label);
  1778.  
  1779.     end Destroy_Pair;
  1780.  
  1781.     procedure LV_Destroy_Deep is new LVT.Destroy_Deep(Destroy_Pair);
  1782.  
  1783. begin
  1784.     LV_Destroy_Deep(T);
  1785.  
  1786. end Destroy_Deep;
  1787.  
  1788. ----------------------------------------------------------------------------
  1789.  
  1790. function Balanced_Tree(    
  1791.     Count: natural
  1792.     ) return Tree
  1793. is
  1794.     function Next return Label_Value_Pair is
  1795.     L: Label_Type;
  1796.     V: Value_Type;
  1797.     begin
  1798.     Next_Pair(L, V);    -- this is provided with instantiation
  1799.     return Label_Value_Pair'(L, V);
  1800.  
  1801.     end Next;
  1802.  
  1803.     function LV_Balanced_Tree is new LVT.Balanced_Tree(Next);
  1804.  
  1805. begin
  1806.     return LV_Balanced_Tree(Count);
  1807.  
  1808. end Balanced_Tree;
  1809.  
  1810. ----------------------------------------------------------------------------
  1811.  
  1812. function Copy_Tree(
  1813.     T: Tree
  1814.     ) return Tree
  1815. is
  1816.     function Copy_Pair(P: Label_Value_Pair) return Label_Value_Pair is
  1817.     begin
  1818.     return Label_Value_Pair'(copy_Label(P.Label), copy_Value(P.Value));
  1819.  
  1820.     end Copy_Pair;
  1821.  
  1822.     function LV_Copy_Tree is new LVT.Copy_Tree(Copy_Pair);
  1823.  
  1824. begin
  1825.     return LV_Copy_Tree(T);
  1826.  
  1827. end Copy_Tree;
  1828.  
  1829. ----------------------------------------------------------------------------
  1830.  
  1831. Function Find(        --| Search a tree for a value.
  1832.     L: Label_Type;    --| Label to be located
  1833.     T: Tree        --| Tree to be searched
  1834.     ) return Value_Type --| Raises: Not_Found, Invalid_Tree.
  1835. is
  1836.     P: Label_Value_Pair;
  1837.  
  1838. begin
  1839.     P.Label := L;
  1840.     P := LVT.Find(P, T);
  1841.     return P.Value;
  1842.  
  1843. end Find;
  1844.  
  1845.  
  1846. Procedure Find(            --| Search a tree for a value.
  1847.     L: Label_Type;        --| Label to be located
  1848.     T: Tree;            --| Tree to be searched
  1849.     Found: out Boolean;        --| TRUE iff a match was found
  1850.     Match: out Value_Type    --| Matching value found in the tree
  1851.     ) --| Raises: Invalid_Tree;
  1852.  
  1853. is
  1854.     P: Label_Value_Pair;
  1855.     was_Found: boolean;
  1856.  
  1857. begin
  1858.     P.Label := L;
  1859.     LVT.Find(P, T, was_Found, P);
  1860.     Found := was_Found;
  1861.     if was_Found then
  1862.       Match := P.Value;
  1863.     end if;
  1864.  
  1865. end Find;
  1866.  
  1867. ----------------------------------------------------------------------------
  1868.  
  1869. function is_Found(    --| Check a tree for a value.
  1870.     L: Label_Type;    --| Label to be located
  1871.     T: Tree        --| Tree to be searched
  1872.     ) return Boolean    --| Raises: Invalid_Tree;
  1873. is
  1874.     P: Label_Value_Pair;
  1875.     Found: Boolean;
  1876.  
  1877. begin
  1878.     P.Label := L;
  1879.     LVT.Find(P, T, Found, P);
  1880.     return Found;
  1881.  
  1882. end is_Found;
  1883.  
  1884.  
  1885. --| Effects: Return TRUE iff L is found in T.
  1886.  
  1887. ----------------------------------------------------------------------------
  1888.  
  1889. procedure Visit(
  1890.     T: Tree;
  1891.     Order: Scan_Kind
  1892.     )
  1893. is
  1894.     procedure Process_Pair(P: Label_Value_Pair) is
  1895.     begin
  1896.     Process(P.Label, P.Value);
  1897.  
  1898.     end Process_Pair;
  1899.  
  1900.     procedure LV_Visit is new LVT.Visit(Process_Pair);
  1901.  
  1902. begin
  1903.     LV_Visit(T, Order);
  1904.  
  1905. end Visit;
  1906.  
  1907.  
  1908. --| Effects: Invoke Process(V) for each value V in T.  The nodes are visited
  1909. --| in the order specified by Order.  Although more limited than using
  1910. --| an iterator, this function is also much faster.
  1911.  
  1912. ----------------------------------------------------------------------------
  1913.  
  1914. procedure Next(        --| Scan the next value in I
  1915.     I: in out Iterator;    --| an active iterator
  1916.     L: out Label_Type;    --| Next label scanned
  1917.     V: out Value_Type    --| Next value scanned
  1918.     )
  1919. is
  1920.     P: Label_Value_Pair;
  1921.  
  1922. begin
  1923.     LVT.Next(I, P);
  1924.     L := P.Label;
  1925.     V := P.Value;
  1926.  
  1927. end Next;
  1928.  
  1929. ----------------------------------------------------------------------------
  1930.  
  1931.  
  1932. end labeled_binary_trees_pkg;
  1933. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1934. --LISTS.SPC
  1935. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1936.  
  1937. generic
  1938.       type ItemType is private;  --| This is the data being manipulated.
  1939.       
  1940.       with function Equal ( X,Y: in ItemType) return boolean is "=";
  1941.                                  --| This allows the user to define
  1942.                                  --| equality on ItemType.  For instance
  1943.                  --| if ItemType is an abstract type
  1944.                  --| then equality is defined in terms of
  1945.                  --| the abstract type.  If this function
  1946.                  --| is not provided equality defaults to
  1947.                  --| =.
  1948. package Lists is
  1949.  
  1950. --| This package provides singly linked lists with elements of type
  1951. --| ItemType, where ItemType is specified by a generic parameter.
  1952.  
  1953. --| Overview
  1954. --| When this package is instantiated, it provides a linked list type for
  1955. --| lists of objects of type ItemType, which can be any desired type.  A
  1956. --| complete set of operations for manipulation, and releasing
  1957. --| those lists is also provided.  For instance, to make lists of strings,
  1958. --| all that is necessary is:
  1959. --|
  1960. --| type StringType is string(1..10);
  1961. --|
  1962. --| package Str_List is new Lists(StringType); use Str_List;
  1963. --| 
  1964. --|    L:List;
  1965. --|    S:StringType;
  1966. --|
  1967. --| Then to add a string S, to the list L, all that is necessary is
  1968. --|
  1969. --|    L := Create;
  1970. --|    Attach(S,L);
  1971. --| 
  1972. --| 
  1973. --| This package provides basic list operations.
  1974. --|
  1975. --| Attach          append an object to an object, an object to a list,
  1976. --|                 or a list to an object, or a list to a list.
  1977.  
  1978. --| Copy            copy a list using := on elements
  1979. --| CopyDeep        copy a list by copying the elements using a copy
  1980. --|                 operation provided by the user
  1981. --| Create          Creates an empty list
  1982. --| DeleteHead      removes the head of a list
  1983. --| DeleteItem      delete the first occurrence of an element from a list
  1984. --| DeleteItems     delete all occurrences of an element from a list
  1985. --| Destroy         remove a list
  1986. --| DestroyDeep     destroy a list as well as the elements in that list
  1987. --| Equal           are two lists equal
  1988. --| FirstValue      get the information from the first element of a list
  1989. --| Forward         advances an iterator
  1990. --| IsInList        determines whether a given element is in a given list
  1991. --| IsEmpty         returns true if the list is empty
  1992. --| LastValue       return the last value of a list
  1993. --| Length          Returns the length of a list 
  1994. --| MakeList        this takes a single element and returns a list
  1995. --| MakeListIter    prepares for an iteration over a list
  1996. --| More            are there any more items in the list
  1997. --| Next            get the next item in a list
  1998. --| ReplaceHead     replace the information at the head of the list
  1999. --| ReplaceTail     replace the tail of a list with a new list
  2000. --| Tail            get the tail of a list
  2001. --| CellValue       this takes an iterator and returns the value of the element
  2002. --|                 whose position the iterator holds
  2003. --|   
  2004.  
  2005. --| N/A: Effects, Requires, Modifies, and Raises.
  2006.  
  2007. --| Notes
  2008. --| Programmer Buddy Altus
  2009.  
  2010. --|                           Types
  2011. --|                           -----
  2012.  
  2013.           type List       is private;
  2014.           type ListIter   is private;
  2015.  
  2016.  
  2017. --|                           Exceptions
  2018. --|                           ----------
  2019.  
  2020.     CircularList     :exception;     --| Raised if an attemp is made to
  2021.                                      --| create a circular list.  This
  2022.                                      --| results when a list is attempted
  2023.                                      --| to be attached to itself.
  2024.      
  2025.     EmptyList        :exception;     --| Raised if an attemp is made to
  2026.                                      --| manipulate an empty list.
  2027.                      
  2028.     ItemNotPresent   :exception;     --| Raised if an attempt is made to
  2029.                                      --| remove an element from a list in
  2030.                                      --| which it does not exist.
  2031.                      
  2032.     NoMore           :exception;     --| Raised if an attemp is made to
  2033.                                      --| get the next element from a list
  2034.                      --| after iteration is complete.
  2035.                      
  2036.  
  2037.  
  2038. --|                           Operations
  2039. --|                           ---------- 
  2040.  
  2041. ----------------------------------------------------------------------------
  2042.  
  2043. procedure Attach(                  --| appends List2 to List1
  2044.           List1:     in out List;  --| The list being appended to.
  2045.           List2:     in     List   --| The list being appended.
  2046. );
  2047.  
  2048. --| Raises
  2049. --| CircularList
  2050.  
  2051. --| Effects
  2052. --| Appends List1 to List2.  This makes the next field of the last element
  2053. --| of List1 refer to List2.  This can possibly change the value of List1
  2054. --| if List1 is an empty list.  This causes sharing of lists.  Thus if
  2055. --| user Destroys List1 then List2 will be a dangling reference.
  2056. --| This procedure raises CircularList if List1 equals List2.  If it is 
  2057. --| necessary to Attach a list to itself first make a copy of the list and 
  2058. --| attach the copy.
  2059.  
  2060. --| Modifies
  2061. --| Changes the next field of the last element in List1 to be List2.
  2062.  
  2063. -------------------------------------------------------------------------------
  2064.  
  2065. function Attach(                 --| Creates a new list containing the two
  2066.                                  --| Elements.
  2067.          Element1: in ItemType;  --| This will be first element in list.
  2068.          Element2: in ItemType   --| This will be second element in list.
  2069. ) return List;
  2070.  
  2071. --| Effects
  2072. --| This creates a list containing the two elements in the order
  2073. --| specified.
  2074.  
  2075. -------------------------------------------------------------------------------
  2076. procedure Attach(                   --| List L is appended with Element.
  2077.          L:       in out List;      --| List being appended to.
  2078.          Element: in     ItemType   --| This will be last element in l    ist.
  2079. );
  2080.  
  2081. --| Effects
  2082. --| Appends Element onto the end of the list L.  If L is empty then this
  2083. --| may change the value of L.
  2084. --|
  2085. --| Modifies
  2086. --| This appends List L with Element by changing the next field in List.
  2087.  
  2088. --------------------------------------------------------------------------------
  2089. procedure Attach(                   --| Makes Element first item in list L.
  2090.          Element: in      ItemType; --| This will be the first element in list.
  2091.          L:       in  out List      --| The List which Element is being
  2092.                                     --| prepended to.
  2093. );
  2094.  
  2095. --| Effects
  2096. --| This prepends list L with Element.
  2097. --|
  2098. --| Modifies
  2099. --| This modifies the list L.
  2100.  
  2101. --------------------------------------------------------------------------
  2102.  
  2103. function Attach (                      --| attaches two lists
  2104.          List1: in     List;           --| first list
  2105.          List2: in     List            --| second list
  2106. ) return List;
  2107.  
  2108. --| Raises
  2109. --| CircularList
  2110.  
  2111. --| Effects
  2112. --| This returns a list which is List1 attached to List2.  If it is desired
  2113. --| to make List1 be the new attached list the following ada code should be
  2114. --| used.
  2115. --|  
  2116. --| List1 := Attach (List1, List2);
  2117. --| This procedure raises CircularList if List1 equals List2.  If it is 
  2118. --| necessary to Attach a list to itself first make a copy of the list and 
  2119. --| attach the copy.
  2120.  
  2121. -------------------------------------------------------------------------
  2122.  
  2123. function Attach (                   --| prepends an element onto a list
  2124.          Element: in    ItemType;   --| element being prepended to list
  2125.          L:       in    List        --| List which element is being added
  2126.                                     --| to
  2127. ) return List;
  2128.  
  2129. --| Effects
  2130. --| Returns a new list which is headed by Element and followed by L.
  2131.  
  2132. ------------------------------------------------------------------------
  2133.  
  2134. function Attach (                  --| Adds an element to the end of a list
  2135.          L: in          List;      --| The list which element is being added to.
  2136.          Element: in    ItemType   --| The element being added to the end of
  2137.                                    --| the list.
  2138. ) return List;
  2139.  
  2140. --| Effects
  2141. --| Returns a new list which is L followed by Element.
  2142.  
  2143. --------------------------------------------------------------------------
  2144.  
  2145. function Copy(          --| returns a copy of list1 
  2146.        L: in List       --| list being copied
  2147. ) return List;
  2148.  
  2149. --| Effects
  2150. --| Returns a copy of L.
  2151.  
  2152. --------------------------------------------------------------------------
  2153.  
  2154. generic
  2155.         with function Copy(I: in     ItemType) return ItemType;
  2156.     
  2157.  
  2158. function CopyDeep(      --| returns a copy of list using a user supplied
  2159.                         --| copy function.  This is helpful if the type
  2160.             --| of a list is an abstract data type.
  2161.          L: in     List --| List being copied.
  2162. ) return List;
  2163.   
  2164. --| Effects
  2165. --| This produces a new list whose elements have been duplicated using
  2166. --| the Copy function provided by the user.
  2167.  
  2168. ------------------------------------------------------------------------------
  2169.  
  2170. function Create           --| Returns an empty List
  2171.  
  2172. return List;
  2173.  
  2174. ------------------------------------------------------------------------------
  2175.  
  2176. procedure DeleteHead(            --| Remove the head element from a list.
  2177.           L: in out List         --| The list whose head is being removed.
  2178. ); 
  2179.  
  2180. --| RAISES
  2181. --| EmptyList
  2182. --|
  2183. --| EFFECTS
  2184. --| This will return the space occupied by the first element in the list
  2185. --| to the heap.  If sharing exists between lists this procedure
  2186. --| could leave a dangling reference.  If L is empty EmptyList will be
  2187. --| raised.
  2188.  
  2189. ------------------------------------------------------------------------------
  2190.  
  2191. procedure DeleteItem(           --| remove the first occurrence of Element
  2192.                                 --| from L
  2193.       L:       in out List;     --| list element is being  removed from
  2194.       Element: in     ItemType  --| element being removed
  2195. );
  2196.  
  2197. --| EFFECTS
  2198. --| Removes the first element of the list equal to Element.  If there is
  2199. --| not an element equal to Element than ItemNotPresent is raised.
  2200.  
  2201. --| MODIFIES
  2202. --| This operation is destructive, it returns the storage occupied by
  2203. --| the elements being deleted.
  2204.  
  2205. ----------------------------------------------------------------------------
  2206.  
  2207. function DeleteItem(            --| remove the first occurrence of Element
  2208.                                 --| from L
  2209.       L:       in     List;     --| list element is being  removed from
  2210.       Element: in     ItemType  --| element being removed
  2211. ) return List;
  2212.  
  2213. --| EFFECTS
  2214. --| This returns the List L with the first occurrence of Element removed.
  2215.  
  2216. ------------------------------------------------------------------------------
  2217.  
  2218. function DeleteItems (          --| remove all occurrences of Element
  2219.                                 --| from  L.
  2220.       L:       in     List;     --| The List element is being removed from
  2221.       Element: in     ItemType  --| element being removed
  2222. ) return List;
  2223.  
  2224. --| EFFECTS
  2225. --| This function returns a copy of the list L which has all elements which
  2226. --| have value Element removed.
  2227.  
  2228. -------------------------------------------------------------------------------
  2229.  
  2230. procedure DeleteItems (         --| remove all occurrences of Element
  2231.                                 --| from  L.
  2232.       L:       in out List;     --| The List element is being removed from
  2233.       Element: in     ItemType  --| element being removed
  2234. );
  2235.  
  2236. --| EFFECTS
  2237. --| This procedure removes all occurrences of Element from the List L.  This
  2238. --| is a destructive procedure.
  2239.  
  2240. ------------------------------------------------------------------------------
  2241.  
  2242. procedure Destroy (           --| removes the list
  2243.           L: in out List      --| the list being removed
  2244. );
  2245.  
  2246. --| Effects
  2247. --| This returns to the heap all the storage that a list occupies.  Keep in
  2248. --| mind if there exists sharing between lists then this operation can leave
  2249. --| dangling references.
  2250.  
  2251. ------------------------------------------------------------------------------
  2252. generic
  2253.     with procedure Dispose (I :in out ItemType); 
  2254.  
  2255. procedure DestroyDeep (  --| Destroy a list as well as all objects which
  2256.                          --| comprise an element of the list.
  2257.     L :in out List
  2258. );
  2259.  
  2260.  
  2261. --| OVERVIEW
  2262. --| This procedure is used to destroy a list and all the objects contained
  2263. --| in an element of the list.  For example if L is a list of lists
  2264. --| then destroy L does not destroy the lists which are elements of L.
  2265. --| DestroyDeep will now destroy L and all the objects in the elements of L.
  2266. --| The produce Dispose is a procedure which will destroy the objects which
  2267. --| comprise an element of a list.  For example if package  L was  a list
  2268. --| of lists then Dispose for L would be the Destroy of list type package L was
  2269. --| instantiated with.
  2270.  
  2271. --| REQUIRES 
  2272. --| This procedure requires no sharing  between elements of lists. 
  2273. --| For example if L_int is a list of integers and L_of_L_int is a list 
  2274. --| of lists of integers and two elements of L_of_L_int have the same value
  2275. --| then doing a DestroyDeep will cause an access violation to be raised.  
  2276. --| The best way to avoid this is not to have sharing between list elements
  2277. --| or use copy functions when adding to the list of lists.
  2278.  
  2279. ------------------------------------------------------------------------------
  2280.  
  2281. function FirstValue(      --| returns the contents of the first record of the 
  2282.                           --| list
  2283.          L: in List       --| the list whose first element is being
  2284.               --| returned
  2285.  
  2286. ) return ItemType;
  2287.  
  2288. --| Raises
  2289. --| EmptyList
  2290. --|
  2291. --| Effects
  2292. --| This returns the Item in the first position in the list.  If the list
  2293. --| is empty EmptyList is raised.
  2294.  
  2295. -------------------------------------------------------------------------------
  2296.  
  2297. procedure Forward (            --| Advances the iterator.
  2298.           I :in out ListIter   --| The iterator.
  2299. );
  2300.  
  2301. --| OVERVIEW
  2302. --| This procedure can be used in conjunction with Cell to iterate over a list.
  2303. --| This is in addition to Next.  Instead of writing
  2304. --|
  2305. --|  I :ListIter;
  2306. --|  L :List;
  2307. --|  V :List_Element_Type;
  2308. --|  
  2309. --|  I := MakeListIter(L);
  2310. --|  while More(I) loop
  2311. --|      Next (I, V);
  2312. --|      Print (V);
  2313. --|  end loop;
  2314. --| 
  2315. --| One can write
  2316. --| I := MakeListIter(L);
  2317. --| while More (I) loop
  2318. --|     Print (Cell (I));
  2319. --|     Forward (I);
  2320. --| end loop;
  2321.  
  2322. -------------------------------------------------------------------------------
  2323.  
  2324. function IsEmpty(            --| Checks if a list is empty.
  2325.          L: in     List      --| List being checked.
  2326. ) return boolean;
  2327.  
  2328. --------------------------------------------------------------------------
  2329.  
  2330. function IsInList(                 --| Checks if element is an element of
  2331.                                    --| list.
  2332.          L:       in     List;     --| list being scanned for element
  2333.          Element: in     ItemType  --| element being searched for
  2334. ) return boolean;
  2335.  
  2336. --| Effects
  2337. --| Walks down the list L looking for an element whose value is Element.
  2338.  
  2339. ------------------------------------------------------------------------------
  2340.  
  2341. function LastValue(       --| Returns the contents of the last record of
  2342.                           --| the list.
  2343.          L: in List       --| The list whose first element is being
  2344.                           --| returned.
  2345. ) return ItemType;
  2346.  
  2347. --| Raises
  2348. --| EmptyList
  2349. --|
  2350. --| Effects
  2351. --| Returns the last element in a list.  If the list is empty EmptyList is
  2352. --| raised.
  2353.  
  2354.  
  2355. ------------------------------------------------------------------------------
  2356.  
  2357. function Length(         --| count the number of elements on a list
  2358.          L: in List      --| list whose length is being computed
  2359. ) return integer;
  2360.  
  2361. ------------------------------------------------------------------------------
  2362.  
  2363. function MakeList (   --| This takes in an element and returns a List.
  2364.        E :in     ItemType
  2365. ) return List;
  2366.  
  2367. ------------------------------------------------------------------------------
  2368.  
  2369. function MakeListIter(          --| Sets a variable to point to  the head
  2370.                                 --| of the list.  This will be used to
  2371.                                 --| prepare for iteration over a list.
  2372.          L: in List             --| The list being iterated over.
  2373. ) return ListIter;
  2374.  
  2375.                                                                           
  2376. --| This prepares a user for iteration operation over a list.  The iterater is
  2377. --| an operation which returns successive elements of the list on successive
  2378. --| calls to the iterator.  There needs to be a mechanism which marks the
  2379. --| position in the list, so on successive calls to the Next operation the
  2380. --| next item in the list can be returned.  This is the function of the
  2381. --| MakeListIter and the type ListIter.  MakeIter just sets the Iter to the
  2382. --| the beginning  of the list. On subsequent calls to Next the Iter
  2383. --| is updated with each call.
  2384.  
  2385. -----------------------------------------------------------------------------
  2386.  
  2387. function More(           --| Returns true if there are more elements in
  2388.                          --| the and false if there aren't any more
  2389.                          --| the in the list.
  2390.          L: in ListIter  --| List being checked for elements.
  2391. ) return boolean;
  2392.  
  2393. ------------------------------------------------------------------------------
  2394.  
  2395. procedure Next(                 --| This is the iterator operation.  Given
  2396.                                 --| a ListIter in the list it returns the
  2397.                                 --| current item and updates the ListIter.
  2398.                                 --| If ListIter is at the end of the list,
  2399.                                 --| More returns false otherwise it
  2400.                                 --| returns true.
  2401.     Place:    in out ListIter;  --| The Iter which marks the position in
  2402.                                 --| the list.
  2403.     Info:        out ItemType   --| The element being returned.
  2404.  
  2405. );
  2406.  
  2407. --| The iterators subprograms MakeListIter, More, and Next should be used
  2408. --| in the following way:
  2409. --|
  2410. --|         L:        List;
  2411. --|         Place:    ListIter;
  2412. --|         Info:     SomeType;
  2413. --|
  2414. --|     
  2415. --|         Place := MakeListIter(L);
  2416. --|
  2417. --|         while ( More(Place) ) loop
  2418. --|               Next(Place, Info);
  2419. --|               process each element of list L;
  2420. --|               end loop;
  2421.  
  2422.  
  2423. ----------------------------------------------------------------------------
  2424.  
  2425. procedure ReplaceHead(     --| Replace the Item at the head of the list
  2426.                            --| with the parameter Item.
  2427.      L:    in out List;    --| The list being modified.
  2428.      Info: in     ItemType --| The information being entered.
  2429. );
  2430. --| Raises 
  2431. --| EmptyList
  2432.  
  2433. --| Effects
  2434. --| Replaces the information in the first element in the list.  Raises
  2435. --| EmptyList if the list is empty.
  2436.  
  2437. ------------------------------------------------------------------------------
  2438.  
  2439. procedure ReplaceTail(           --| Replace the Tail of a list
  2440.                                  --| with a new list.
  2441.           L:       in out List;  --| List whose Tail is replaced.
  2442.           NewTail: in     List   --| The list which will become the
  2443.                  --| tail of Oldlist.
  2444. );
  2445. --| Raises
  2446. --| EmptyList
  2447. --|
  2448. --| Effects
  2449. --| Replaces the tail of a list with a new list.  If the list whose tail
  2450. --| is being replaced is null EmptyList is raised.
  2451.  
  2452. -------------------------------------------------------------------------------
  2453.  
  2454. function Tail(           --| returns the tail of a list L
  2455.          L: in List      --| the list whose tail is being returned
  2456. ) return List;
  2457.  
  2458. --| Raises
  2459. --| EmptyList
  2460. --|
  2461. --| Effects
  2462. --| Returns a list which is the tail of the list L.  Raises EmptyList if
  2463. --| L is empty.  If L only has one element then Tail returns the Empty
  2464. --| list.
  2465.  
  2466. ------------------------------------------------------------------------------
  2467.  
  2468. function CellValue (    --| Return the value of the element where the iterator is
  2469.             --| positioned.
  2470.          I :in     ListIter
  2471. ) return ItemType;
  2472.  
  2473. --| OVERVIEW
  2474. --| This returns the value of the element at the position of the iterator.
  2475. --| This is used in conjunction with Forward.
  2476.  
  2477. --------------------------------------------------------------------------
  2478.  
  2479.  
  2480. function Equal(            --| compares list1 and list2 for equality
  2481.          List1: in List;   --| first list
  2482.          List2: in List    --| second list
  2483.  )  return boolean;
  2484.  
  2485. --| Effects
  2486. --| Returns true if for all elements of List1 the corresponding element
  2487. --| of List2 has the same value.  This function uses the Equal operation
  2488. --| provided by the user.  If one is not provided then = is used.
  2489.  
  2490. ------------------------------------------------------------------------------
  2491. private
  2492.     type Cell;
  2493.     
  2494.     type List is access Cell;      --| pointer added by this package
  2495.                                    --| in order to make a list
  2496.                    
  2497.     
  2498.     type Cell is                   --| Cell for the lists being created
  2499.          record
  2500.               Info: ItemType;
  2501.               Next: List;
  2502.          end record;
  2503.  
  2504.     
  2505.     type ListIter is new List;     --| This prevents Lists being assigned to
  2506.                                    --| iterators and vice versa
  2507.   
  2508. end Lists;
  2509.  
  2510.  
  2511.  
  2512.  
  2513. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2514. --LISTS.BDY
  2515. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2516.  
  2517. with unchecked_deallocation;
  2518.  
  2519. package body Lists is
  2520.  
  2521.     procedure Free is new unchecked_deallocation (Cell, List);
  2522.  
  2523. --------------------------------------------------------------------------
  2524.  
  2525.    function Last (L: in     List) return List is
  2526.  
  2527.        Place_In_L:        List;
  2528.        Temp_Place_In_L:   List;
  2529.  
  2530.    --|  Link down the list L and return the pointer to the last element
  2531.    --| of L.  If L is null raise the EmptyList exception.
  2532.  
  2533.    begin
  2534.        if L = null then
  2535.            raise EmptyList;
  2536.        else
  2537.  
  2538.            --|  Link down L saving the pointer to the previous element in 
  2539.            --|  Temp_Place_In_L.  After the last iteration Temp_Place_In_L
  2540.            --|  points to the last element in the list.
  2541.  
  2542.            Place_In_L := L;
  2543.            while Place_In_L /= null loop
  2544.                Temp_Place_In_L := Place_In_L;
  2545.                Place_In_L := Place_In_L.Next;
  2546.            end loop;
  2547.            return Temp_Place_In_L;
  2548.        end if;
  2549.     end Last;
  2550.     
  2551.     
  2552. --------------------------------------------------------------------------
  2553.  
  2554.     procedure Attach (List1: in out List;
  2555.                       List2: in     List ) is
  2556.         EndOfList1: List;
  2557.  
  2558.     --| Attach List2 to List1. 
  2559.     --| If List1 is null return List2
  2560.     --| If List1 equals List2 then raise CircularList
  2561.     --| Otherwise get the pointer to the last element of List1 and change
  2562.     --| its Next field to be List2.
  2563.  
  2564.     begin
  2565.         if List1 = null then
  2566.         List1 := List2;
  2567.             return;
  2568.         elsif List1 = List2 then
  2569.             raise CircularList;
  2570.         else     
  2571.             EndOfList1 := Last (List1);
  2572.             EndOfList1.Next := List2;
  2573.         end if;
  2574.     end Attach;
  2575.  
  2576. --------------------------------------------------------------------------
  2577.  
  2578.    procedure Attach (L:       in out List;
  2579.                      Element: in     ItemType ) is
  2580.  
  2581.        NewEnd:    List;
  2582.  
  2583.    --| Create a list containing Element and attach it to the end of L
  2584.  
  2585.    begin
  2586.        NewEnd := new Cell'(Info => Element, Next => null);
  2587.        Attach (L, NewEnd);
  2588.    end;
  2589.  
  2590. --------------------------------------------------------------------------
  2591.  
  2592.    function Attach (Element1: in   ItemType;
  2593.                     Element2: in   ItemType ) return List is
  2594.        NewList: List;
  2595.  
  2596.    --| Create a new list containing the information in Element1 and
  2597.    --| attach Element2 to that list.
  2598.  
  2599.    begin
  2600.        NewList := new Cell'(Info => Element1, Next => null);
  2601.        Attach (NewList, Element2);
  2602.        return NewList;
  2603.    end;
  2604.  
  2605. --------------------------------------------------------------------------
  2606.  
  2607.    procedure Attach (Element: in     ItemType;
  2608.                      L:       in out List      ) is
  2609.  
  2610.    --|  Create a new cell whose information is Element and whose Next
  2611.    --|  field is the list L.  This prepends Element to the List L.
  2612.  
  2613.    begin
  2614.        L := new Cell'(Info => Element, Next => L);
  2615.    end;
  2616.  
  2617. --------------------------------------------------------------------------
  2618.  
  2619.    function Attach ( List1: in    List;
  2620.                      List2: in    List   ) return List is
  2621.  
  2622.    Last_Of_List1: List;
  2623.  
  2624.    begin 
  2625.        if List1 = null then
  2626.            return List2;
  2627.        elsif List1 = List2 then
  2628.            raise CircularList;
  2629.        else 
  2630.            Last_Of_List1 := Last (List1);
  2631.            Last_Of_List1.Next := List2;
  2632.            return List1;   
  2633.        end if;
  2634.    end  Attach;
  2635.  
  2636. -------------------------------------------------------------------------
  2637.  
  2638.    function Attach( L:       in     List;
  2639.                     Element: in     ItemType ) return List is
  2640.  
  2641.    NewEnd: List;
  2642.    Last_Of_L: List;
  2643.  
  2644.    --| Create a list called NewEnd and attach it to the end of L.
  2645.    --| If L is null return NewEnd 
  2646.    --| Otherwise get the last element in L and make its Next field
  2647.    --| NewEnd.
  2648.  
  2649.    begin 
  2650.        NewEnd := new Cell'(Info => Element, Next => null);
  2651.        if L = null then
  2652.            return NewEnd;
  2653.        else 
  2654.            Last_Of_L := Last (L);
  2655.            Last_Of_L.Next := NewEnd;
  2656.            return L;
  2657.        end if;
  2658.    end Attach;
  2659.  
  2660. --------------------------------------------------------------------------
  2661.  
  2662.    function Attach (Element: in     ItemType;
  2663.                     L:       in     List        ) return List is
  2664.  
  2665.    begin
  2666.        return (new Cell'(Info => Element, Next => L));
  2667.    end Attach;
  2668.  
  2669. ---------------------------------------------------------------------------
  2670.  
  2671.  
  2672.    function Copy (L: in     List) return List is
  2673.    
  2674.    --| If L is null return null
  2675.    --| Otherwise recursively copy the list by first copying the information
  2676.    --| at the head of the list and then making the Next field point to 
  2677.    --| a copy of the tail of the list.
  2678.  
  2679.    begin
  2680.        if L = null then
  2681.        return null;
  2682.        else
  2683.        return new Cell'(Info => L.Info, Next => Copy (L.Next));
  2684.        end if;
  2685.    end Copy;
  2686.  
  2687.  
  2688. --------------------------------------------------------------------------
  2689.  
  2690.    function CopyDeep (L: in List) return List is
  2691.        
  2692.    --|  If L is null then return null.
  2693.    --|  Otherwise copy the first element of the list into the head of the
  2694.    --|  new list and copy the tail of the list recursively using CopyDeep.
  2695.  
  2696.    begin
  2697.        if L = null then
  2698.        return null;
  2699.        else
  2700.        return new Cell'( Info => Copy (L.Info), Next => CopyDeep(L.Next));
  2701.        end if;
  2702.    end CopyDeep;
  2703.        
  2704. --------------------------------------------------------------------------
  2705.  
  2706.     function Create return List is
  2707.  
  2708.     --| Return the empty list.
  2709.  
  2710.     begin
  2711.         return null;
  2712.     end Create;
  2713.     
  2714. --------------------------------------------------------------------------
  2715.    procedure DeleteHead (L: in out List) is
  2716.  
  2717.        TempList: List;
  2718.  
  2719.    --| Remove the element of the head of the list and return it to the heap.
  2720.    --| If L is null EmptyList.
  2721.    --| Otherwise save the Next field of the first element, remove the first
  2722.    --| element and then assign to L the Next field of the first element.
  2723.  
  2724.    begin
  2725.        if L = null then
  2726.            raise EmptyList;
  2727.        else
  2728.            TempList := L.Next;
  2729.            Free (L);
  2730.            L := TempList;
  2731.        end if;
  2732.    end DeleteHead;
  2733.  
  2734. --------------------------------------------------------------------------
  2735.  
  2736. function DeleteItem(            --| remove the first occurrence of Element
  2737.                                 --| from L
  2738.       L:       in     List;     --| list element is being  removed from
  2739.       Element: in     ItemType  --| element being removed
  2740. ) return List is
  2741.     I       :List;
  2742.     Result  :List;
  2743.     Found   :boolean := false;
  2744. begin
  2745.     --| ALGORITHM
  2746.     --| Attach all elements of L to Result except the first element in L
  2747.     --| whose value is Element.  If the current element pointed to by I
  2748.     --| is not equal to element or the element being skipped was found
  2749.     --| then attach the current element to Result.
  2750.  
  2751.     I := L;
  2752.     while (I /= null) loop
  2753.         if (not Equal (I.Info, Element)) or (Found) then
  2754.             Attach (Result, I.Info);
  2755.         else
  2756.            Found := true;
  2757.         end if;
  2758.         I := I.Next;
  2759.     end loop;
  2760.     return Result;
  2761. end DeleteItem;
  2762.  
  2763. ------------------------------------------------------------------------------
  2764.  
  2765. function DeleteItems (          --| remove all occurrences of Element
  2766.                                 --| from  L.
  2767.       L:       in     List;     --| The List element is being removed from
  2768.       Element: in     ItemType  --| element being removed
  2769. ) return List is
  2770.     I       :List;
  2771.     Result  :List;
  2772. begin
  2773.     --| ALGORITHM
  2774.     --| Walk over the list L and if the current element does not equal 
  2775.     --| Element then attach it to the list to be returned.
  2776.  
  2777.     I := L;
  2778.     while I /= null loop
  2779.         if not Equal (I.Info, Element) then
  2780.             Attach (Result, I.Info);
  2781.         end if;
  2782.         I := I.Next;
  2783.     end loop;
  2784.     return Result;
  2785. end DeleteItems;
  2786.  
  2787. -------------------------------------------------------------------------------
  2788.  
  2789.    procedure DeleteItem (L:       in out List;
  2790.                          Element: in     ItemType ) is
  2791.  
  2792.        Temp_L  :List;
  2793.  
  2794.    --| Remove the first element in the list with the value Element.
  2795.    --| If the first element of the list is equal to element then
  2796.    --| remove it.  Otherwise, recurse on the tail of the list.
  2797.  
  2798.    begin
  2799.        if Equal(L.Info, Element) then
  2800.            DeleteHead(L);
  2801.        else
  2802.            DeleteItem(L.Next, Element);
  2803.        end if; 
  2804.    end DeleteItem;
  2805.  
  2806. --------------------------------------------------------------------------
  2807.  
  2808.    procedure DeleteItems (L:       in out List;
  2809.                           Element: in     ItemType ) is
  2810.  
  2811.        Place_In_L       :List;     --| Current place in L.
  2812.        Last_Place_In_L  :List;     --| Last place in L.
  2813.        Temp_Place_In_L  :List;     --| Holds a place in L to be removed.
  2814.  
  2815.    --| Walk over the list removing all elements with the value Element.
  2816.  
  2817.    begin
  2818.        Place_In_L := L;
  2819.        Last_Place_In_L := null;
  2820.        while (Place_In_L /= null) loop
  2821.            --| Found an element equal to Element
  2822.            if Equal(Place_In_L.Info, Element) then
  2823.                 --| If Last_Place_In_L is null then we are at first element
  2824.                 --| in L.
  2825.                 if Last_Place_In_L = null then
  2826.                      Temp_Place_In_L := Place_In_L;
  2827.                      L := Place_In_L.Next;
  2828.                 else
  2829.                      Temp_Place_In_L := Place_In_L;
  2830.                
  2831.                      --| Relink the list Last's Next gets Place's Next
  2832.  
  2833.                      Last_Place_In_L.Next := Place_In_L.Next;
  2834.                 end if;
  2835.  
  2836.                 --| Move Place_In_L to the next position in the list.
  2837.                 --| Free the element.
  2838.                 --| Do not update the last element in the list it remains the
  2839.                 --| same. 
  2840.  
  2841.                 Place_In_L := Place_In_L.Next;                       
  2842.                 Free (Temp_Place_In_L);
  2843.            else
  2844.                 --| Update the last place in L and the place in L.
  2845.  
  2846.                 Last_Place_In_L := Place_In_L;
  2847.                 Place_In_L := Place_In_L.Next;                       
  2848.            end if;    
  2849.        end loop;
  2850.  
  2851.    --| If we have not found an element raise an exception.
  2852.  
  2853.    end DeleteItems;
  2854. ------------------------------------------------------------------------------
  2855.  
  2856.    procedure Destroy (L: in out List) is
  2857.  
  2858.        Place_In_L:  List;
  2859.        HoldPlace:   List;
  2860.  
  2861.    --| Walk down the list removing all the elements and set the list to
  2862.    --| the empty list. 
  2863.  
  2864.    begin
  2865.        Place_In_L := L;
  2866.        while Place_In_L /= null loop
  2867.            HoldPlace := Place_In_L;
  2868.            Place_In_L := Place_In_L.Next;
  2869.            Free (HoldPlace);
  2870.        end loop;
  2871.        L := null;
  2872.    end Destroy;
  2873.  
  2874. --------------------------------------------------------------------------
  2875.  
  2876.    procedure DestroyDeep (L: in out List) is
  2877.  
  2878.        Place_In_L:  List;
  2879.        HoldPlace:   List;
  2880.  
  2881.    --| Walk down the list removing all the elements and set the list to
  2882.    --| the empty list. 
  2883.  
  2884.    begin
  2885.        Place_In_L := L;
  2886.        while Place_In_L /= null loop
  2887.            HoldPlace := Place_In_L;
  2888.            Place_In_L := Place_In_L.Next;
  2889.            Dispose (HoldPlace.Info);
  2890.            Free (HoldPlace);
  2891.        end loop;
  2892.        L := null;
  2893.    end DestroyDeep;
  2894.  
  2895. --------------------------------------------------------------------------
  2896.  
  2897.    function FirstValue (L: in    List) return ItemType is
  2898.  
  2899.    --| Return the first value in the list.
  2900.  
  2901.    begin
  2902.        if L = null then
  2903.        raise EmptyList;
  2904.        else
  2905.            return (L.Info);
  2906.        end if;
  2907.    end FirstValue;
  2908.    
  2909. --------------------------------------------------------------------------
  2910.  
  2911.    procedure Forward (I: in out ListIter) is
  2912.  
  2913.    --| Return the pointer to the next member of the list.
  2914.  
  2915.    begin
  2916.        if I = null then 
  2917.            raise NoMore;
  2918.        else
  2919.            I := ListIter (I.Next);
  2920.        end if;
  2921.    end Forward;
  2922.    
  2923. --------------------------------------------------------------------------
  2924.  
  2925.    function IsInList (L:       in    List; 
  2926.                       Element: in    ItemType  ) return boolean is
  2927.  
  2928.    Place_In_L: List;
  2929.  
  2930.    --| Check if Element is in L.  If it is return true otherwise return false.
  2931.  
  2932.    begin
  2933.        Place_In_L := L;
  2934.        while Place_In_L /= null loop
  2935.        if Equal(Place_In_L.Info, Element) then
  2936.            return true;
  2937.        end if;
  2938.            Place_In_L := Place_In_L.Next;
  2939.     end loop;
  2940.     return false;
  2941.    end IsInList;
  2942.  
  2943. --------------------------------------------------------------------------
  2944.  
  2945.     function IsEmpty (L: in     List) return boolean is
  2946.     
  2947.     --| Is the list L empty.
  2948.  
  2949.     begin
  2950.     return (L = null);
  2951.     end IsEmpty;
  2952.     
  2953. --------------------------------------------------------------------------
  2954.  
  2955.    function LastValue (L: in     List) return ItemType is
  2956.        
  2957.        LastElement: List;
  2958.  
  2959.    --| Return the value of the last element of the list. Get the pointer
  2960.    --| to the last element of L and then return its information.
  2961.  
  2962.    begin
  2963.        LastElement := Last (L);
  2964.        return LastElement.Info;
  2965.    end LastValue;
  2966.        
  2967. --------------------------------------------------------------------------
  2968.  
  2969.    function Length (L: in     List) return integer is
  2970.  
  2971.    --| Recursively compute the length of L.  The length of a list is
  2972.    --| 0 if it is null or  1 + the length of the tail.
  2973.  
  2974.    begin
  2975.        if L = null then
  2976.            return (0);
  2977.        else
  2978.            return (1 + Length (Tail (L)));
  2979.        end if;
  2980.    end Length;
  2981.  
  2982. --------------------------------------------------------------------------
  2983.  
  2984.    function MakeList (
  2985.           E :in     ItemType
  2986.    ) return List is
  2987.  
  2988.    begin
  2989.        return new Cell ' (Info => E, Next => null);
  2990.    end;
  2991.  
  2992. --------------------------------------------------------------------------
  2993.    function MakeListIter (L: in     List) return ListIter is
  2994.    
  2995.    --| Start an iteration operation on the list L.  Do a type conversion
  2996.    --| from List to ListIter.
  2997.     
  2998.    begin
  2999.        return ListIter (L);
  3000.    end MakeListIter;
  3001.  
  3002. --------------------------------------------------------------------------
  3003.  
  3004.    function More (L: in     ListIter) return boolean is
  3005.  
  3006.    --| This is a test to see whether an iteration is complete.
  3007.   
  3008.    begin
  3009.        return L /= null;
  3010.    end;
  3011.  
  3012. --------------------------------------------------------------------------
  3013.  
  3014.    procedure Next (Place:   in out ListIter;
  3015.                    Info:       out ItemType ) is
  3016.        PlaceInList: List;
  3017.    
  3018.    --| This procedure gets the information at the current place in the List
  3019.    --| and moves the ListIter to the next postion in the list.
  3020.    --| If we are at the end of a list then exception NoMore is raised.
  3021.  
  3022.    begin
  3023.        if Place = null then
  3024.       raise NoMore;
  3025.        else
  3026.           PlaceInList := List(Place);  
  3027.           Info := PlaceInList.Info;
  3028.           Place := ListIter(PlaceInList.Next);
  3029.        end if;
  3030.    end Next;
  3031.  
  3032. --------------------------------------------------------------------------
  3033.  
  3034.    procedure ReplaceHead (L:    in out  List;
  3035.                           Info: in      ItemType ) is
  3036.  
  3037.    --| This procedure replaces the information at the head of a list
  3038.    --| with the given information. If the list is empty the exception
  3039.    --| EmptyList is raised.
  3040.  
  3041.    begin
  3042.        if L = null then
  3043.        raise EmptyList;
  3044.        else
  3045.            L.Info := Info;
  3046.        end if;
  3047.    end ReplaceHead;
  3048.  
  3049. --------------------------------------------------------------------------
  3050.  
  3051.    procedure ReplaceTail (L:        in out List;
  3052.                           NewTail:  in     List  ) is
  3053.        Temp_L: List;
  3054.    
  3055.    --| This destroys the tail of a list and replaces the tail with
  3056.    --| NewTail.  If L is empty EmptyList is raised.
  3057.  
  3058.    begin
  3059.        Destroy(L.Next); 
  3060.        L.Next := NewTail; 
  3061.    exception
  3062.        when constraint_error =>
  3063.            raise EmptyList;
  3064.    end ReplaceTail;
  3065.  
  3066. --------------------------------------------------------------------------
  3067.  
  3068.     function Tail (L: in    List) return List is
  3069.  
  3070.     --| This returns the list which is the tail of L.  If L is null 
  3071.     --| EmptyList is raised.
  3072.  
  3073.     begin
  3074.     if L = null then
  3075.         raise EmptyList;
  3076.     else
  3077.         return L.Next;
  3078.     end if;
  3079.     end Tail;
  3080.  
  3081. --------------------------------------------------------------------------
  3082.  
  3083.     function CellValue (     
  3084.            I :in ListIter
  3085.     ) return ItemType is
  3086.         L :List;
  3087.     begin
  3088.           -- Convert I to a List type and then return the value it points to.
  3089.         L := List(I);
  3090.         return L.Info;
  3091.     end CellValue;
  3092.  
  3093. --------------------------------------------------------------------------
  3094.     function Equal (List1: in    List;
  3095.                     List2: in    List ) return boolean is
  3096.  
  3097.         PlaceInList1: List;
  3098.         PlaceInList2: LIst;
  3099.     Contents1:    ItemType;
  3100.     Contents2:    ItemType;
  3101.  
  3102.     --| This function tests to see if two lists are equal.  Two lists
  3103.     --| are equal if for all the elements of List1 the corresponding
  3104.     --| element of List2 has the same value.  Thus if the 1st elements
  3105.     --| are equal and the second elements are equal and so up to n.
  3106.     --|  Thus a necessary condition for two lists to be equal is that
  3107.     --| they have the same number of elements.
  3108.  
  3109.     --| This function walks over the two list and checks that the
  3110.     --| corresponding elements are equal.  As soon as we reach 
  3111.     --| the end of a list (PlaceInList = null) we fall out of the loop.
  3112.     --| If both PlaceInList1 and PlaceInList2 are null after exiting the loop
  3113.     --| then the lists are equal.  If they both are not null the lists aren't 
  3114.     --| equal.  Note that equality on elements is based on a user supplied
  3115.     --| function Equal which is used to test for item equality.
  3116.  
  3117.     begin
  3118.         PlaceInList1 := List1;
  3119.         PlaceInList2 := List2;
  3120.         while   (PlaceInList1 /= null) and (PlaceInList2 /= null) loop
  3121.             if not Equal (PlaceInList1.Info, PlaceInList2.Info) then
  3122.                 return false;
  3123.             end if;
  3124.         PlaceInList1 := PlaceInList1.Next;
  3125.         PlaceInList2 := PlaceInList2.Next;
  3126.         end loop;
  3127.         return ((PlaceInList1 = null) and (PlaceInList2 = null) );
  3128.     end Equal;
  3129. end Lists;
  3130.  
  3131. --------------------------------------------------------------------------
  3132.  
  3133.  
  3134. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3135. --ltrees.spc
  3136. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3137.  
  3138. with Lists;
  3139. generic
  3140.     type Label_Type is private;
  3141.                        --| This is used to identify nodes in the tree.
  3142.  
  3143.     type Value_Type is private; 
  3144.                        --| Information being contained in a node of tree
  3145.  
  3146.  
  3147.     with function "<" ( 
  3148.                X  :in    Label_Type;
  3149.                Y  :in    Label_Type
  3150.     ) return boolean is <> ;
  3151.                        --| Function which defines ordering of nodes
  3152.                        --| a < b -> not (b < a) and  (b /= a) for all a and b.
  3153. package Labeled_Trees  is 
  3154.  
  3155. --| Overview
  3156. --| This package creates an ordered binary tree.  This will allow for 
  3157. --| quick insertion, and search.  
  3158. --|
  3159. --| The tree is organized such that 
  3160. --|  
  3161. --|  label (leftchild) < label (root)    label (root) < label (rightchild)
  3162. --| 
  3163. --| This means that by doing a left to right search of the tree will 
  3164. --| produce the nodes of the tree in ascending order.
  3165.  
  3166.  
  3167.  
  3168.  
  3169.  
  3170. --                             Types
  3171. --                             -----
  3172.  
  3173. type Tree is  private;     --| This is the type exported to represent the
  3174.                            --| tree.
  3175.  
  3176.  
  3177. type Tree_Iter is private;  --| This is the type which is used to iterate
  3178.                             --| over the set.
  3179.  
  3180. --|                          Exceptions
  3181. --|                          ----------
  3182.  
  3183. Label_Already_Exists_In_Tree :exception;     
  3184. Label_Not_Present            :exception;
  3185. No_More                      :exception;
  3186. Tree_Is_Empty                :exception;    
  3187.  
  3188. --|                          Operations
  3189. --|                          ----------
  3190. --|
  3191. --| Create              Creates a tree.
  3192. --| Destroy_Tree        Destroys the given tree and returns the spaces.
  3193. --| Destroy_Deep_Tree   Destroys all space associated with a tree.  This
  3194. --|                     includes all nodes and the label and value associated
  3195. --|                     with each node.
  3196. --| Fetch_Value         Given a tree and or a label this returns the value
  3197. --|                     associated with the tree or label.
  3198. --| Get_Tree            Given a tree and a label this returns the tree
  3199. --|                     whose root is at the label.
  3200. --| Forward             This advances the iterator to the next node in the
  3201. --|                     iteration.
  3202. --| Insert_Node         This inserts a node n into a tree t.
  3203. --| Is_Empty            Returns true if the tree is empty false otherwise.
  3204. --| Iterator_Label      This returns the label of the node which corresponds
  3205. --|                     to the given iterator.
  3206. --| Iterator_Value      This returns the value of the node which corresponds
  3207. --|                     to the given iterator.
  3208. --| Make_Tree           This takes a label and a value and returns a tree.
  3209. --| Make_Tree_Iter_In   This returns an iterator to the user in order to start
  3210. --|                     an inorder iteration of the tree.  Inorder means
  3211. --|                     scan left child, scan node, scan right child.
  3212. --| Make_Tree_Iter_Pre  This returns an iterator to the use in order to 
  3213. --|                     start a preorder scan of the tree. Preorder is 
  3214. --|                     scan node, scan left child, scan right child.
  3215. --| Make_Tree_Iter_Post This returns an iterator to the user in order to
  3216. --|                     start a postorder scan of the tree. Postorder
  3217. --|                     means scan the left child, right child and then the 
  3218. --|                     node.  
  3219. --| More                This returns true if there are more elements to iterate
  3220. --|                     over in the tree.
  3221. --| Next                This returns the information associated with the 
  3222. --|                     current iterator and advances the iterator.
  3223. --| Store_Value         Replaces the given node's information with 
  3224. --|                     the given information.       
  3225.  
  3226. ---------------------------------------------------------------------------
  3227.  
  3228. function Create             --| This function creates the tree.
  3229.  
  3230. return Tree;
  3231.  
  3232. --| Effects
  3233. --| This creates a tree containing no information and no children.  An 
  3234. --| emptytree.
  3235.  
  3236. -------------------------------------------------------------------------------
  3237.  
  3238. generic
  3239.   with procedure Dispose_Label (L :in out Label_Type);
  3240.   with procedure Dispose_Value (V :in out Value_Type);
  3241. procedure Destroy_Deep_Tree (     --| Procedure destroys all nodes in a tree 
  3242.                                   --| and the label and value assoiciated with
  3243.                                   --| each node.
  3244.   T :in out Tree
  3245. );
  3246.  
  3247. -------------------------------------------------------------------------------
  3248.     
  3249. procedure Destroy_Tree (         --| Destroys a tree.
  3250.           T  :in out Tree        --| Tree being destroyed.
  3251. );
  3252.  
  3253. --| Effects
  3254. --| Destroys a tree and returns the space which it is occupying.
  3255.  
  3256. --------------------------------------------------------------------------
  3257.  
  3258. function Fetch_Value (         --| Get the value of the node with the given 
  3259.                                --| label.
  3260.        T :in     Tree;         --| The tree which contains the node.
  3261.        L :in     Label_Type    --| The label of the node.
  3262. ) return Value_Type;   
  3263.  
  3264. --| Effects 
  3265. --| If the label is not present Label_Not_Present is raised.
  3266.  
  3267. --------------------------------------------------------------------------
  3268.  
  3269. function Fetch_Value (  --| Return the value stored at the root node
  3270.                         --| of the given tree.
  3271.          T :in Tree
  3272. ) return Value_Type;
  3273.  
  3274. --| Effects
  3275. --| Raises Label_Not_Present if the tree T is empty.  
  3276.  
  3277. --------------------------------------------------------------------------
  3278.  
  3279. function Get_Tree (         --| Get the subtree whose root is labelled L.
  3280.        T :in    Tree;       --| Tree which contains the label L.
  3281.        L :in    Label_Type  --| The label being searched for.
  3282. ) return Tree;
  3283.  
  3284. --| Raises
  3285. --| Raises Label_Not_Present if the label L is not in T.
  3286.  
  3287. --------------------------------------------------------------------------
  3288.  
  3289. procedure Forward (        --| Advances the iterator to the next node in
  3290.                            --| the iteration. 
  3291.   I :in out Tree_Iter      --| Iterator being advance.
  3292. );
  3293.  
  3294. --| OVERVIEW
  3295. --| This is used to advance the iterator.  Typically this is used in
  3296. --| conjunction with Node_Value and Node_Label.
  3297.  
  3298. --------------------------------------------------------------------------
  3299.  
  3300. procedure Insert_Node(            --| This procedure inserts a node into the 
  3301.                                   --| specified tree.
  3302.        T      :in out Tree;       --| Tree being inserted into.
  3303.        L      :in     Label_Type; --| The label for the value being inserted.
  3304.        V      :in     Value_Type  --| The information to be contained in the 
  3305.                                   --| node being inserted.   
  3306.  
  3307. ); 
  3308. --| EFFECTS
  3309. --| This adds the node with label L to the tree T.  Label_Already_Exists is 
  3310. --| raised if L already exists in T.
  3311.  
  3312. --| MODIFIES
  3313. --| This modifies the tree T by adding a node whose label is l and value is v.
  3314.  
  3315. ------------------------------------------------------------------------------
  3316.  
  3317. function Is_Empty (        --| Returns true if the tree is empty false
  3318.                            --| otherwise.
  3319.          T :in     Tree
  3320. ) return boolean;
  3321.  
  3322. ------------------------------------------------------------------------------
  3323.  
  3324.  
  3325. function Is_Label_In_Tree (            --| Is the given label in the given
  3326.                                        --| tree.
  3327.          T :in    Tree;                --| The tree being searched.
  3328.          L :in    Label_Type           --| The label being searched for.
  3329. ) return boolean;
  3330.  
  3331. ------------------------------------------------------------------------------
  3332.  
  3333. procedure Is_Label_In_Tree (      --| Sets the variable Present to true if
  3334.                                   --| the given label is in the given tree.
  3335.            T       :in     Tree;        --| Tree being searched.
  3336.            L       :in     Label_Type;  --| Label being searched for.
  3337.            Subtree :   out Tree;        --| Subtree which is contains label.
  3338.            Present :   out boolean      --| True if label is in tree, false
  3339.                                         --| if not.
  3340. );
  3341.  
  3342. --| OVERVIEW
  3343. --| This operation can be used to see if a label is in the tree.
  3344. --| If it is the Subtree out parameter can then be used to
  3345. --| to update the value field of the label.  The sequence would be
  3346. --| 
  3347. --|  Is_Label_In_Tree (T, L, Subtree, Present);
  3348. --|  if Present then
  3349. --|     Store_Value (Subtree, SomeValue);
  3350. --|  end if;
  3351. --| 
  3352. --| If the label is not Present then Subtree is the root of the tree
  3353. --| where the label would be stored if it were present.  Thus the following
  3354. --| sequence would be useful.
  3355. --|
  3356. --| Is_Label_In_Tree (T, L, Subtree, Present);
  3357. --| if not Present then
  3358. --|    Insert_Node (Subtree, L, V);
  3359. --| end if;
  3360. --| 
  3361. --| The advantage to this routine is that the tree need only be searched 
  3362. --| once instead of twice once for the existence check and then once for
  3363. --| the insertion.
  3364.  
  3365. --| MODIFIES
  3366. --| The tree T, also sets the variables Present and Subtree.
  3367.  
  3368. ------------------------------------------------------------------------------
  3369.  
  3370. function Iterator_Label (  --| Returns the label of the node corresponding
  3371.                            --| to the iterator.
  3372.   I :in      Tree_Iter     --| Iterator.
  3373. ) return Label_Type;
  3374.  
  3375. -----------------------------------------------------------------------------
  3376.  
  3377. function Iterator_Value (  --| Returns the value of the node corresponding
  3378.                            --| to the iterator.
  3379.   I :in      Tree_Iter     --| Iterator.
  3380. ) return Value_Type;
  3381.  
  3382. -----------------------------------------------------------------------------
  3383.  
  3384. function Make_Tree (          --| This creates a tree given a label and a  
  3385.                               --| value.
  3386.        L :in     Label_Type;  --| The label.
  3387.        V :in     Value_Type   --| The value.
  3388. ) return Tree;
  3389.  
  3390. --| EFFECTS
  3391. --| Creates a tree whose root has the given label and value.
  3392.  
  3393. ------------------------------------------------------------------------------
  3394.  
  3395. function Make_Tree_Iter_In  (  --| This sets up an iteration of the nodes
  3396.                                --| of the tree in inorder.  
  3397.         T :in     Tree         --| Tree being iterated over 
  3398. ) return Tree_Iter;
  3399.  
  3400.  
  3401. --| EFFECTS
  3402. --| By using the Next operations the nodes of the tree are returned in
  3403. --| in post order. Inorder means return the left child then the node 
  3404. --| then the right child.
  3405.  
  3406. ------------------------------------------------------------------------------
  3407.  
  3408. function Make_Tree_Iter_Post (  --| This sets up an iteration of the nodes
  3409.                                 --| of the tree in postorder.  
  3410.         T :in     Tree          --| Tree being iterated over 
  3411. ) return Tree_Iter;
  3412.  
  3413.  
  3414. --| EFFECTS
  3415. --| By using the Next operations the nodes of the tree are returned in
  3416. --| post order. Post order means return the node first then its left child 
  3417. --| and then its right child.
  3418.  
  3419. -----------------------------------------------------------------------------
  3420.  
  3421. function Make_Tree_Iter_Pre (   --| This sets up an iteration of the nodes
  3422.                                 --| of the tree in preorder.  Then nodes
  3423.                                 --| of the tree are returned in ascending 
  3424.                                 --| order.  
  3425.         T :in     Tree          --| Tree being iterated over 
  3426. ) return Tree_Iter;
  3427.  
  3428.  
  3429. --| EFFECTS
  3430. --| By using the Next operations the nodes of the tree are returned in
  3431. --| ascending order.
  3432.  
  3433. -----------------------------------------------------------------------------
  3434.  
  3435. function More (                 --| Returns true if there are more elements 
  3436.                                 --| in the tree to iterate over.
  3437.           I :in Tree_Iter  
  3438. ) return boolean;
  3439.  
  3440.  
  3441. -----------------------------------------------------------------------------
  3442.  
  3443. procedure Next (                --| This returns the next element in the 
  3444.                                 --| iteration.
  3445.     I :in out Tree_Iter;        --| The Iter which marks the position in the 
  3446.                                 --| Tree.
  3447.     V :   out Value_Type        --| Information being returned from a node.
  3448. );    
  3449. --| EFFECTS
  3450. --| No_More is raised when after the last element has been returned an attempt
  3451. --| is made to get another element.
  3452.  
  3453.  
  3454. ---------------------------------------------------------------------------
  3455.  
  3456. procedure Next (                --| This is the iterator operation.  
  3457.     I :in out Tree_Iter;        --| The iterator which marks the position in
  3458.                                 --| the Tree.
  3459.     V :   out Value_Type;       --| Information being returned from a node.
  3460.     L :   out Label_Type        --| The label of the node in the iteration.
  3461.  
  3462. );    
  3463.  
  3464. --| EFFECTS
  3465. --| This iteration operation returns the label of a node as well as the 
  3466. --| nodes value.  No_More is raised if Next is called after the last
  3467. --| element of the tree has been returned.
  3468.  
  3469.  
  3470. ---------------------------------------------------------------------------
  3471.  
  3472. procedure Store_Value (             
  3473.         T :in out Tree;          --| The tree which contains the label
  3474.                                  --| whose value is being changed.
  3475.         L :in     Label_Type;    --| The label of the node where the 
  3476.                                  --| information is being stored.
  3477.         V :in     Value_Type     --| The value being stored.
  3478. );
  3479.  
  3480. --| MODIFIES
  3481. --| The tree T, and the node identified by the label L.  
  3482.  
  3483. --| EFFECTS
  3484. --| Label_Not_Present is raised if L is not in T.
  3485.  
  3486. ---------------------------------------------------------------------------
  3487.  
  3488. procedure Store_Value (          --| This stores the value V in the root
  3489.                                  --| node of the tree T.   
  3490.         T :in out Tree;          --| Tree value being stored in the tree.
  3491.         V :in     Value_Type     --| The value being stored.
  3492. );
  3493.  
  3494. --| MODIFIES
  3495. --| The tree T, and the node identified by the label L.
  3496.  
  3497. --| EFFECTS
  3498. --| Raises Label_Not_Present if T is empty.
  3499.  
  3500. -------------------------------------------------------------------------------
  3501.  
  3502. private
  3503.  
  3504.    type Node;
  3505.    type Tree is access Node;
  3506.  
  3507.    type Node is 
  3508.         record
  3509.             Label           :Label_Type;
  3510.             Value           :Value_Type;
  3511.             Left_Child      :Tree;
  3512.             Right_Child     :Tree;
  3513.         end record;
  3514.  
  3515.    package Node_Order is new Lists (Tree);
  3516.  
  3517.  
  3518.    type Tree_Iter is
  3519.       record
  3520.           Node_List :Node_Order.List;
  3521.           State     :Node_Order.ListIter;
  3522.       end record;
  3523.  
  3524.  
  3525. end Labeled_Trees;
  3526.  
  3527.  
  3528. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3529. --ltrees.bdy
  3530. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3531. with unchecked_deallocation;
  3532. package body Labeled_Trees is
  3533.  
  3534. ----------------------------------------------------------------------------
  3535. --                   Local Subprograms
  3536. ----------------------------------------------------------------------------
  3537.  
  3538. procedure Free is new unchecked_deallocation (Node, Tree);
  3539.  
  3540. function equal (
  3541.        X :in     Label_Type;
  3542.        Y :in     Label_Type
  3543. ) return boolean is 
  3544.  
  3545. begin
  3546.     return (not (X < Y))  and  (not (Y < X));
  3547. end equal;
  3548.  
  3549. ------------------------------------------------------------------------------
  3550.  
  3551. procedure Internal_Is_Label_In_Tree (
  3552.    T         :in      Tree;
  3553.    L         :in      Label_Type;
  3554.    Parent    :in out Tree;
  3555.    Present   :   out boolean;
  3556.    recursed  :in out boolean
  3557. ) is
  3558. begin
  3559.     --| OVERVIEW
  3560.     --| This procedure is used so that
  3561.     --| Is_Label_In_Tree (T, L, Subtree, Present) returns more useful 
  3562.     --| information.  If the label L is not in the tree then Subtree is
  3563.     --| the root of the tree where L should be inserted.  If L is in 
  3564.     --| the tree then Subtree is the root of the tree where L is.
  3565.     --| This procedure is necessary because in Is_Label_In_Tree has Subtree
  3566.     --| as an out parameter not as in out.
  3567.  
  3568.     --| The variable Recursed is used to indicate whether we have called
  3569.     --| the procedure recursively.  It is used when T is null.  If T is
  3570.     --| null and we haven't called recursively then T's parent is null.
  3571.     --| If T is null and we have called the procedure recusively then
  3572.     --| T's parent is not null.
  3573.  
  3574.     if T = null then
  3575.         Present := false;
  3576.         if not Recursed then
  3577.             Parent := null;
  3578.         end if;
  3579.     elsif L < T.Label then
  3580.         Parent := T;
  3581.         recursed := true;
  3582.         Internal_Is_Label_In_Tree (T.Left_Child, L, Parent, Present, Recursed);
  3583.     elsif T.Label < L then
  3584.         Parent := T;
  3585.         Recursed := true;
  3586.         Internal_Is_Label_In_Tree (
  3587.           T.Right_Child , L, Parent, Present, Recursed
  3588.                                   );
  3589.     else
  3590.         Parent := T;
  3591.         Present := true;
  3592.     end if;
  3593. end Internal_Is_Label_In_Tree;
  3594.  
  3595. ------------------------------------------------------------------------------
  3596.  
  3597. function Pre_Order_Generate (
  3598.           T :in Tree
  3599. ) return  Node_Order.List is
  3600.  
  3601.  
  3602. --| This routine generates a list of pointers to nodes in the tree t.
  3603. --| The list of nodes is a pre order list of the nodes of the tree.
  3604.  
  3605.     L : Node_Order.List;
  3606. begin 
  3607.     L := Node_Order.Create;
  3608.     if T /= null then
  3609.         Node_Order.Attach (L, T);
  3610.         Node_Order.Attach (L, Pre_Order_Generate (T.Left_Child));
  3611.         Node_Order.Attach (L, Pre_Order_Generate (T.Right_Child));
  3612.     end if;
  3613.     return L;
  3614. end Pre_Order_Generate;
  3615.  
  3616. ------------------------------------------------------------------------------
  3617.  
  3618. function Post_Order_Generate (
  3619.           T :in Tree
  3620. ) return  Node_Order.List is
  3621.  
  3622.  
  3623. --| This routine generates a list of pointers to nodes in the tree t.
  3624. --| The list is a post ordered list of nodes of the tree.
  3625.  
  3626.     L : Node_Order.List;
  3627. begin 
  3628.     L := Node_Order.Create;
  3629.     if T /= null then
  3630.         L := Post_Order_Generate (T.Left_Child);
  3631.         Node_Order.Attach (L, Post_Order_Generate (T.Right_Child));
  3632.         Node_Order.Attach (L, T);
  3633.     end if;
  3634.     return L;
  3635. end Post_Order_Generate;
  3636.  
  3637. ------------------------------------------------------------------------------
  3638.  
  3639. function In_Order_Generate (
  3640.           T :in Tree
  3641. ) return  Node_Order.List is
  3642.  
  3643.  
  3644. --| This routine generates a list of pointers to nodes in the tree t.
  3645. --| The list is ordered with respect to the order of the nodes in the tree.
  3646. --| The nodes in the list are such the element 1 < element 2 < .... 
  3647. --| element (n - 1) < element (n).  Where < is passed in .
  3648.  
  3649.     L : Node_Order.List;
  3650. begin 
  3651.     L := Node_Order.Create;
  3652.     if T /= null then
  3653.         L := In_Order_Generate (T.Left_Child);
  3654.         Node_Order.Attach (L, T);
  3655.         Node_Order.Attach (L, In_Order_Generate (T.Right_Child));
  3656.     end if;
  3657.     return L;
  3658. end In_Order_Generate;
  3659.  
  3660. ------------------------------------------------------------------------------
  3661.  
  3662.  
  3663.  
  3664. ------------------------------------------------------------------------------
  3665. --                    Visible Subprograms
  3666. ------------------------------------------------------------------------------
  3667.  
  3668. ------------------------------------------------------------------------------
  3669.  
  3670. function Create  return Tree is
  3671.  
  3672. begin
  3673.     return null;
  3674. end;
  3675.  
  3676. ------------------------------------------------------------------------------
  3677.  
  3678. procedure Destroy_Deep_Tree (
  3679.   T :in out Tree
  3680. ) is
  3681.  
  3682. begin
  3683.     --| ALGORITHM
  3684.     --| Walk over the tree destroying the value, the label, and then the node
  3685.     --| itself.  Do this in post order.  This means destroy the left child
  3686.     --| destroy the right child and then destroy the node.
  3687.  
  3688.     if T /= null then
  3689.        Destroy_Deep_Tree (T.Left_Child);
  3690.        Destroy_Deep_Tree (T.Right_Child);
  3691.        Dispose_Label (T.Label);
  3692.        Dispose_Value (T.Value);
  3693.        Destroy_Tree (T);
  3694.     end if;
  3695. end;
  3696.  
  3697. ------------------------------------------------------------------------------
  3698.  
  3699. procedure Destroy_Tree ( T :in out Tree) is
  3700.  
  3701.  
  3702. begin
  3703.     --| OVERVIEW
  3704.     --| This procedure recursively destroys the tree T.
  3705.     --|  1.  It destroy the Left_Child of T
  3706.     --|  2.  It then destroys the Right_Child of T.
  3707.     --|  3.  It then destroy the root T and set T to be null.
  3708.  
  3709.     if T /= null then
  3710.         Destroy_Tree (T.Left_Child);
  3711.         Destroy_Tree (T.Right_Child);
  3712.         Free (T);
  3713.     end if;
  3714. end Destroy_Tree;
  3715.  
  3716. ------------------------------------------------------------------------------
  3717.  
  3718. function Fetch_Value (         --| Get the value of the node with the given 
  3719.                                --| value.
  3720.        T :in     Tree;         --| The tree which contains the node.
  3721.        L :in     Label_Type    --| The label of the node.
  3722. ) return Value_Type is
  3723.  
  3724. begin
  3725.     if T = null then 
  3726.         raise Label_Not_Present;
  3727.     elsif L < T.Label then
  3728.         return Fetch_Value (T.Left_Child, L);
  3729.     elsif T.Label < L then
  3730.         return Fetch_Value (T.Right_Child, L);
  3731.     else
  3732.         return T.Value;
  3733.     end if;               
  3734. end Fetch_Value;
  3735.      
  3736. --------------------------------------------------------------------------
  3737.  
  3738. function Fetch_Value (  --| Return the value stored at the root node
  3739.                         --| of the given tree.
  3740.          T :in Tree
  3741. ) return Value_Type is
  3742.  
  3743. begin
  3744.     if T = null then
  3745.        raise Tree_Is_Empty;    
  3746.     else
  3747.        return T.Value;
  3748.     end if;
  3749. end Fetch_Value;
  3750.   
  3751. --------------------------------------------------------------------------
  3752.  
  3753. procedure Forward (        --| Advances the iterator to the next node in
  3754.                            --| the iteration. 
  3755.   I :in out Tree_Iter      --| Iterator being advance.
  3756. ) is
  3757. begin
  3758.     Node_Order.Forward (I.State);
  3759. end Forward;
  3760.  
  3761. ------------------------------------------------------------------------------
  3762.  
  3763. function Get_Tree (         --| Get the tree whose root is labelled L.
  3764.        T :in    Tree;       --| Tree which contains the label L.
  3765.        L :in    Label_Type  --| The label being searched for.
  3766. ) return Tree is
  3767.  
  3768. begin
  3769.     if T = null then
  3770.         raise Label_Not_Present;
  3771.     elsif L < T.Label then
  3772.         return Get_Tree (T.Left_Child, L);
  3773.     elsif T.Label < L then
  3774.         return Get_Tree (T.Right_Child, L);
  3775.     else
  3776.        return T;
  3777.     end if;
  3778. end Get_Tree;
  3779.  
  3780. ------------------------------------------------------------------------------
  3781.  
  3782. procedure Insert_Node (       --| This procedure inserts a node into
  3783.                               --| the tree T with label and value V.
  3784.       T  :in out Tree;
  3785.       L  :in     Label_Type;
  3786.       V  :in     Value_Type
  3787. ) is
  3788.  
  3789. begin
  3790.     if T = null then
  3791.        T := new Node ' 
  3792.             ( Value => V, Label => L, Left_Child => null, Right_Child => null);
  3793.     elsif L < T.Label then
  3794.        Insert_Node (T.Left_Child, L, V);
  3795.     elsif T.Label < L then
  3796.        Insert_Node (T.Right_Child, L, V);
  3797.     elsif T.Label = L then
  3798.        raise Label_Already_Exists_In_Tree;
  3799.     end if;
  3800. end Insert_Node; 
  3801.     
  3802. ------------------------------------------------------------------------------
  3803.  
  3804. function Is_Empty (        --| Returns true if the tree is empty false
  3805.                            --| otherwise.
  3806.          T :in     Tree
  3807. ) return boolean is
  3808. begin
  3809.     return T = null;
  3810. end Is_Empty;
  3811.  
  3812. ------------------------------------------------------------------------------
  3813.  
  3814. function Is_Label_In_Tree (            --| Is the given label in the given
  3815.                                        --| tree.
  3816.          T :in    Tree;                --| The tree being searched.
  3817.          L :in    Label_Type           --| The label being searched for.
  3818. ) return boolean is
  3819. begin
  3820.     if T = null then
  3821.          return false;
  3822.     elsif L < T.Label then
  3823.          return Is_Label_In_Tree (T.Left_Child, L);
  3824.     elsif T.Label < L then
  3825.          return Is_Label_In_Tree (T.Right_Child, L);
  3826.     else
  3827.         return true;
  3828.     end if;
  3829. end Is_Label_In_Tree;
  3830.  
  3831. ------------------------------------------------------------------------------
  3832.  
  3833. procedure Is_Label_In_Tree (            --| Checks if the given label is 
  3834.                                         --| in the given tree.
  3835.            T       :in     Tree;        --| Tree being searched.
  3836.            L       :in     Label_Type;  --| Label being searched for.
  3837.            Subtree :   out Tree;        --| Subtree which is contains label.
  3838.            Present :   out boolean      --| True if label is in tree, false
  3839.                                         --| if not.
  3840. ) is
  3841.     Recursed          :boolean := false;
  3842.     Internal_Subtree  :Tree;    -- This variable is needed because
  3843.                                 -- in Internal_Is_Label subtree is an in out
  3844.                                 -- parameter.                   
  3845.       
  3846. begin
  3847.      --| Sets the variable Present to true if the given label is in the given 
  3848.      --| tree. Also sets the variable Subtree to 
  3849.      --| the root of the subtree which contains the label.  If L isn't in the
  3850.      --| tree then Subtree is the root of the tree where label should be
  3851.      --| inserted.  This internal routine is called so that if L isn't in T
  3852.      --| then Subtree will be the root of the tree where L should be inserted.
  3853.      --| In order to do this we need the extra variable Recursed.
  3854.  
  3855.     Internal_Is_Label_In_Tree (T, L, Internal_Subtree, Present, Recursed);
  3856.     Subtree := Internal_Subtree;
  3857. end Is_Label_In_Tree;
  3858.  
  3859. ----------------------------------------------------------------------------
  3860.  
  3861. function Iterator_Label (  --| Returns the label of the node corresponding
  3862.                            --| to the iterator.
  3863.   I :in      Tree_Iter     --| Iterator.
  3864. ) return Label_Type is
  3865.     T :Tree;
  3866. begin
  3867.     T := Node_Order.CellValue (I.State);
  3868.     return T.Label;
  3869. end Iterator_Label;
  3870.  
  3871. -----------------------------------------------------------------------------
  3872.  
  3873. function Iterator_Value (  --| Returns the value of the node corresponding
  3874.                            --| to the iterator.
  3875.   I :in      Tree_Iter     --| Iterator.
  3876. ) return Value_Type is
  3877.     T :Tree;
  3878. begin
  3879.     T := Node_Order.CellValue (I.State);
  3880.     return T.Value;
  3881. end;
  3882.  
  3883. -------------------------------------------------------------------------------
  3884.  
  3885. function Make_Tree (          --| This creates a tree given a label and a  
  3886.                               --| value.
  3887.        L :in     Label_Type;  --| The label.
  3888.        V :in     Value_Type   --| The value.
  3889. ) return Tree is
  3890.  
  3891. begin
  3892.      return  new Node ' ( 
  3893.                    Value => V, 
  3894.                    Label => L, 
  3895.                    Left_Child => null,
  3896.                    Right_Child => null
  3897.                         );
  3898. end;
  3899.  
  3900. -------------------------------------------------------------------------------
  3901.  
  3902. function Make_Tree_Iter_In  (  --| This sets up an inoder iteration of the 
  3903.                                --| nodes of the tree.
  3904.         T :in     Tree         --| Tree being iterated over 
  3905. ) return Tree_Iter is
  3906.  
  3907. --| This sets up the iterator for a tree T.
  3908. --| The NodeList keeps track of the order of the nodes of T.  The Node_List
  3909. --| is computed by first invoking In_Generate of the Left_Child then append
  3910. --| the root node to Node_List and then append the result of In_Generate
  3911. --| to Node_List.  Since the tree is ordered such that 
  3912. --|
  3913. --|    Left_Child < root    root < Right_Child 
  3914. --| 
  3915. --| Node_Order returns the nodes in ascending order.
  3916. --|
  3917. --| Thus Node_List keeps the list alive for the duration of the iteration
  3918. --| operation.  The variable State is the a pointer into the Node_List
  3919. --| which is the current place of the iteration.
  3920.  
  3921.     I :Tree_Iter;
  3922. begin
  3923.     I.Node_List := Node_Order.Create;
  3924.     if T /= null then
  3925.         Node_Order.Attach (I.Node_List, In_Order_Generate (T));    
  3926.     end if;
  3927.     I.State := Node_Order.MakeListIter (I.Node_List);
  3928.     return I;    
  3929. end Make_Tree_Iter_In;    
  3930.  
  3931. ------------------------------------------------------------------------------
  3932.  
  3933. function Make_Tree_Iter_Post (  --| This sets up a postorder iteration of the
  3934.                                 --| nodes of the tree.
  3935.         T :in     Tree          --| Tree being iterated over 
  3936. ) return Tree_Iter is
  3937.  
  3938. --| A postorder iteration of the tree ( + a b)  where the root is + and 
  3939. --| the left child is a and the right child is b will return the nodes
  3940. --| in the order a b +.  
  3941. --| Node_List is a post_ordered list of the nodes of the tree generated 
  3942. --| by Post_Order Generate. Thus Node_List keeps the list alive for the 
  3943. --| duration of the iteration operation.  The variable State is the a pointer 
  3944. --| into the Node_List which is the current place of the iteration.
  3945.  
  3946.     I :Tree_Iter;
  3947. begin
  3948.     I.Node_List := Node_Order.Create;
  3949.     if T /= null then
  3950.         Node_Order.Attach (I.Node_List, Post_Order_Generate (T));    
  3951.     end if;
  3952.     I.State := Node_Order.MakeListIter (I.Node_List);
  3953.     return I;    
  3954. end Make_Tree_Iter_Post;    
  3955.  
  3956. -----------------------------------------------------------------------------
  3957.  
  3958. function Make_Tree_Iter_Pre (   --| This sets up an iteration of the nodes
  3959.                                 --| of the tree in preorder.  Then nodes
  3960.                                 --| of the tree are returned in ascending 
  3961.                                 --| order.  
  3962.         T :in     Tree          --| Tree being iterated over 
  3963. ) return Tree_Iter is
  3964.  
  3965.  
  3966. --| A preorder iteration of the tree ( + a b)  where the root is + and 
  3967. --| the left child is a and the right child is b will return the nodes
  3968. --| in the order + a b .  
  3969. --| Node_List is a pre_ordered list of the nodes of the tree generated 
  3970. --| by Pre_Order_Generate. Thus Node_List keeps the list alive for the 
  3971. --| duration of the iteration operation.  The variable State is the a pointer 
  3972. --| into the Node_List which is the current place of the iteration.
  3973.  
  3974.     I :Tree_Iter;
  3975. begin
  3976.     I.Node_List := Node_Order.Create;
  3977.     if T /= null then
  3978.         Node_Order.Attach (I.Node_List, Pre_Order_Generate (T));    
  3979.     end if;
  3980.     I.State := Node_Order.MakeListIter (I.Node_List);
  3981.     return I;    
  3982. end Make_Tree_Iter_Pre;    
  3983.  
  3984. ------------------------------------------------------------------------------
  3985.  
  3986. function More (
  3987.      I :in Tree_Iter
  3988. ) return boolean is
  3989.    
  3990. begin
  3991.     return Node_Order.More (I.State);
  3992. end More;
  3993.  
  3994. ------------------------------------------------------------------------------
  3995.  
  3996. procedure Next (
  3997.           I     :in out Tree_Iter;
  3998.           V     :   out Value_Type       
  3999. ) is
  4000.  
  4001.  
  4002.     T :Tree;
  4003. begin
  4004.     --| OVERVIEW    
  4005.     --| Next returns the information at the current position in the iterator
  4006.     --| and increments the iterator.  This is accomplished by using the iterater
  4007.     --| associated with the Node_Order list.  This returns a pointer into the Tree
  4008.     --| and then the information found at this node in T is returned.
  4009.     Node_Order.Next (I.State, T);
  4010.     V := T.Value ;
  4011. exception 
  4012.     when Node_Order.NoMore => 
  4013.       raise No_More;
  4014.     when others =>
  4015.       raise;
  4016. end Next;
  4017.  
  4018. -----------------------------------------------------------------------------
  4019.  
  4020. procedure Next ( 
  4021.           I :in out Tree_Iter;
  4022.           V :   out Value_Type;
  4023.           L :   out Label_Type
  4024. ) is
  4025.  
  4026.     T :Tree;
  4027. begin
  4028.     --| OVERVIEW    
  4029.     --| Next returns the information at the current position in the iterator
  4030.     --| and increments the iterator.  This is accomplished by using the 
  4031.     --| iterater associated with the Node_Order list.  This returns a 
  4032.     --| pointer into the Tree and then the information found at this node in 
  4033.     --| T is returned.
  4034.  
  4035.     Node_Order.Next (I.State, T);
  4036.     V := T.Value ;
  4037.     L := T.Label;
  4038.  
  4039. exception 
  4040.     when Node_Order.NoMore => 
  4041.       raise No_More;
  4042.     when others =>
  4043.       raise;
  4044. end Next;
  4045.  
  4046. -----------------------------------------------------------------------------
  4047.  
  4048. procedure Store_Value (             
  4049.         T :in out Tree;          --| Tree value is being stored in.
  4050.         L :in     Label_Type;    --| The label of the node where the 
  4051.                                  --| information is being stored.
  4052.         V :in     Value_Type     --| The value being stored.
  4053. ) is
  4054.  
  4055. begin
  4056.     if T = null then
  4057.         raise Label_Not_Present;
  4058.     elsif L < T.Label then
  4059.         Store_Value (T.Left_Child, L, V);
  4060.     elsif T.Label < L then
  4061.         Store_Value (T.Right_Child, L, V);
  4062.     else
  4063.         T.Value := V;
  4064.     end if;
  4065. end Store_Value; 
  4066.  
  4067. -------------------------------------------------------------------------------
  4068.  
  4069. procedure Store_Value (          --| This stores the value V in the root
  4070.                                  --| node of the tree T.   
  4071.         T :in out Tree;          --| Tree value being stored in the tree.
  4072.         V :in     Value_Type     --| The value being stored.
  4073. ) is
  4074. begin
  4075.     if T /= null then 
  4076.         T.Value := V;
  4077.     else
  4078.         raise Label_Not_Present;
  4079.     end if;
  4080. end Store_Value;
  4081.  
  4082. -----------------------------------------------------------------------------
  4083. end Labeled_Trees;
  4084. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4085. --btrees.spc
  4086. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4087.  
  4088. with Lists;
  4089. generic
  4090.  
  4091.     type ItemType is private; 
  4092.                        --| Information being contained in a node of tree
  4093.  
  4094.  
  4095.     with function "<"(X,Y: in ItemType) return boolean;
  4096.                        --| Function which defines ordering of nodes
  4097.  
  4098. package BinaryTrees is 
  4099.  
  4100.  
  4101. --| Overview
  4102. --| This package creates an ordered binary tree.  This will allow for 
  4103. --| quick insertion, and search.  
  4104. --|
  4105. --| The tree is organized such that 
  4106. --|  
  4107. --|  leftchild < root    root < rightchild
  4108. --| 
  4109. --| This means that by doing a left to right search of the tree will can
  4110. --| produce the nodes of the tree in ascending order.
  4111.  
  4112.  
  4113.  
  4114.  
  4115.  
  4116. --                             Types
  4117. --                             -----
  4118.  
  4119. type Tree is  private;     --| This is the type exported to represent the
  4120.                            --| tree.
  4121.  
  4122.  
  4123. type TreeIter is private;  --| This is the type which is used to iterate
  4124.                            --| over the set.
  4125.  
  4126. --|                          Exceptions
  4127. --|                          ----------
  4128.  
  4129. --|                          Operations
  4130. --|                          ----------
  4131. --|
  4132. --| Create           Creates a tree.
  4133. --| Deposit          Replaces the given node's information with 
  4134. --|                  the given information.
  4135. --| DestroyTree      Destroys the given tree and returns the spaces.
  4136. --| InsertNode       This inserts a node n into a tree t.
  4137. --| MakeTreeIter     This returns an iterator to the user in order to start
  4138. --|                  an iteration.
  4139. --| More             This returns true if there are more elements to iterate
  4140. --|                  over in the tree.
  4141. --| Next             This returns the information associated with the current
  4142. --|                  iterator and advances the iterator.
  4143.        
  4144.  
  4145. ---------------------------------------------------------------------------
  4146.  
  4147. function Create             --| This function creates the tree.
  4148.  
  4149. return Tree;
  4150.  
  4151. --| Effects
  4152. --| This creates a tree containing no information and no children.  An 
  4153. --| emptytree.
  4154.  
  4155. -------------------------------------------------------------------------------
  4156.  
  4157. procedure Deposit (              --| This deposits the information I in the
  4158.                                  --| root of the Tree S.
  4159.           I :in     ItemType;    --| The information being deposited.
  4160.           S :in     Tree         --| The tree where the information is being
  4161.                                  --| stored.
  4162. );
  4163.  
  4164. --| Modifies
  4165. --| This changes the information stored at the root of the tree S.
  4166.  
  4167. -------------------------------------------------------------------------------
  4168.  
  4169.  
  4170. procedure DestroyTree (         --| Destroys a tree.
  4171.           T  :in out Tree       --| Tree being destroyed.
  4172. );
  4173.  
  4174. --| Effects
  4175. --| Destroys a tree and returns the space which it is occupying.
  4176.  
  4177. --------------------------------------------------------------------------
  4178.  
  4179. Procedure Insertnode(           --| This Procedure Inserts A Node Into The 
  4180.                                 --| Specified Tree.
  4181.        N      :In Out Itemtype; --| The Information To Be Contained In The 
  4182.                                 --| Node Being Inserted.   
  4183.                               
  4184.        T      :In Out Tree;     --| Tree Being Inserted Into.
  4185.        Root   :   Out Tree;     --| Root of the subtree which Node N heads. 
  4186.                                 --| This is the position of the node N in T.
  4187.        Exists :   out boolean   --| If this node already exists in the tree
  4188.                                 --| Exists is true.  If this is the first
  4189.                                 --| insertion Exists is false.
  4190. ); 
  4191.  
  4192. --| Effects
  4193. --| This adds the node N to the tree T inserting in the proper postion.
  4194.  
  4195. --| Modifies
  4196. --| This modifies the tree T by add the node N to it.
  4197.  
  4198. ------------------------------------------------------------------------------
  4199.  
  4200. function MakeTreeIter (         --| Sets a variable to a position in the
  4201.                                 --| tree
  4202.                                 --| where the iteration is to begin.  In this 
  4203.                                 --| case the position is a pointer to the  
  4204.                                 --| the deepest leftmost leaf in the tree.
  4205.         T:in Tree               --| Tree being iterated over 
  4206. ) return TreeIter;
  4207.  
  4208.  
  4209. --| Effects
  4210.  
  4211.  
  4212. -----------------------------------------------------------------------------
  4213.  
  4214. function More (                 --| Returns true if there are more elements 
  4215.                                 --| in the tree to iterate over.
  4216.           I :in TreeIter  
  4217. ) return boolean;
  4218.  
  4219.  
  4220. -----------------------------------------------------------------------------
  4221.  
  4222. procedure Next (                --| This is the iterator operation.  Given 
  4223.                                 --| an Iter in the Tree it returns the 
  4224.                                 --| item Iter points to and updates the
  4225.                                 --| iter. If Iter is at the end of the Tree, 
  4226.                                 --| yielditer returns false otherwise it 
  4227.                                 --| returns true.
  4228.     I        :in out TreeIter;  --| The iter which marks the position in the 
  4229.                                 --| Tree.
  4230.  
  4231.     Info     :   out ItemType   --| Information being returned from a node.
  4232. );    
  4233.  
  4234.  
  4235. ---------------------------------------------------------------------------
  4236.  
  4237. private
  4238.  
  4239.    type Node;
  4240.    type Tree is access Node;
  4241.  
  4242.    type Node is 
  4243.         record
  4244.             Info           :ItemType;
  4245.             LeftChild      :Tree;
  4246.             RightChild     :Tree;
  4247.         end record;
  4248.  
  4249.    package NodeOrder is new Lists (Tree);
  4250.  
  4251.  
  4252.    type TreeIter is
  4253.       record
  4254.           NodeList :NodeOrder.List;
  4255.           State    :NodeOrder.ListIter;
  4256.       end record;
  4257.  
  4258.  
  4259. end BinaryTrees;
  4260.  
  4261.  
  4262. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4263. --btrees.bdy
  4264. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4265.  
  4266. with unchecked_deallocation;
  4267.  
  4268. package body Binarytrees is
  4269.  
  4270. ----------------------------------------------------------------------------
  4271. --                   Local Subprograms
  4272. ----------------------------------------------------------------------------
  4273.  
  4274. procedure Free is new unchecked_deallocation (Node, Tree);
  4275.  
  4276. function equal (X, Y: in ItemType) return boolean is 
  4277.  
  4278. begin
  4279.  
  4280.     return (not (X < Y))  and  (not (Y < X));
  4281. end;
  4282.  
  4283. ------------------------------------------------------------------------------
  4284.  
  4285. function generate (T :in Tree ) return  Nodeorder.List is
  4286.     L : Nodeorder.List;
  4287.  
  4288. --| This routine generates a list of pointers to nodes in the tree t.
  4289. --| The list is ordered with respect to the order of the nodes in the tree.
  4290.  
  4291. --| generate does a depth first search of the tree.  
  4292. --| 1.   It first visits the leftchild of t and generates the list for that.
  4293. --| 2.   It then appends the root node of t to the list generated for the left
  4294. --|      child.
  4295. --| 3.   It then appends the list generated for the rightchild to the list
  4296. --|      generated for the leftchild and the root.
  4297. --|
  4298.  
  4299. begin 
  4300.     L := NodeOrder.Create;
  4301.     if T /= null then
  4302.         L := Generate (T.Leftchild);
  4303.         Nodeorder.Attach (L, T);
  4304.         Nodeorder.Attach (L, Generate (T.Rightchild));
  4305.     end if;
  4306.     return L;
  4307. End Generate;
  4308.  
  4309. ------------------------------------------------------------------------------
  4310.  
  4311.  
  4312.  
  4313. ------------------------------------------------------------------------------
  4314. --                    Visible Subprograms
  4315. ------------------------------------------------------------------------------
  4316.  
  4317.  
  4318.  
  4319.  
  4320.  
  4321. ------------------------------------------------------------------------------
  4322.  
  4323. function Create  return Tree is
  4324.  
  4325. begin
  4326.     return null;
  4327. end;
  4328.  
  4329. -----------------------------------------------------------------------------
  4330.  
  4331. procedure Deposit (
  4332.           I :in      ItemType;
  4333.           S :in      Tree         ) is
  4334.  
  4335. begin
  4336.     S.Info := I;
  4337. end;
  4338.  
  4339. ------------------------------------------------------------------------------
  4340.  
  4341. procedure DestroyTree ( T :in out Tree) is
  4342.  
  4343. --| This procedure recursively destroys the tree T.
  4344. --|  1.  It destroy the leftchild of T
  4345. --|  2.  It then destroys the rightchild of T.
  4346. --|  3.  It then destroy the root T and set T to be null.
  4347.  
  4348. begin
  4349.     if T.leftchild /= null then
  4350.      DestroyTree (T.leftchild);
  4351.      DestroyTree (T.rightchild);
  4352.      Free (T);
  4353. end if;
  4354. end DestroyTree;
  4355.  
  4356. ------------------------------------------------------------------------------
  4357.  
  4358. procedure InsertNode ( 
  4359.         N           :in out ItemType;    --| Node being inserted.
  4360.         T           :in out Tree;        --| Tree node is being inserted
  4361.                                          --| into.                   
  4362.         Root        :   out Tree;        --| Root of the subtree which node N
  4363.                                          --| heads.  This is the position of 
  4364.                                          --| node N in T;
  4365.         Exists      :   out boolean      --| If this node already exists in
  4366.                                          --| the tree then Exists is true. If
  4367.                                          --| If this is the first insertion 
  4368.                                          --| Exists is false.
  4369.               
  4370.                                                                        ) is
  4371. --| This inserts the node N in T.
  4372. --| 1.  If T is null then a new node is allocated and assigned to T
  4373. --| 2.  If T is not null then T is searched for the proper place to insert n.
  4374. --|     This is first done by checking whether N < rightchild 
  4375. --| 3.  If this is not true then we check to see if leftchild < N
  4376. --| 4.  If this is not true then N is in the tree.
  4377.  
  4378. begin
  4379.     if T = null then
  4380.         T := new Node ' (Info => N, leftchild => null, rightchild => null);
  4381.         Root := T;
  4382.         Exists := false;
  4383.         N := T.Info;
  4384.     elsif N < T.Info then
  4385.         InsertNode (N, T.leftchild, Root, Exists);
  4386.     elsif T.Info < N then
  4387.         InsertNode (N, T.rightchild, Root, Exists);
  4388.     else
  4389.         Root := T;
  4390.         Exists := true;
  4391.         N := T.Info;
  4392.         
  4393.     end if;
  4394. end InsertNode;
  4395.  
  4396. ------------------------------------------------------------------------------
  4397.  
  4398. function MakeTreeIter (T :in     Tree ) return TreeIter is
  4399.  
  4400.     I :TreeIter;
  4401. --| This sets up the iterator for a tree T.
  4402. --| The NodeList keeps track of the order of the nodes of T.  The NodeList
  4403. --| is computed by first invoking Generate of the leftchild then append
  4404. --| the root node to NodeList and then append the result of Generate
  4405. --| to NodeList.  Since the tree is ordered such that 
  4406. --|
  4407. --|    leftchild < root    root < rightchild 
  4408. --| 
  4409. --| NodeOrder returns the nodes in ascending order.
  4410. --|
  4411. --| Thus NodeList keeps the list alive for the duration of the iteration
  4412. --| operation.  The variable State is the a pointer into the NodeList
  4413. --| which is the current place of the iteration.
  4414.  
  4415. begin
  4416.     I.NodeList := NodeOrder.Create;
  4417.     if T /= null then
  4418.         I.NodeList := Generate (T.leftchild);
  4419.         NodeOrder.Attach (I.NodeList, T);    
  4420.         NodeOrder.Attach (I.NodeList, Generate (T.rightChild));
  4421.     end if;
  4422.     I.State := NodeOrder.MakeListIter (I.NodeList);
  4423.     return I;    
  4424. end;    
  4425.  
  4426. ------------------------------------------------------------------------------
  4427.  
  4428. function More (I :in TreeIter) return boolean is
  4429.    
  4430. begin
  4431.     return NodeOrder.More (I.State);
  4432. end;
  4433.  
  4434. ------------------------------------------------------------------------------
  4435.  
  4436. procedure Next (
  4437.           I    :in out TreeIter;
  4438.           Info :   out ItemType       ) is
  4439.   T: Tree;
  4440.     
  4441. --| Next returns the information at the current position in the iterator
  4442. --| and increments the iterator.  This is accomplished by using the iterater
  4443. --| associated with the NodeOrder list.  This returns a pointer into the Tree
  4444. --| and then the information found at this node in T is returned.
  4445.  
  4446.  
  4447. begin
  4448.     NodeOrder.Next (I.State, T);
  4449.     Info := T.Info;
  4450. end;
  4451.  
  4452. -------------------------------------------------------------------------------
  4453.  
  4454. end BinaryTrees;
  4455. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4456. --DOCREF.SPC
  4457. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4458. package Document_Ref is
  4459. --| Defines and supports a standard form for expressing references to a 
  4460. --| document.
  4461.  
  4462. --| Overview
  4463. --| This package defines and supports a notation for naming documents
  4464. --| and positions within the document (by paragraph).  The syntax of a 
  4465. --| reference to a document is as follows:
  4466. --|-
  4467. --|     Reference    ::= DocID ParagraphID
  4468. --|     DocID        ::= Name [ Version ] { '.' Name [ Version ] }
  4469. --|     ParagraphID  ::= DottedNumber
  4470. --|     Name         ::= Letter { [ Underline ] Letter | Digit }
  4471. --|     Version      ::= '(' DottedNumber ')'
  4472. --|     DottedNumber ::= Number { '.' Number }
  4473. --|+
  4474. --| This package defines types for each of the non-terminals in the
  4475. --| above grammar, functions for scanning values of each type from
  4476. --| a string, and functions for comparing objects of each type.
  4477. --| 
  4478. --| For purposes of comparison, each of the string types defined
  4479. --| here are considered to be made up of components.  For example, in 
  4480. --| the ParagraphID "(1.2.3)", the components are "1", "2", and "3".  
  4481. --| In comparing one string to another, the strings are compared one
  4482. --| component at a time.  If the components differ, the result is
  4483. --| determined by those components.  If the components are the same,
  4484. --| the result is determined by comparing the next pair of components.
  4485. --| If one string runs out of components before the other one does,
  4486. --| the one with fewer components is less than the one with more of
  4487. --| them.  Thus, "(1.2.1)" < "(1.3)" but "(1.2)" < "(1.2.3)", and
  4488. --| the null string is less than any other string.
  4489. --| When comparing DocID strings, all of the name components are
  4490. --| compared before any of the version components are.  Thus:
  4491. --|-
  4492. --|     A(1) < A(2) < A(1).B < A(2).B < A(1).C < A(2).C
  4493. --|+
  4494. --| Reference strings are compared by first comparing their Document Id
  4495. --| strings, and, if equal, then comparing their Paragraph Id strings.
  4496.  
  4497. ------------------------------------------------------------------------
  4498.  
  4499. subtype Small_Num is INTEGER range 0 .. 255;
  4500.     -- used for discriminants which may sometimes be default
  4501.     -- initialized, and which need a good-sized name length
  4502.  
  4503.  
  4504. ------------------------------------------------------------------------
  4505.      ---------------- ParagraphID Strings ----------------
  4506. ------------------------------------------------------------------------
  4507.  
  4508. Invalid_ParagraphID_String:    --| Raised if a string does not correspond
  4509.     exception;            --| to the syntax for a ParagraphID
  4510.  
  4511. type ParagraphID_String(length : Small_Num := 0)
  4512.   is private;    --| String of the form: ( Number { '.' Number } )
  4513.  
  4514.  
  4515. function Image(   --| return string image of the paragraphid_string
  4516.     PS : in ParagraphID_String
  4517.     ) return STRING;
  4518.  
  4519. --| Effects: Convert a ParagraphID_String into an ordinary string.
  4520. --| N/A: Modifies, Errors, Raises, Requires
  4521.  
  4522.  
  4523. function Compare(    --| -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2
  4524.     S1 : in ParagraphID_String;
  4525.     S2 : in ParagraphID_String
  4526.     ) return INTEGER;
  4527.  
  4528. --| Effects: Compare S1 to S2 and return the "difference".
  4529. --| N/A: Modifies, Errors, Raises, Requires
  4530.  
  4531.  
  4532. function EQ(            --| Return TRUE iff S1 = S2
  4533.     S1 : in ParagraphID_String;
  4534.     S2 : in ParagraphID_String
  4535.     ) return BOOLEAN;
  4536.  
  4537. --| N/A: Raises, Modifies, Errors
  4538. --| Effects: Compare S1 to S2 and return TRUE if they are equal.
  4539.  
  4540.  
  4541. function "<"(            --| Return TRUE iff S1 < S2
  4542.     S1 : in ParagraphID_String;
  4543.     S2 : in ParagraphID_String
  4544.     ) return BOOLEAN;
  4545.  
  4546. --| N/A: Raises, Modifies, Errors
  4547. --| Effects: Compare S1 to S2 and return TRUE if S1 < S2
  4548.  
  4549.  
  4550. function ">"(            --| Return TRUE iff S1 > S2
  4551.     S1 : in ParagraphID_String;
  4552.     S2 : in ParagraphID_String
  4553.     ) return BOOLEAN;
  4554.  
  4555. --| N/A: Raises, Modifies, Errors
  4556. --| Effects: Compare S1 to S2 and return TRUE if S1 > S2
  4557.  
  4558.  
  4559. function "<="(            --| Return TRUE iff S1 <= S2
  4560.     S1 : in ParagraphID_String;
  4561.     S2 : in ParagraphID_String
  4562.     ) return BOOLEAN;
  4563.  
  4564. --| N/A: Raises, Modifies, Errors
  4565. --| Effects: Compare S1 to S2 and return TRUE if S1 <= S2
  4566.  
  4567.  
  4568. function ">="(            --| Return TRUE iff S1 >= S2
  4569.     S1 : in ParagraphID_String;
  4570.     S2 : in ParagraphID_String
  4571.     ) return BOOLEAN;
  4572.  
  4573. --| N/A: Raises, Modifies, Errors        
  4574. --| Effects: Compare S1 to S2 and return TRUE if S1 >= S2
  4575.  
  4576.  
  4577. ------------------------------------------------------------------------
  4578.         ---------------- DocID Strings ----------------
  4579. ------------------------------------------------------------------------
  4580.  
  4581. Invalid_DocID_String:        --| Raised if a string does not
  4582.     exception;            --| correspond to the syntax for a DocID
  4583.  
  4584. type DocID_String(length : Small_Num := 0) is private;
  4585. --| String of the form: Name [Version] { . Name [Version] }
  4586.  
  4587.  
  4588. function Image(            --| return string image of the docid_string   
  4589.     DS : in DocID_String
  4590.     ) return STRING;
  4591.  
  4592. --| Effects: Convert a DocID_String into human readable form.
  4593. --| N/A: Modifies, Errors, Raises, Requires
  4594.  
  4595.  
  4596. function Compare(    --| Return -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2
  4597.     S1 : in DocID_String;
  4598.     S2 : in DocID_String
  4599.     ) return INTEGER;
  4600.  
  4601. --| Effects: Return the "difference" between S1 and S2, ignoring upper/
  4602. --| lower case differences.
  4603. --| N/A: Modifies, Errors, Raises, Requires
  4604.  
  4605.  
  4606. function EQ(            --| Return TRUE iff S1 = S2
  4607.     S1 : in DocID_String;
  4608.     S2 : in DocID_String
  4609.     ) return BOOLEAN;
  4610.  
  4611. --| N/A: Raises, Modifies, Errors
  4612. --| Effects: Compare S1 to S2 and return TRUE if S1 = S2
  4613.  
  4614.  
  4615. function "<"(            --| Return TRUE iff S1 < S2
  4616.     S1 : in DocID_String;
  4617.     S2 : in DocID_String
  4618.     ) return BOOLEAN;
  4619.  
  4620. --| N/A: Raises, Modifies, Errors
  4621. --| Effects: Compare S1 to S2 and return TRUE if S1 < S2
  4622.  
  4623.  
  4624. function ">"(            --| Return TRUE iff S1 > S2
  4625.     S1 : in DocID_String;
  4626.     S2 : in DocID_String
  4627.     ) return BOOLEAN;
  4628.  
  4629. --| N/A: Raises, Modifies, Errors
  4630. --| Effects: Compare S1 to S2 and return TRUE if S1 > S2
  4631.  
  4632.  
  4633. function "<="(            --| Return TRUE iff S1 <= S2
  4634.     S1 : in DocID_String;
  4635.     S2 : in DocID_String
  4636.     ) return BOOLEAN;
  4637.  
  4638. --| N/A: Raises, Modifies, Errors
  4639. --| Effects: Compare S1 to S2 and return TRUE if S1 <= S2
  4640.  
  4641.  
  4642. function ">="(            --| Return TRUE iff S1 >= S2
  4643.     S1 : in DocID_String;
  4644.     S2 : in DocID_String
  4645.     ) return BOOLEAN;
  4646.  
  4647. --| N/A: Raises, Modifies, Errors
  4648. --| Effects: Compare S1 to S2 and return TRUE if S1 >= S2
  4649.  
  4650.  
  4651. ------------------------------------------------------------------------
  4652.       ---------------- Reference Strings ----------------
  4653. ------------------------------------------------------------------------
  4654.  
  4655. Invalid_Reference_String:    --| Raised if a string does not 
  4656.     exception;            --| correspond to the syntax for a
  4657.                 --| Reference
  4658.  
  4659. type Reference_String is private;
  4660. --| String of the form: DocID [ ParagraphID ]
  4661.  
  4662.  
  4663. procedure Scan(            --| Scan the string S starting at
  4664.                 --| S(Index) for a Reference
  4665.     S     : in     STRING;    --| String to scan
  4666.     Index : in out NATURAL;    --| Position where scan starts and ends
  4667.     RS    : in out Reference_String
  4668.     );
  4669.  
  4670. --| Raises: Invalid_Reference_String
  4671.  
  4672. --| Effects
  4673. --| Starting at S(Index), skip leading white space, and check for
  4674. --| sequence of names with optional version numbers separated by dots,
  4675. --| followed by an optional ParagraphID, leaving Index just past the
  4676. --| last number.  If a syntax error is detected during the scan, 
  4677. --| Index is unchanged and the exception Invalid_ParagraphID_String
  4678. --| or Invalid_DocID_String is raised.
  4679.  
  4680. --| N/A: Modifies, Errors
  4681.  
  4682.  
  4683. function Image(      --| return string image of a Reference_String
  4684.     RS : in Reference_String
  4685.     ) return STRING;
  4686.  
  4687. --| Effects: Convert a Reference_String into human-readable form.
  4688. --| N/A: Modifies, Errors, Raises, Requires
  4689.  
  4690.  
  4691. function Compare(
  4692.     S1 : in Reference_String;
  4693.     S2 : in Reference_String
  4694.     ) return INTEGER;
  4695.  
  4696. --| Effects: Return the "difference" between S1 and S2.
  4697. --| N/A: Modifies, Errors, Raises, Requires
  4698.  
  4699.  
  4700. procedure Split(        --| Splits the reference string
  4701.                 --| into DocID and ParagraphID
  4702.     RS: in Reference_String;    --| reference string
  4703.     DS: in out DocID_String;    --| DocID string
  4704.     PS: in out ParagraphID_String --| ParagraphID string
  4705.     );
  4706.  
  4707. --| Effects: Split RS into its component parts.
  4708. --| N/A: Modifies, Errors, Raises
  4709.  
  4710.  
  4711. procedure Join(            --| Joint DocID and ParagraphID
  4712.                 --| into a Reference string
  4713.     RS: in out Reference_String;    --| reference string
  4714.     DS: in DocID_String;        --| DocID string
  4715.     PS: in ParagraphID_String         --| ParagraphID string
  4716.     );
  4717.  
  4718. --| Effects: Join DS and PS into a single Reference_String RS.
  4719. --| N/A: Modifies, Errors, Raises
  4720.  
  4721. ------------------------------------------------------------------------
  4722.  
  4723. function EQ(            --| Return TRUE iff S1 = S2
  4724.     S1 : in Reference_String;
  4725.     S2 : in Reference_String
  4726.     ) return BOOLEAN;
  4727.  
  4728. --| N/A: Raises, Modifies, Errors
  4729. --| Effects: Compare S1 to S2 and return TRUE iff they are equal.
  4730.  
  4731.  
  4732. function "<"(            --| Return TRUE iff S1 < S2
  4733.     S1 : in Reference_String;
  4734.     S2 : in Reference_String
  4735.     ) return BOOLEAN;
  4736.  
  4737. --| N/A: Raises, Modifies, Errors
  4738. --| Effects: Compare S1 to S2 and return TRUE iff S1 < S2.
  4739.  
  4740.  
  4741. function ">"(            --| Return TRUE iff S1 > S2
  4742.     S1 : in Reference_String;
  4743.     S2 : in Reference_String
  4744.     ) return BOOLEAN;
  4745.  
  4746. --| N/A: Raises, Modifies, Errors
  4747. --| Effects: Compare S1 to S2 and return TRUE iff S1 > S2.
  4748.  
  4749.  
  4750. function "<="(            --| Return TRUE iff S1 <= S2
  4751.     S1 : in Reference_String;
  4752.     S2 : in Reference_String
  4753.     ) return BOOLEAN;
  4754.  
  4755. --| N/A: Raises, Modifies, Errors
  4756. --| Effects: Compare S1 to S2 and return TRUE iff S1 <= S2.
  4757.  
  4758.  
  4759. function ">="(            --| Return TRUE iff S1 >= S2
  4760.     S1 : in Reference_String;
  4761.     S2 : in Reference_String
  4762.     ) return BOOLEAN;
  4763.  
  4764. --| N/A: Raises, Modifies, Errors
  4765. --| Effects: Compare S1 to S2 and return TRUE iff S1 >= S2.
  4766.  
  4767. ------------------------------------------------------------------------
  4768.  
  4769. private
  4770.  
  4771. pragma inline(EQ, "<", "<=", ">", ">=");
  4772.  
  4773. type DottedNumber is access ParagraphID_String;
  4774.  
  4775. type ParagraphID_String(length : Small_Num := 0) is
  4776.     record            --| a linked list of number strings
  4777.     number_string : String(1..length);
  4778.     next : DottedNumber := null;
  4779.     end record;
  4780.  
  4781. subtype DottedNumberRecord is ParagraphID_String;
  4782.  
  4783. type NameList is access DocID_String;
  4784.  
  4785. type DocID_String(length : Small_Num := 0) is
  4786.     record            --| a linked list of names/versions
  4787.     name_string : String(1..length);
  4788.     version : DottedNumber := null;
  4789.     next : NameList := null;
  4790.     end record;
  4791.  
  4792. subtype NameListRecord is DocID_String;
  4793.  
  4794. type Reference_String is
  4795.     record            --| String of the form:
  4796.     doc_id : NameList;      --| DocID 
  4797.     par_id : DottedNumber;  --| ParagraphID
  4798.     end record;
  4799.  
  4800. end Document_Ref;
  4801. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4802. --DOCREF.BDY
  4803. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4804. with case_insensitive_string_comparison;
  4805.  
  4806. package body Document_Ref is
  4807.  
  4808.     package SC renames case_insensitive_string_comparison;
  4809.  
  4810.     BadReferenceString : exception;
  4811.  
  4812.     -- some character subtypes
  4813.     subtype Digit   is Character range '0' .. '9';
  4814.     subtype UC_Char is Character range 'A' .. 'Z';
  4815.     subtype LC_Char is Character range 'a' .. 'z';
  4816.  
  4817.     type TokenKind is (lparen, rparen, dot, number, name, eos);
  4818.     --| an enumeration of lexer tokens
  4819.  
  4820.     type TokenRecord(kind : TokenKind := eos; length : small_num := 0) is
  4821.     --| a lexical token structure
  4822.       record
  4823.     case kind is
  4824.     when number | name => String_value : STRING(1..length);
  4825.     when others => null;
  4826.     end case;
  4827.       end record;
  4828.  
  4829.     GlobalToken : TokenRecord;    -- our "lookahead" token
  4830.     -- lexical token constants used by lexer for efficiency
  4831.     LParenToken: constant TokenRecord
  4832.         := TokenRecord'(kind => lparen, length => 1);
  4833.     RParenToken: constant TokenRecord
  4834.         := TokenRecord'(kind => rparen, length => 1);
  4835.     DotToken: constant TokenRecord
  4836.         := TokenRecord'(kind => dot, length => 1);
  4837.     EOSToken: constant TokenRecord := TokenRecord'(kind => eos, length => 0);
  4838.  
  4839. pragma Page;
  4840.  
  4841. procedure GetNumberToken(  --| get a number type of lexical object
  4842.     Str : in STRING;
  4843.     Token : out TokenRecord
  4844.     )
  4845. is
  4846.     I : Natural := Str'first;
  4847.  
  4848. begin
  4849.     while I <= Str'last and then Str(I) in Digit loop
  4850.     I := I + 1;
  4851.     end loop;
  4852.     declare
  4853.     -- Adjust the index range in Token
  4854.       tempstr: STRING(1..I-Str'first) := Str(Str'first..I - 1);
  4855.     begin
  4856.       Token := TokenRecord'(kind => number,
  4857.                 length => I - Str'first,
  4858.                 String_value => tempStr);
  4859.     end;
  4860.  
  4861. end GetNumberToken;
  4862.  
  4863.  
  4864. procedure GetNameToken(  --| get a token whose lexical structure is
  4865.                      --| that of an Aa identifier
  4866.     Str : in STRING;
  4867.     Token : out TokenRecord
  4868.     )
  4869. is
  4870.     I : Natural := Str'first;
  4871.  
  4872. begin
  4873.     while I <= Str'last loop
  4874.     -- we know the first char is alphabetic, so the below case stmt is ok
  4875.     case Str(I) is
  4876.     when UC_Char | LC_Char | Digit =>
  4877.         null;
  4878.     when '_' =>
  4879.         -- Check for adjacent underscores
  4880.         if Str(I-1) = '_' then
  4881.             raise BadReferenceSTRING;
  4882.         end if;
  4883.     when others =>
  4884.         -- Cannot end with an underscore
  4885.         if Str(I-1) = '_' then
  4886.             raise BadReferenceSTRING;
  4887.         else
  4888.             exit;
  4889.         end if;
  4890.     end case;
  4891.     I := I + 1;
  4892.     end loop;
  4893.  
  4894.     declare
  4895.       -- Adjust index range of Token.String_Value
  4896.       tempstr: STRING(1..I-Str'first) := Str(Str'first..I - 1);
  4897.     begin
  4898.       Token := TokenRecord'(kind => name,
  4899.                 length => I - Str'first,
  4900.                 String_value => tempStr);
  4901.     end;
  4902.  
  4903. end GetNameToken;
  4904.  
  4905.  
  4906. procedure GetToken(   --| get the lexical token beginning at position
  4907.                   --| Index in STRING Str
  4908.     Str: in STRING;
  4909.     Index: in out Natural;
  4910.     Token: in out TokenRecord
  4911.     )
  4912. is
  4913.     I : Natural := Index;
  4914.     Last : Natural := Str'last;
  4915.  
  4916. begin
  4917.     while I <= Last and then (Str(I) = ' ' or str(i) = ascii.ht) loop
  4918.     -- skip blanks and tabs
  4919.     I := I + 1;
  4920.     end loop;
  4921.     Index := I;
  4922.     if I > Last then
  4923.     -- no more in Str
  4924.     Token := EOSToken;
  4925.     return;
  4926.     end if;
  4927.     case Str(I) is
  4928.       when '(' =>
  4929.     Token := LParenToken;
  4930.     Index := I + 1;
  4931.       when ')' =>
  4932.     Token := RParenToken;
  4933.     Index := I + 1;
  4934.       when '.' =>
  4935.     Token := DotToken;
  4936.     Index := I + 1;
  4937.       when Digit =>
  4938.     GetNumberToken(Str(I..Last), Token);
  4939.     Index := I + Token.length;
  4940.       when LC_Char | UC_Char =>
  4941.     GetNameToken(Str(I..Last), Token);
  4942.     Index := I + Token.length;
  4943.       when others =>    -- Terminate the scan
  4944.     Token := EOSToken;
  4945.     return;
  4946.     end case;
  4947. end GetToken;
  4948.  
  4949. ------------------------------------------------------------------------
  4950. -- Reference STRING parser
  4951. -- the main internal routines are GetName and GetDotNum. They
  4952. -- each assume that the first (lookahead) token is in GlobalToken,
  4953. -- and make the appropriate checks.
  4954.  
  4955. procedure GetDotNum(  --| parse a dotted number from Str beginning at Index
  4956.     Str: STRING;
  4957.     Index: in out Natural;
  4958.     DotNum: out DottedNumber
  4959.     )
  4960. is
  4961.     NumPtr : DottedNumber;
  4962. begin
  4963.     -- First check our lookahead token
  4964.     if GlobalToken.kind /= number then
  4965.     raise BadReferenceSTRING;
  4966.     else
  4967.     -- Initialize a dotted number record object 
  4968.     NumPtr := new DottedNumberRecord'(length => GlobalToken.length,
  4969.       Number_String => GlobalToken.String_value, next => null);
  4970.     DotNum := NumPtr;
  4971.     end if;
  4972.     -- See if we have more in the list (separated by dots)
  4973.     GetToken(Str, Index, GlobalToken);
  4974.     if GlobalToken.kind = dot then
  4975.     -- if so, set the "next" field of the list to be the remaining
  4976.     -- dotted number list
  4977.     GetToken(Str, Index, GlobalToken);
  4978.     GetDotNum(Str, Index, NumPtr.next);
  4979.     end if;
  4980.  
  4981. end GetDotNum;
  4982.  
  4983. procedure GetName(  --| parse a name structure in Str beginning at Index
  4984.     Str: in STRING;
  4985.     Index: in out Natural;
  4986.     NmList: out NameList
  4987.     )
  4988. is
  4989.     NamePtr: NameList;
  4990.     NumPtr: DottedNumber;
  4991.  
  4992. begin
  4993.     If GlobalToken.kind /= name then    -- check lookahead token
  4994.     raise BadReferenceSTRING;
  4995.     end if;
  4996.     -- Initialize the name record
  4997.     NamePtr := new NameListRecord'(Length => Globaltoken.length,
  4998.                    name_String => GlobalToken.String_value,
  4999.                    version => null,
  5000.                    next => null);
  5001.     NmList := NamePtr;
  5002.     GetToken(Str, Index, GlobalToken);
  5003.     -- check for version number
  5004.     if GlobalToken.kind = lparen then
  5005.     GetToken(Str, Index, GlobalToken);
  5006.     -- fill in the version field
  5007.     GetDotNum(Str, Index, NamePtr.version);
  5008.     if GlobalToken.kind /= rparen then
  5009.         raise BadReferenceSTRING;
  5010.     else
  5011.         GetToken(Str, Index, GlobalToken);
  5012.     end if;
  5013.     end if;
  5014.     -- check for more name elements separated by a dot
  5015.     if GlobalToken.kind = dot then
  5016.     GetToken(Str, Index, GlobalToken);
  5017.     -- fill in "next" field of name list if present
  5018.     GetName(Str, Index, NamePtr.next);
  5019.     end if;
  5020. end GetName;
  5021.  
  5022.  
  5023.       -------------- ParagraphID STRINGs ----------------
  5024.  
  5025. function Image(
  5026.     PS : in ParagraphID_String
  5027.     ) return STRING is
  5028. begin
  5029.     if PS.next = null then
  5030.     return PS.Number_String;
  5031.     else
  5032.     return PS.Number_String & "." & Image(PS.next.all);
  5033.     end if;
  5034. end Image;
  5035.  
  5036. -------------------------------------------------
  5037.  
  5038. function Compare(    --| -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2
  5039.     S1 : in ParagraphID_String;
  5040.     S2 : in ParagraphID_String
  5041.     ) return INTEGER
  5042. is
  5043.     S1V, S2V: integer;
  5044.  
  5045. begin
  5046.     if S1.Number_String /= "" then
  5047.     S1V := integer'value(S1.Number_String);
  5048.     else
  5049.     S1V := 0;
  5050.     end if;
  5051.     if S2.Number_String /= "" then
  5052.     S2V := integer'value(S2.Number_String);
  5053.     else
  5054.     S2V := 0;
  5055.     end if;
  5056.     if S1V < S2V then
  5057.     return -1;
  5058.     elsif S1V > S2V then
  5059.     return 1;
  5060.     elsif S1.next = null then
  5061.     -- Values were equal; compare next components
  5062.     if S2.next = null then
  5063.         return 0;
  5064.     else
  5065.         return -1;
  5066.     end if;
  5067.     elsif S2.next = null then
  5068.     return 1;
  5069.     else
  5070.     return Compare(S1.next.all, S2.next.all);
  5071.     end if;
  5072. end Compare;
  5073.  
  5074. -------------------------------------------------
  5075.  
  5076. function EQ(
  5077.     S1 : in ParagraphID_String;
  5078.     S2 : in ParagraphID_String
  5079.     ) return BOOLEAN is
  5080. begin
  5081.     return Compare(S1, S2) = 0;
  5082.  
  5083. end EQ;
  5084.  
  5085. -------------------------------------------------
  5086.  
  5087. function "<"(
  5088.     S1 : in ParagraphID_String;
  5089.     S2 : in ParagraphID_String
  5090.     ) return BOOLEAN is
  5091. begin
  5092.     return Compare(S1, S2) < 0;
  5093.  
  5094. end "<";
  5095.  
  5096. -------------------------------------------------
  5097.  
  5098. function ">"(
  5099.     S1 : in ParagraphID_String;
  5100.     S2 : in ParagraphID_String
  5101.     ) return BOOLEAN is
  5102. begin
  5103.     return Compare(S1, S2) > 0;
  5104.  
  5105. end ">";
  5106.  
  5107. -------------------------------------------------
  5108.  
  5109. function "<="(
  5110.     S1 : in ParagraphID_String;
  5111.     S2 : in ParagraphID_String
  5112.     ) return BOOLEAN is
  5113. begin
  5114.     return Compare(S1, S2) <= 0;
  5115.  
  5116. end "<=";
  5117.  
  5118. -------------------------------------------------
  5119.  
  5120. function ">="(
  5121.     S1 : in ParagraphID_String;
  5122.     S2 : in ParagraphID_String
  5123.     ) return BOOLEAN is
  5124. begin
  5125.     return Compare(S1, S2) >= 0;
  5126.  
  5127. end ">=";
  5128.  
  5129.  
  5130.         ---------------- DocID STRINGs ----------------
  5131.  
  5132. function Image(
  5133.     DS : in DocID_String
  5134.     ) return STRING is
  5135. begin
  5136.     if DS.next = null then
  5137.     if DS.version = null then
  5138.       return DS.name_String;
  5139.     else
  5140.       return DS.name_String & "("
  5141.           & Image(ParagraphID_String(DS.version.all)) & ")";
  5142.           -- needs explicit type coercion
  5143.     end if;
  5144.     else
  5145.     -- Catenate "next" list of images to first one
  5146.     if DS.version = null then
  5147.         return DS.name_String & "." & Image(DS.next.all);
  5148.     else
  5149.         return DS.name_String & "(" &
  5150.           Image(ParagraphID_String(DS.version.all)) & ")" &
  5151.           "." & Image(DS.next.all);
  5152.     end if;
  5153.     end if;
  5154. end Image;
  5155.  
  5156. -------------------------------------------------
  5157.  
  5158. function CompareNames(  --| compare the name fields (not versions)
  5159.                     --| of two DocID STRINGs
  5160.     S1 : in DocID_String;
  5161.     S2 : in DocID_String
  5162.     ) return INTEGER
  5163. is
  5164.     diff: integer := SC.Compare(S1.Name_String, S2.Name_String);
  5165.  
  5166. begin
  5167.     if diff = 0 then    --| STRINGs were equal: compare next component
  5168.     if S1.next = null then
  5169.       if S2.next = null then
  5170.         return 0;
  5171.       end if;
  5172.       return -1;
  5173.     elsif S2.next = null then
  5174.       return 1;
  5175.     else
  5176.       return CompareNames(S1.next.all, S2.next.all);
  5177.     end if;
  5178.     else
  5179.     return diff;
  5180.     end if;
  5181. end CompareNames;
  5182.  
  5183. function CompareVersions(  --| compare the versions of two DocID STRINGs
  5184.     S1 : in DocID_String;
  5185.     S2 : in DocID_String
  5186.     ) return INTEGER is
  5187.     C : INTEGER;
  5188. begin
  5189.     -- This routine is only called if the name parts of a ParagraphID_String
  5190.     -- are equal, and therefore have the same number of components. This
  5191.     -- fact is used often below, and is commented appropriately.
  5192.     if S1.version = null then
  5193.     if S2.version = null then
  5194.         if S1.next = null then
  5195.         -- we know that S2.next is also null (else CompareNames
  5196.         -- would be non-zero, and we would not have been called)
  5197.             return 0;
  5198.         else
  5199.         -- by similar reasoning, we know S2 is not null in this case
  5200.             return CompareVersions(S1.next.all, S2.next.all);
  5201.         end if;
  5202.     else
  5203.         return -1;
  5204.     end if;
  5205.     elsif S2.version = null then
  5206.     return 1;
  5207.     else
  5208.     C := Compare(ParagraphID_String(S1.version.all),
  5209.              ParagraphID_String(S2.version.all));
  5210.     -- note that this calls the paragraph_id comparison
  5211.     if C /= 0 or else S1.next = null then
  5212.         return C;
  5213.     else
  5214.         -- again, they are both non-null
  5215.         return CompareVersions(S1.next.all, S2.next.all);
  5216.     end if;
  5217.     end if;
  5218. end CompareVersions;
  5219.  
  5220. function Compare(    --| -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2
  5221.     S1 : in DocID_String;
  5222.     S2 : in DocID_String
  5223.     ) return INTEGER
  5224. is
  5225.     C : INTEGER := CompareNames(S1, S2);
  5226.  
  5227. begin
  5228.     if C /= 0 then
  5229.     return C;
  5230.     else
  5231.     return CompareVersions(S1, S2);
  5232.     end if;
  5233.  
  5234. end Compare;
  5235.  
  5236. -------------------------------------------------
  5237.  
  5238. function EQ(
  5239.     S1 : in DocID_String;
  5240.     S2 : in DocID_String
  5241.     ) return BOOLEAN is
  5242. begin
  5243.     return Compare(S1, S2) = 0;
  5244.  
  5245. end EQ;
  5246.  
  5247. -------------------------------------------------
  5248.  
  5249. function "<"(
  5250.     S1 : in DocID_String;
  5251.     S2 : in DocID_String
  5252.     ) return BOOLEAN is
  5253. begin
  5254.     return Compare(S1, S2) < 0;
  5255.  
  5256. end "<";
  5257.  
  5258. -------------------------------------------------
  5259.  
  5260. function ">"(
  5261.     S1 : in DocID_String;
  5262.     S2 : in DocID_String
  5263.     ) return BOOLEAN is
  5264. begin
  5265.     return Compare(S1, S2) > 0;
  5266.  
  5267. end ">";
  5268.  
  5269. -------------------------------------------------
  5270.  
  5271. function "<="(
  5272.     S1 : in DocID_String;
  5273.     S2 : in DocID_String
  5274.     ) return BOOLEAN is
  5275. begin
  5276.     return Compare(S1, S2) <= 0;
  5277.  
  5278. end "<=";
  5279.  
  5280. -------------------------------------------------
  5281.  
  5282. function ">="(
  5283.     S1 : in DocID_String;
  5284.     S2 : in DocID_String
  5285.     ) return BOOLEAN is
  5286. begin
  5287.     return Compare(S1, S2) >= 0;
  5288.  
  5289. end ">=";
  5290.  
  5291.  
  5292.       ---------------- Reference STRINGs ----------------
  5293.  
  5294. procedure Scan(
  5295.     S     : in     STRING;
  5296.     Index : in out natural;
  5297.     RS    : in out Reference_String
  5298.     )
  5299. is
  5300.     IndexSave : Natural := Index;  --| in case of a misformed Reference_String
  5301.  
  5302. begin
  5303.     -- First get the lookahead token prepared
  5304.     begin
  5305.     GetToken(S, Index, GlobalToken);
  5306.     if GlobalToken.Kind /= Name then
  5307.       Index := IndexSave;
  5308.       raise Invalid_DocID_String;
  5309.     end if;
  5310.     GetName(S, Index, RS.doc_id);
  5311.     exception
  5312.       when BadReferenceSTRING =>
  5313.     Index := IndexSave;
  5314.     raise Invalid_DocID_String;
  5315.     end;
  5316.     begin
  5317.     GetDotNum(S, Index, RS.par_id);
  5318.     exception
  5319.       when BadReferenceSTRING =>
  5320.     Index := IndexSave;
  5321.     raise Invalid_ParagraphID_String;
  5322.     end;
  5323.     -- Gets here if scan is successful. Back up from the lookahead token.
  5324.     Index := Index - GlobalToken.length;
  5325.  
  5326. end Scan;
  5327.  
  5328. -------------------------------------------------
  5329.  
  5330. function Image(
  5331.     RS : in Reference_String
  5332.     ) return STRING is
  5333. begin
  5334.     return Image(RS.doc_id.all) & ' ' & Image(RS.par_id.all);
  5335. end Image;
  5336.  
  5337. -------------------------------------------------
  5338.  
  5339. procedure Split(
  5340.     RS : in     Reference_String;
  5341.     DS : in out DocID_String;
  5342.     PS : in out ParagraphID_String
  5343.     ) is
  5344. begin
  5345.     DS := RS.doc_id.all;
  5346.     PS := RS.par_id.all;
  5347. end Split;
  5348.  
  5349. -------------------------------------------------
  5350.  
  5351. procedure Join(
  5352.     RS : in out Reference_String;
  5353.     DS : in     DocID_String;
  5354.     PS : in     ParagraphID_String
  5355.     ) is
  5356. begin
  5357.     RS.doc_id := new DocID_String'(DS);
  5358.     RS.par_id := new ParagraphID_String'(PS);
  5359. end Join;
  5360.  
  5361. -------------------------------------------------
  5362.  
  5363. function Compare(
  5364.     S1 : in Reference_String;
  5365.     S2 : in Reference_String
  5366.     ) return INTEGER is
  5367.     C1 : INTEGER := Compare(S1.doc_id.all, S2.doc_id.all);
  5368. begin
  5369.     if C1 /= 0 then
  5370.     return C1;
  5371.     else
  5372.     return Compare(S1.par_id.all, S2.par_id.all);
  5373.     end if;
  5374. end Compare;
  5375.  
  5376. -------------------------------------------------
  5377.  
  5378. function EQ(
  5379.     S1 : in Reference_String;
  5380.     S2 : in Reference_String
  5381.     ) return BOOLEAN is
  5382. begin
  5383.     return Compare(S1, S2) = 0;
  5384. end EQ;
  5385.  
  5386. -------------------------------------------------
  5387.  
  5388. function "<"(
  5389.     S1 : in Reference_String;
  5390.     S2 : in Reference_String
  5391.     ) return BOOLEAN is
  5392. begin
  5393.     return Compare(S1, S2) < 0;
  5394. end "<";
  5395.  
  5396. -------------------------------------------------
  5397.  
  5398. function ">"(
  5399.     S1 : in Reference_String;
  5400.     S2 : in Reference_String
  5401.     ) return BOOLEAN is
  5402. begin
  5403.     return Compare(S1, S2) > 0;
  5404. end ">";
  5405.  
  5406. -------------------------------------------------
  5407.  
  5408. function "<="(
  5409.     S1 : in Reference_String;
  5410.     S2 : in Reference_String
  5411.     ) return BOOLEAN is
  5412. begin
  5413.     return Compare(S1, S2) <= 0;
  5414. end "<=";
  5415.  
  5416. -------------------------------------------------
  5417.  
  5418. function ">="(
  5419.     S1 : in Reference_String;
  5420.     S2 : in Reference_String
  5421.     ) return BOOLEAN is
  5422. begin
  5423.     return Compare(S1, S2) >= 0;
  5424. end ">=";
  5425.  
  5426. -------------------------------------------------
  5427.  
  5428. end Document_Ref;
  5429. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5430. --STRING.SPC
  5431. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5432. -- $Source: /nosc/work/abstractions/string/RCS/string.spc,v $
  5433. -- $Revision: 1.1 $ -- $Date: 85/01/10 17:51:46 $ -- $Author: ron $
  5434.  
  5435. -- $Source: /nosc/work/abstractions/string/RCS/string.spc,v $
  5436. -- $Revision: 1.1 $ -- $Date: 85/01/10 17:51:46 $ -- $Author: ron $
  5437.  
  5438. package string_pkg is
  5439.  
  5440. --| Overview:
  5441. --| Package string_pkg exports an abstract data type, string_type.  A
  5442. --| string_type value is a sequence of characters.  The values have arbitrary
  5443. --| length.  For a value, s, with length, l, the individual characters are
  5444. --| numbered from 1 to l.  These values are immutable; characters cannot be
  5445. --| replaced or appended in a destructive fashion.  
  5446. --|
  5447. --| In the documentation for this package, we are careful to distinguish 
  5448. --| between string_type objects, which are Ada objects in the usual sense, 
  5449. --| and string_type values, the members of this data abstraction as described
  5450. --| above.  A string_type value is said to be associated with, or bound to,
  5451. --| a string_type object after an assignment (:=) operation.  
  5452. --| 
  5453. --| The operations provided in this package fall into three categories: 
  5454. --|
  5455. --| 1. Constructors:  These functions typically take one or more string_type
  5456. --|      objects as arguments.  They work with the values associated with 
  5457. --|      these objects, and return new string_type values according to 
  5458. --|      specification.  By a slight abuse of language, we will sometimes 
  5459. --|      coerce from string_type objects to values for ease in description.
  5460. --|
  5461. --| 2. Heap Management:   
  5462. --|      These operations (make_persistent, flush, mark, release) control the
  5463. --|      management of heap space.  Because string_type values are
  5464. --|      allocated on the heap, and the type is not limited, it is necessary
  5465. --|      for a user to assume some responsibility for garbage collection.  
  5466. --|      String_type is not limited because of the convenience of
  5467. --|      the assignment operation, and the usefulness of being able to 
  5468. --|      instantiate generic units that contain private type formals.  
  5469. --|      ** Important: To use this package properly, it is necessary to read
  5470. --|      the descriptions of the operations in this section.
  5471. --|
  5472. --| 3. Queries:  These functions return information about the values 
  5473. --|      that are associated with the argument objects.  The same conventions 
  5474. --|      for description of operations used in (1) is adopted.
  5475. --| 
  5476. --| A note about design decisions...  The decision to not make the type 
  5477. --| limited causes two operations to be carried over from the representation.
  5478. --| These are the assignment operation, :=, and the "equality" operator, "=".
  5479. --| See the discussion at the beginning of the Heap Management section for a 
  5480. --| discussion of :=.
  5481. --| See the spec for the first of the equal functions for a discussion of "=".
  5482. --| 
  5483. --| The following is a complete list of operations, written in the order
  5484. --| in which they appear in the spec.  Overloaded subprograms are followed
  5485. --| by (n), where n is the number of subprograms of that name.
  5486. --|
  5487. --| 1. Constructors:
  5488. --|        create
  5489. --|        "&" (3)
  5490. --|        substr
  5491. --|        splice
  5492. --|        insert (3)
  5493. --|        lower (2) 
  5494. --|        upper (2)
  5495. --| 2. Heap Management:
  5496. --|        make_persistent (2)
  5497. --|        flush
  5498. --|        mark, release
  5499. --| 3. Queries:
  5500. --|        is_empty
  5501. --|        length
  5502. --|        value
  5503. --|        fetch
  5504. --|       set_comparison_option
  5505. --|       get_comparison_option
  5506. --|        equal (3)
  5507. --|        "<" (3), 
  5508. --|       "<=" (3)
  5509. --|        match_c
  5510. --|        match_not_c
  5511. --|        match_s (2)
  5512. --|        match_any (2)
  5513. --|        match_none (2)
  5514.  
  5515. --| Notes:
  5516. --| Programmer: Ron Kownacki
  5517.  
  5518.     type string_type is private;
  5519.  
  5520.     bounds:          exception;  --| Raised on index out of bounds.
  5521.     any_empty:       exception;  --| Raised on incorrect use of match_any.
  5522.     illegal_alloc:   exception;  --| Raised by value creating operations.
  5523.     illegal_dealloc: exception;  --| Raised by release.
  5524.     
  5525.     
  5526. -- Constructors:
  5527.  
  5528.     function create(s: string)
  5529.         return string_type;
  5530.  
  5531.       --| Raises: illegal_alloc
  5532.       --| Effects:
  5533.       --| Return a value consisting of the sequence of characters in s.
  5534.       --| Sometimes useful for array or record aggregates.
  5535.       --| Raises illegal_alloc if string space has been improperly
  5536.       --| released.  (See procedures mark/release.)
  5537.  
  5538.     function "&"(s1, s2: string_type)
  5539.         return string_type;
  5540.  
  5541.       --| Raises: illegal_alloc
  5542.       --| Effects:
  5543.       --| Return the concatenation of s1 and s2.
  5544.       --| Raises illegal_alloc if string space has been improperly
  5545.       --| released.  (See procedures mark/release.)
  5546.  
  5547.     function "&"(s1: string_type; s2: string)
  5548.         return string_type;
  5549.  
  5550.       --| Raises: illegal_alloc
  5551.       --| Effects:
  5552.       --| Return the concatenation of s1 and create(s2).
  5553.       --| Raises illegal_alloc if string space has been improperly
  5554.       --| released.  (See procedures mark/release.)
  5555.  
  5556.     function "&"(s1: string; s2: string_type)
  5557.         return string_type;
  5558.  
  5559.       --| Raises: illegal_alloc
  5560.       --| Effects:
  5561.       --| Return the concatenation of create(s1) and s2.
  5562.       --| Raises illegal_alloc if string space has been improperly
  5563.       --| released.  (See procedures mark/release.)
  5564.  
  5565.     function substr(s: string_type; i: positive; len: natural)
  5566.     return string_type;
  5567.   
  5568.       --| Raises: bounds, illegal_alloc
  5569.       --| Effects:
  5570.       --| Return the substring, of specified length, that occurs in s at
  5571.       --| position i.  If len = 0, then returns the empty value.  
  5572.       --| Otherwise, raises bounds if either i or (i + len - 1)
  5573.       --| is not in 1..length(s).
  5574.       --| Raises illegal_alloc if string space has been improperly
  5575.       --| released.  (See procedures mark/release.)
  5576.   
  5577.     function splice(s: string_type; i: positive; len: natural)
  5578.     return string_type;
  5579.   
  5580.       --| Raises: bounds, illegal_alloc
  5581.       --| Effects:
  5582.       --| Let s be the string, abc, where a, b and c are substrings.  If
  5583.       --| substr(s, i, length(b)) = b, for some i in 1..length(s), then
  5584.       --| splice(s, i, length(b)) = ac.  
  5585.       --| Returns a value equal to s if len = 0.  Otherwise, raises bounds if
  5586.       --| either i or (i + len - 1) is not in 1..length(s).
  5587.       --| Raises illegal_alloc if string space has been improperly
  5588.       --| released.  (See procedures mark/release.)
  5589.   
  5590.     function insert(s1, s2: string_type; i: positive)
  5591.     return string_type;
  5592.   
  5593.       --| Raises: bounds, illegal_alloc
  5594.       --| Effects:
  5595.       --| Return substr(s1, 1, i - 1) & s2 & substr(s1, i, length(s1)).
  5596.       --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  5597.       --| exception is raised by insert.
  5598.       --| Raises bounds if i is not in 1..length(s1) + 1.
  5599.       --| Raises illegal_alloc if string space has been improperly
  5600.       --| released.  (See procedures mark/release.)
  5601.  
  5602.     function insert(s1: string_type; s2: string; i: positive)
  5603.     return string_type;
  5604.   
  5605.       --| Raises: bounds, illegal_alloc
  5606.       --| Effects:
  5607.       --| Return substr(s1, 1, i - 1) & s2 & substr(s1, i, length(s1)).
  5608.       --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  5609.       --| exception is raised by insert.
  5610.       --| Raises bounds if i is not in 1..length(s1) + 1.
  5611.       --| Raises illegal_alloc if string space has been improperly
  5612.       --| released.  (See procedures mark/release.)
  5613.       
  5614.     function insert(s1: string; s2: string_type; i: positive)
  5615.     return string_type;
  5616.   
  5617.       --| Raises: bounds, illegal_alloc
  5618.       --| Effects:
  5619.       --| Return s1(s1'first..i - 1) & s2 & s1(i..s1'last).
  5620.       --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  5621.       --| exception is raised by insert.
  5622.       --| Raises bounds if i is not in s'first..s'last + 1.
  5623.       --| Raises illegal_alloc if string space has been improperly
  5624.       --| released.  (See procedures mark/release.)
  5625.       
  5626.     function lower(s: string)
  5627.     return string_type;
  5628.   
  5629.       --| Raises: illegal_alloc
  5630.       --| Effects:
  5631.       --| Return a value that contains exactly those characters in s with
  5632.       --| the exception that all upper case characters are replaced by their 
  5633.       --| lower case counterparts.
  5634.       --| Raises illegal_alloc if string space has been improperly
  5635.       --| released.  (See procedures mark/release.)
  5636.  
  5637.     function lower(s: string_type)
  5638.     return string_type;
  5639.   
  5640.       --| Raises: illegal_alloc
  5641.       --| Effects:
  5642.       --| Return a value that is a copy of s with the exception that all
  5643.       --| upper case characters are replaced by their lower case counterparts.
  5644.       --| Raises illegal_alloc if string space has been improperly
  5645.       --| released.  (See procedures mark/release.)
  5646.  
  5647.     function upper(s: string)
  5648.     return string_type;
  5649.   
  5650.       --| Raises: illegal_alloc
  5651.       --| Effects:
  5652.       --| Return a value that contains exactly those characters in s with
  5653.       --| the exception that all lower case characters are replaced by their 
  5654.       --| upper case counterparts.
  5655.       --| Raises illegal_alloc if string space has been improperly
  5656.       --| released.  (See procedures mark/release.)
  5657.  
  5658.     function upper(s: string_type)
  5659.     return string_type;
  5660.   
  5661.       --| Raises: illegal_alloc
  5662.       --| Effects:
  5663.       --| Return a value that is a copy of s with the exception that all
  5664.       --| lower case characters are replaced by their upper case counterparts.
  5665.       --| Raises illegal_alloc if string space has been improperly
  5666.       --| released.  (See procedures mark/release.)
  5667.       
  5668.  
  5669. -- Heap Management (including object/value binding):
  5670. --
  5671. -- Two forms of heap management are provided.  The general scheme is to "mark"
  5672. -- the current state of heap usage, and to "release" in order to reclaim all
  5673. -- space that has been used since the last mark.  However, this alone is 
  5674. -- insufficient because it is frequently desirable for objects to remain 
  5675. -- associated with values for longer periods of time, and this may come into 
  5676. -- conflict with the need to clean up after a period of "string hacking."
  5677. -- To deal with this problem, we introduce the notions of "persistent" and
  5678. -- "nonpersistent" values.
  5679. --
  5680. -- The nonpersistent values are those that are generated by the constructors 
  5681. -- in the previous section.  These are claimed by the release procedure.
  5682. -- Persistent values are generated by the two make_persistent functions
  5683. -- described below.  These values must be disposed of individually by means of
  5684. -- the flush procedure.  
  5685. --
  5686. -- This allows a description of the meaning of the ":=" operation.  For a 
  5687. -- statement of the form, s := expr, where expr is a string_type expression, 
  5688. -- the result is that the value denoted/created by expr becomes bound to the
  5689. -- the object, s.  Assignment in no way affects the persistence of the value.
  5690. -- If expr happens to be an object, then the value associated  with it will be
  5691. -- shared.  Ideally, this sharing would not be visible, since values are
  5692. -- immutable.  However, the sharing may be visible because of the memory
  5693. -- management, as described below.  Programs which depend on such sharing are 
  5694. -- erroneous.
  5695.    
  5696.     function make_persistent(s: string_type) 
  5697.     return string_type; 
  5698.  
  5699.       --| Effects: 
  5700.       --| Returns a persistent value, v, containing exactly those characters in
  5701.       --| value(s).  The value v will not be claimed by any subsequent release.
  5702.       --| Only an invocation of flush will claim v.  After such a claiming
  5703.       --| invocation of flush, the use (other than :=) of any other object to 
  5704.       --| which v was bound is erroneous, and program_error may be raised for
  5705.       --| such a use.
  5706.  
  5707.     function make_persistent(s: string) 
  5708.     return string_type; 
  5709.  
  5710.       --| Effects: 
  5711.       --| Returns a persistent value, v, containing exactly those chars in s.
  5712.       --| The value v will not be claimed by any subsequent release.
  5713.       --| Only an invocation of flush will reclaim v.  After such a claiming
  5714.       --| invocation of flush, the use (other than :=) of any other object to 
  5715.       --| which v was bound is erroneous, and program_error may be raised for
  5716.       --| such a use.
  5717.     
  5718.     procedure flush(s: in out string_type);
  5719.     
  5720.       --| Effects:
  5721.       --| Return heap space used by the value associated with s, if any, to 
  5722.       --| the heap.  s becomes associated with the empty value.  After an
  5723.       --| invocation of flush claims the value, v, then any use (other than :=)
  5724.       --| of an object to which v was bound is erroneous, and program_error 
  5725.       --| may be raised for such a use.
  5726.       --| 
  5727.       --| This operation should be used only for persistent values.  The mark 
  5728.       --| and release operations are used to deallocate space consumed by other
  5729.       --| values.  For example, flushing a nonpersistent value implies that a
  5730.       --| release that tries to claim this value will be erroneous, and
  5731.       --| program_error may be raised for such a use.
  5732.  
  5733.     procedure mark;
  5734.  
  5735.       --| Effects:
  5736.       --| Marks the current state of heap usage for use by release.  
  5737.       --| An implicit mark is performed at the beginning of program execution.
  5738.  
  5739.     procedure release;
  5740.  
  5741.       --| Raises: illegal_dealloc
  5742.       --| Effects:
  5743.       --| Releases all heap space used by nonpersistent values that have been
  5744.       --| allocated since the last mark.  The values that are claimed include
  5745.       --| those bound to objects as well as those produced and discarded during
  5746.       --| the course of general "string hacking."  If an invocation of release
  5747.       --| claims a value, v, then any subsequent use (other than :=) of any 
  5748.       --| other object to which v is bound is erroneous, and program_error may
  5749.       --| be raised for such a use.
  5750.       --|
  5751.       --| Raises illegal_dealloc if the invocation of release does not balance
  5752.       --| an invocation of mark.  It is permissible to match the implicit
  5753.       --| initial invocation of mark.  However, subsequent invocations of 
  5754.       --| constructors will raise the illegal_alloc exception until an 
  5755.       --| additional mark is performed.  (Anyway, there is no good reason to 
  5756.       --| do this.)  In any case, a number of releases matching the number of
  5757.       --| currently active marks is implicitly performed at the end of program
  5758.       --| execution.
  5759.       --|
  5760.       --| Good citizens generally perform their own marks and releases
  5761.       --| explicitly.  Extensive string hacking without cleaning up will 
  5762.       --| cause your program to run very slowly, since the heap manager will
  5763.       --| be forced to look hard for chunks of space to allocate.
  5764.       
  5765. -- Queries:
  5766.       
  5767.     function is_empty(s: string_type)
  5768.         return boolean;
  5769.  
  5770.       --| Effects:
  5771.       --| Return true iff s is the empty sequence of characters.
  5772.  
  5773.     function length(s: string_type)
  5774.         return natural;
  5775.  
  5776.       --| Effects:
  5777.       --| Return number of characters in s.
  5778.  
  5779.     function value(s: string_type)
  5780.         return string;
  5781.  
  5782.       --| Effects:
  5783.       --| Return a string, s2, that contains the same characters that s
  5784.       --| contains.  The properties, s2'first = 1 and s2'last = length(s),
  5785.       --| are satisfied.  This implies that, for a given string, s3,
  5786.       --| value(create(s3))'first may not equal s3'first, even though
  5787.       --| value(create(s3)) = s3 holds.  Thus, "content equality" applies
  5788.       --| although the string objects may be distinguished by the use of
  5789.       --| the array attributes.
  5790.  
  5791.     function fetch(s: string_type; i: positive)
  5792.         return character;
  5793.  
  5794.       --| Raises: bounds
  5795.       --| Effects:
  5796.       --| Return the ith character in s.  Characters are numbered from
  5797.       --| 1 to length(s).  Raises bounds if i not in 1..length(s).
  5798.  
  5799.  
  5800.     type comparison_option is (case_sensitive, case_insensitive);
  5801.  
  5802.     --| Used for equal, "<" and "<=" functions.  If the comparison_option
  5803.     --| is case_sensitive, then a straightforward comparison of values
  5804.     --| is performed.  If the option is case_insensitive, then comparison
  5805.     --| between the arguments is performed after first normalizing them to
  5806.     --| lower case.
  5807.  
  5808.     procedure set_comparison_option(choice: comparison_option);
  5809.  
  5810.     --| Effects: 
  5811.     --| Set the comparison option for equal, "<" and "<="  (as described
  5812.     --| above) to the given choice.  The initial setting is case_sensitive.
  5813.  
  5814.     function get_comparison_option
  5815.     return comparison_option;
  5816.  
  5817.     --| Effects: 
  5818.     --| Return the current comparison_option setting.
  5819.  
  5820.     function equal(s1, s2: string_type)
  5821.         return boolean;
  5822.  
  5823.       --| Effects:
  5824.       --| Value equality relation; return true iff length(s1) = length(s2)
  5825.       --| and, for all i in 1..length(s1), fetch(s1, i) = fetch(s2, i).
  5826.       --| (If the comparison_option is currently case_insensitive, then 
  5827.       --| lower(s1) and lower(s2) are used instead.)
  5828.       --| 
  5829.       --| Notes:
  5830.       --| The "=" operation is carried over from the representation.
  5831.       --| It allows one to distinguish among the heap addresses of
  5832.       --| string_type values.  Even "equal" values under case_sensitive 
  5833.       --| comparison may not be "=", although s1 = s2 implies equal(s1, s2).
  5834.       --| There is no reason to use "=".
  5835.  
  5836.     function equal(s1: string_type; s2: string)
  5837.         return boolean;
  5838.  
  5839.       --| Effects:
  5840.       --| Return equal(s1, create(s2)).
  5841.  
  5842.     function equal(s1: string; s2: string_type)
  5843.         return boolean;
  5844.  
  5845.       --| Effects:
  5846.       --| Return equal(create(s1), s2).
  5847.  
  5848.     function "<"(s1, s2: string_type)
  5849.         return boolean; 
  5850.  
  5851.       --| Effects: 
  5852.       --| Lexicographic comparison according to the current comparison_option;
  5853.       --| return value(s1) < value(s2).
  5854.  
  5855.     function "<"(s1: string_type; s2: string)
  5856.         return boolean; 
  5857.  
  5858.       --| Effects: 
  5859.       --| Lexicographic comparison according to the current comparison_option;
  5860.       --| return value(s1) < s2.
  5861.  
  5862.     function "<"(s1: string; s2: string_type)
  5863.         return boolean; 
  5864.  
  5865.       --| Effects: 
  5866.       --| Lexicographic comparison according to the current comparison_option;
  5867.       --| return s1 < value(s2).
  5868.  
  5869.     function "<="(s1, s2: string_type)
  5870.         return boolean; 
  5871.  
  5872.       --| Effects: 
  5873.       --| Lexicographic comparison according to the current comparison_option;
  5874.       --| return value(s1) <= value(s2).
  5875.  
  5876.     function "<="(s1: string_type; s2: string)
  5877.         return boolean; 
  5878.  
  5879.       --| Effects: 
  5880.       --| Lexicographic comparison according to the current comparison_option;
  5881.       --| return value(s1) <= s2.
  5882.  
  5883.     function "<="(s1: string; s2: string_type)
  5884.         return boolean; 
  5885.  
  5886.       --| Effects: 
  5887.       --| Lexicographic comparison according to the current comparison_option;
  5888.       --| return s1 <= value(s2).
  5889.  
  5890.     function match_c(s: string_type; c: character; start: positive := 1)
  5891.         return natural;
  5892.  
  5893.       --| Effects:
  5894.       --| Return the minimum index, i in start..length(s), such that
  5895.       --| fetch(s, i) = c.  Returns 0 if no such i exists, 
  5896.       --| including the case where is_empty(s).
  5897.  
  5898.     function match_not_c(s: string_type; c: character; start: positive := 1)
  5899.         return natural;
  5900.   
  5901.       --| Effects:
  5902.       --| Return the minimum index, i in start..length(s), such that
  5903.       --| fetch(s, i) /= c.  Returns 0 if no such i exists,
  5904.       --| including the case where is_empty(s).
  5905.  
  5906.     function match_s(s1, s2: string_type; start: positive := 1)
  5907.         return natural;
  5908.  
  5909.       --| Effects:
  5910.       --| Return the minimum index, i, in start..length(s1), such that,
  5911.       --| for all j in 1..length(s2), fetch(s2, j) = fetch(s1, i + j - 1).
  5912.       --| This is the position of the substring, s2, in s1.
  5913.       --| Returns 0 if no such i exists, including the cases
  5914.       --| where is_empty(s1) or is_empty(s2).
  5915.       --| Note that equal(substr(s1, match_s(s1, s2, i), length(s2)), s2)
  5916.       --| holds, providing that match_s does not raise an exception.
  5917.  
  5918.     function match_s(s1: string_type; s2: string; start: positive := 1)
  5919.         return natural;
  5920.  
  5921.       --| Effects:
  5922.       --| Return the minimum index, i, in start..length(s1), such that,
  5923.       --| for all j in s2'range, s2(j) = fetch(s1, i + j - 1).
  5924.       --| This is the position of the substring, s2, in s1.
  5925.       --| Returns 0 if no such i exists, including the cases
  5926.       --| where is_empty(s1) or s2 = "".
  5927.       --| Note that equal(substr(s1, match_s(s1, s2, i), s2'length), s2)
  5928.       --| holds, providing that match_s does not raise an exception.
  5929.  
  5930.     function match_any(s, any: string_type; start: positive := 1)
  5931.         return natural;
  5932.  
  5933.       --| Raises: any_empty
  5934.       --| Effects:
  5935.       --| Return the minimum index, i in start..length(s), such that
  5936.       --| fetch(s, i) = fetch(any, j), for some j in 1..length(any).
  5937.       --| Raises any_empty if is_empty(any).
  5938.       --| Otherwise, returns 0 if no such i exists, including the case
  5939.       --| where is_empty(s).
  5940.  
  5941.  
  5942.     function match_any(s: string_type; any: string; start: positive := 1)
  5943.         return natural;
  5944.  
  5945.       --| Raises: any_empty
  5946.       --| Effects:
  5947.       --| Return the minimum index, i, in start..length(s), such that
  5948.       --| fetch(s, i) = any(j), for some j in any'range.
  5949.       --| Raises any_empty if any = "".
  5950.       --| Otherwise, returns 0 if no such i exists, including the case
  5951.       --| where is_empty(s).
  5952.  
  5953.     function match_none(s, none: string_type; start: positive := 1)
  5954.         return natural;
  5955.  
  5956.       --| Effects:
  5957.       --| Return the minimum index, i in start..length(s), such that
  5958.       --| fetch(s, i) /= fetch(none, j) for each j in 1..length(none).
  5959.       --| If (not is_empty(s)) and is_empty(none), then i is 1.
  5960.       --| Returns 0 if no such i exists, including the case
  5961.       --| where is_empty(s).
  5962.  
  5963.     function match_none(s: string_type; none: string; start: positive := 1)
  5964.         return natural;
  5965.  
  5966.       --| Effects:
  5967.       --| Return the minimum index, i in start..length(s), such that
  5968.       --| fetch(s, i) /= none(j) for each j in none'range.
  5969.       --| If not is_empty(s) and none = "", then i is 1.
  5970.       --| Returns 0 if no such i exists, including the case
  5971.       --| where is_empty(s).
  5972.  
  5973.  
  5974. private
  5975.  
  5976.     type string_type is access string;
  5977.  
  5978.       --| Abstract data type, string_type, is a constant sequence of chars
  5979.       --| of arbitrary length.  Representation type is access string.
  5980.       --| It is important to distinguish between an object of the rep type
  5981.       --| and its value; for an object, r, val(r) denotes the value.
  5982.       --|
  5983.       --| Representation Invariant:  I: rep --> boolean
  5984.       --| I(r: rep) = (val(r) = null) or else
  5985.       --|             (val(r).all'first = 1 &
  5986.       --|              val(r).all'last >= 0 &
  5987.       --|              (for all r2, val(r) = val(r2) /= null => r is r2))
  5988.       --|
  5989.       --| Abstraction Function:  A: rep --> string_type
  5990.       --| A(r: rep) = if r = null then
  5991.       --|                 the empty sequence
  5992.       --|             elsif r'last = 0 then  
  5993.       --|                 the empty sequence
  5994.       --|             else
  5995.       --|                 the sequence consisting of r(1),...,r(r'last).
  5996.  
  5997. end string_pkg;
  5998. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5999. --SLISTS.SPC
  6000. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6001. with String_Pkg;
  6002. with Lists;
  6003.  
  6004. package String_Lists is new Lists(
  6005.         ItemType => String_Pkg.String_Type,
  6006.         Equal    => String_Pkg.Equal);
  6007.  
  6008. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6009. --FILEMGR.SPC
  6010. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6011. with String_Lists;
  6012.  
  6013. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6014. --         * * * * * * * * * *  WARNING  * * * * * * * * * *               --
  6015. --    THE BODY OF THIS PACKAGE IS HOST DEPENDENT THEREFORE NOT PORTABLE    --
  6016. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6017.  
  6018. package File_Manager is
  6019.  
  6020. --| The File_Manager package provides procedures to manipulate files
  6021. --| in a file system under a given operating system.
  6022.                                                                     pragma page;
  6023. --| Overview
  6024. --| The File_Manager provides routines to manipulate closed files.
  6025. --| It provides procedures to rename, copy, move, delete and expand
  6026. --| a name containing wild card characters to a list of filenames.
  6027.  
  6028. --| N/A: Raises, Effects, Requires, Modifies, Errors
  6029.                                                                     pragma page;
  6030.             -- Packages --
  6031.  
  6032. package SL renames String_Lists;
  6033.  
  6034.              -- Types --
  6035.  
  6036. type Mode_Type is(
  6037.     FULL,            --| Full path name
  6038.     NO_VERSION,        --| Path name without version number
  6039.     NO_DIRECTORY,        --| File and version number
  6040.     FILE_ONLY,        --| File
  6041.     NAME_ONLY,        --| File name (without extention)
  6042.     TYPE_ONLY);        --| File type (eg. .ADA)
  6043.  
  6044.             -- Exceptions --
  6045.  
  6046. Delete_Error: exception;    --| raised when unable to delete a file
  6047. Device_Not_Ready: exception;    --| raised when device is not ready
  6048. Device_Write_Locked: exception;    --| raised when device is write locked
  6049. Directory_Not_Found: exception;    --| raised when unable to find the directory
  6050. Date_Error: exception;        --| raised on error when getting file date
  6051. Expand_Error: exception;    --| raised when name expansion error occurs
  6052. File_Already_Exists: exception;    --| raised when a file already exists
  6053. File_Locked: exception;        --| raised when file is locked
  6054. File_Name_Error: exception;    --| raised when the file name is too long
  6055. File_Not_Found: exception;    --| raised when the file is not found
  6056. Input_File_Error: exception;    --| raised when unable to read a file to copy
  6057. Output_File_Error: exception;    --| raised when unable to write a new file
  6058. Parse_Error: exception;        --| raised when parsing error 
  6059. Privilege_Violation: exception;    --| raised when privilege violation is detected
  6060. Rename_Error: exception;    --| raised on error during rename operation
  6061. Create_Error: exception;    --| raised when directory creation failed
  6062.                                                                     pragma page;
  6063.  
  6064.             -- Operations --
  6065.  
  6066. ----------------------------------------------------------------    
  6067.  
  6068. procedure Rename(        --| rename a file in the file system
  6069.     Old_File: in STRING;    --| name the file presently has
  6070.     New_File: in STRING        --| new name to give to the file
  6071.     );
  6072.  
  6073. --| Raises: Device_Not_Ready, Directory_Not_Found, File_Not_Found,
  6074. --| Parse_Error, Privilege_Violation, Rename_Error
  6075.  
  6076. --| Effects: If possible, the file specified by Old_File is renamed to the
  6077. --| name specified by New_File.  The content of the file is not changed.
  6078. --| If any error occurs, the appropriate exception is raised.
  6079.  
  6080. --| N/A: Errors, Requires, Modifies
  6081.                                                                     pragma page;
  6082. ----------------------------------------------------------------    
  6083.  
  6084. procedure Delete(        --| deletes the named file
  6085.     File: in STRING        --| name of the file to be deleted
  6086.     );
  6087.  
  6088. --| Raises: Delete_Error, Device_Not_Ready, Device_Write_Locked,
  6089. --| Directory_Not_Found, Parse_Error, Privilege_Violation
  6090.  
  6091. --| Effects: Deletes the named file from the file system.
  6092.  
  6093. --| N/A: Errors, Modifies, Requires
  6094.                                                                     pragma page;
  6095. ----------------------------------------------------------------    
  6096.  
  6097. procedure Copy(            --| copy one file to another.
  6098.     Input_File: in STRING;    --| name of the old file
  6099.     Output_File: in STRING    --| name of the file to copy it into
  6100.     );
  6101.  
  6102. --| Raises: Device_Not_Ready, Device_Write_Locked, Directory_Not_Found,
  6103. --| File_Already_Exists, File_Locked, File_Not_Found, Parse_Error,
  6104. --| Input_File_Error, Output_File_Error, Privilege_Violation
  6105.  
  6106. --| Effects:
  6107. --| Copies Input_File to Output_File.  The contents of the output file
  6108. --| are identical to the contents of the Input_File.
  6109.  
  6110. --| N/A: Errors, Requires, Modifies
  6111.                                                                     pragma page;
  6112. ----------------------------------------------------------------    
  6113.  
  6114. procedure Append(        --| Appends a file to another file
  6115.     Input_File: in STRING;    --| File to append
  6116.     Append_File: in STRING    --| File to be appended
  6117.     );
  6118.  
  6119. --| Raises: Device_Not_Ready, Device_Write_Locked, Directory_Not_Found,
  6120. --| File_Already_Exists, File_Locked, File_Not_Found, Parse_Error,
  6121. --| Input_File_Error, Output_File_Error, Privilege_Violation
  6122.  
  6123. --| Effects:  The contents of Append_File is appended to Input_File.
  6124. --| Append_File is not changed by this operation.
  6125.  
  6126. --| N/A: Errors, Raises, Modifies
  6127.                                                                     pragma page;
  6128. ----------------------------------------------------------------    
  6129.  
  6130. function creation_Date(    --| Return the creation date of a file
  6131.     File: in STRING    --| Name of a file
  6132.     ) return STRING; --| Raises: File_Not_Found
  6133.  
  6134. --| Effects: Return a string containing the date and time that File
  6135. --| was created in the form "mm/dd/yy hh:mm:ss.cc".
  6136.  
  6137. --| N/A: Modifies, Requires
  6138.  
  6139. ----------------------------------------------------------------    
  6140.  
  6141. function modification_Date(    --| Return the modification date of a file
  6142.     File: in STRING        --| Name of a file
  6143.     ) return STRING; --| Raises: File_Not_Found
  6144.  
  6145. --| Effects: Return a string containing the date and time that File
  6146. --| was last modified in the form "mm/dd/yy hh:mm:ss.cc".
  6147.  
  6148. --| N/A: Modifies, Requires
  6149.  
  6150.  
  6151. ----------------------------------------------------------------    
  6152.  
  6153. function Expand(        --| Expands a name containing wild card
  6154.                 --| to a full filename
  6155.     File: in STRING;        --| string to be expanded
  6156.     Mode: in Mode_Type := FULL    --| filename expansion mode
  6157.     ) return SL.List;
  6158.  
  6159. --| Raises: Device_Not_Ready, Directory_Not_Found, Expand_Error,
  6160. --| File_Not_Found, Parse_Error
  6161.  
  6162. --| Effects: Expands a string into a list of filenames matching all wild
  6163. --| card characters that occur in File.  In the event that no files match,
  6164. --| a null list is returned.
  6165.  
  6166. --| N/A: Errors, Modifies, Requires
  6167.                                                                     pragma page;
  6168. ----------------------------------------------------------------    
  6169.  
  6170. procedure Destroy(
  6171.     Name_List: in out SL.List
  6172.     );
  6173.  
  6174.  
  6175. --| Effects: All storage associated with the given list is released.
  6176. --| This function is provided for reclaiming any storage allocated to lists
  6177. --| of file names created by other functions in this package.  
  6178.  
  6179. --| N/A: Errors, Modifies, Requires, Raises
  6180.                                                                     pragma page;
  6181. ----------------------------------------------------------------    
  6182.  
  6183. function Strip_Dir(
  6184.     Long_Name: in STRING
  6185.     ) return STRING;
  6186.  
  6187. --| Raises:
  6188.  
  6189. --| Effects: Strips the device and directory name off of Long_Name
  6190.  
  6191. --| N/A: Errors, Modifies, Requires
  6192.                                                                     pragma page;
  6193. ----------------------------------------------------------------    
  6194.  
  6195. function Parse_Filename(    --| parse a filename
  6196.     Name: in STRING;        --| filename to be parsed
  6197.     Mode: in Mode_Type := FULL    --| filename parsing mode
  6198.     ) return STRING;
  6199.  
  6200. --| Effects: Parse Name and return file specification according to Mode
  6201.  
  6202. --| N/A: Raises, Errors, Requires, Modifies
  6203.                                                                     pragma page;
  6204. ----------------------------------------------------------------    
  6205.  
  6206. function Path_Name(        --| Find path name for a file
  6207.     Directory: in STRING;        --| Device/directory specification
  6208.     File: in STRING;            --| File name
  6209.     Absolute: in BOOLEAN := FALSE    --| Absolute or relative path name
  6210.     ) return STRING;
  6211.  
  6212. --| Raises: Device_Not_Ready, Directory_Not_Found, Privilege_Violation,
  6213. --| Parse_Error
  6214.  
  6215. --| Effects: Returns the system dependent path name
  6216. --| Useful hint: Path_Name with directory as a null directory ([] in VMS)
  6217. --|              and file as a null string "" and Absoulte = TRUE will
  6218. --|              return the current dirctory name
  6219. --|
  6220.  
  6221. --| N/A: Errors, Requires, Modifies
  6222.                                                                     pragma page;
  6223. ----------------------------------------------------------------    
  6224.  
  6225. procedure Create_Directory(    --| Create a new directory
  6226.     Directory: in STRING    --| Name of directory to be created
  6227.     );
  6228.  
  6229. --| Raises: Create_Error
  6230.  
  6231. --| Effects: Creates a new directory.  If an error occurs, the exception
  6232. --| Create_Error is raised.
  6233.  
  6234. --| N/A: Errors, Modifies, Requires
  6235.                                                                     pragma page;
  6236. ----------------------------------------------------------------    
  6237.  
  6238. function Is_Directory(        --| Return TRUE iff Directory exists
  6239.     Directory: in STRING
  6240.     ) return BOOLEAN;
  6241.  
  6242. --| Raises: Device_Not_Ready, Device_Write_Locked, Parse_Error
  6243.  
  6244. --| Effects: Returns TRUE if the named directory exists, FALSE otherwise.
  6245.  
  6246. --| N/A: Errors, Modifies, Requires
  6247.  
  6248. ----------------------------------------------------------------    
  6249.  
  6250.  
  6251. end  File_Manager;
  6252. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6253. --FILEMGR.BDY
  6254. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6255. with System;            use System;     -- for =
  6256. with Starlet;
  6257. with Condition_Handling;
  6258. with System;
  6259. with String_Pkg;
  6260.  
  6261. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6262. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6263. --         * * * * * * * * * *  WARNING  * * * * * * * * * *               --
  6264. --           DEPENDS ON VAX/VMS SYSTEM INTERFACE PACKAGES                  -- 
  6265. --        WILL NOT PORT TO OTHER SYSTEMS WITHOUT MODIFICATIONS             --
  6266. --         * * * * * * * * * *  WARNING  * * * * * * * * * *               --
  6267. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6268. --=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--
  6269.  
  6270. package body File_Manager is
  6271.  
  6272. package SP renames String_Pkg;
  6273. package CH  renames Condition_Handling;
  6274. package SYS renames System;
  6275. package STR renames Starlet;
  6276.  
  6277. subtype File_String is STRING (1 .. 255);
  6278.                                                                     pragma page;
  6279. -----------------------------------------------------------------------------
  6280.  
  6281. procedure Raise_Error (
  6282.     STS : SYS.Unsigned_Longword
  6283.     ) is
  6284.  
  6285. begin
  6286.  
  6287.     case STS is
  6288.     when STR.RMS_DNF =>
  6289.         raise Directory_Not_Found;
  6290.     when STR.RMS_DNR =>
  6291.         raise Device_Not_Ready;
  6292.     when STR.RMS_FEX =>
  6293.         raise File_Already_Exists;
  6294.     when STR.RMS_FLK =>
  6295.         raise File_Locked;
  6296.     when STR.RMS_FNF =>
  6297.         raise File_Not_Found;
  6298.     when STR.RMS_PRV =>
  6299.         raise Privilege_Violation;
  6300.     when STR.RMS_WLK =>
  6301.         raise Device_Write_Locked;
  6302.     when others =>
  6303.         null;
  6304.     end case;
  6305.  
  6306. end Raise_Error;
  6307.                                                                     pragma page;
  6308. -----------------------------------------------------------------------------
  6309.  
  6310. procedure Set_FAB_NAM (
  6311.     File  : in     STRING;
  6312.     FAB   : in out STR.FAB_Type;
  6313.     NAM   : in out STR.NAM_Type;
  6314.     ES    : in out File_String
  6315.     ) is
  6316.  
  6317.     Status : CH.Cond_Value_Type;
  6318.     From   : INTEGER;
  6319.     To     : INTEGER;
  6320.  
  6321. begin
  6322.  
  6323.     if File'length > 255 then
  6324.     raise File_Name_Error;
  6325.     end if;
  6326.     FAB     := STR.FAB_Type_Init;
  6327.     FAB.FNA := File'address;
  6328.     FAB.FNS := SYS.Unsigned_Byte(File'length);
  6329.     FAB.NAM := NAM'address;
  6330.  
  6331.     NAM     := STR.NAM_Type_Init;
  6332.     NAM.ESA := ES'address;
  6333.     NAM.ESS := SYS.Unsigned_Byte(ES'length);
  6334.  
  6335.     STR.Parse(Status, FAB);
  6336.     if CH.Success(Status) then
  6337.     FAB.FOP.NAM := TRUE;
  6338.     return;
  6339.     end if;
  6340.  
  6341.     Raise_Error(FAB.STS);
  6342.     raise Parse_Error;
  6343.  
  6344. end Set_FAB_NAM;
  6345.                                                                     pragma page;
  6346. -----------------------------------------------------------------------------
  6347.  
  6348. procedure Copy_Append (    
  6349.     File1 : in STRING;
  6350.     File2 : in STRING;
  6351.     CIF   : in BOOLEAN
  6352.     ) is
  6353.  
  6354.     FAB1    : STR.FAB_Type;
  6355.     NAM1    : STR.NAM_Type;
  6356.     RAB1    : STR.RAB_Type;
  6357.     ES1     : File_String;
  6358.     FAB2    : STR.FAB_Type;
  6359.     NAM2    : STR.NAM_Type;
  6360.     RAB2    : STR.RAB_Type;
  6361.     ES2     : File_String;
  6362.     Buffer  : STRING (1 .. 1024);
  6363.     Status  : CH.Cond_Value_Type;
  6364.  
  6365. begin
  6366.  
  6367.     Set_FAB_NAM(File => File1, FAB => FAB1, NAM => NAM1, ES => ES1);
  6368.     FAB1.FAC.GET := TRUE;
  6369.     STR.Open(Status, FAB1);
  6370.     if not CH.Success(Status) then
  6371.     Raise_Error(FAB1.STS);
  6372.     raise Input_File_Error;
  6373.     end if;
  6374.  
  6375.     RAB1     := STR.RAB_Type_Init;
  6376.     RAB1.FAB := FAB1'address;
  6377.     RAB1.MBF := 2;
  6378.     RAB1.ROP.RAH := TRUE;
  6379.     STR.Connect(Status, RAB1);
  6380.     if not CH.Success(Status) then
  6381.     raise Input_File_Error;
  6382.     end if;
  6383.     RAB1.UBF := Buffer'address;
  6384.     RAB1.USZ := SYS.Unsigned_Word(Buffer'length);
  6385.  
  6386.     Set_FAB_NAM(File => File2, FAB => FAB2, NAM => NAM2, ES => ES2);
  6387.     FAB2.FAC.PUT := TRUE;
  6388.     FAB2.FOP.CTG := TRUE;
  6389.     FAB2.FOP.CIF := CIF;
  6390.     FAB2.RAT.CR  := TRUE;
  6391.     STR.Create(Status, FAB2);
  6392.     if not CH.Success(Status) then
  6393.     Raise_Error(FAB2.STS);
  6394.     raise Output_File_Error;
  6395.     end if;
  6396.     RAB2 := STR.RAB_Type_Init;
  6397.     RAB2.FAB := FAB2'address;
  6398.     RAB2.MBF := 2;
  6399.     RAB2.ROP.EOF := CIF;
  6400.     RAB2.ROP.WBH := TRUE;
  6401.     STR.Connect(Status, RAB2);
  6402.     if not CH.Success(Status) then
  6403.     raise Output_File_Error;
  6404.     end if;
  6405.  
  6406.     Read_Write: loop
  6407.     STR.Get(Status, RAB1);
  6408.     if CH.Success(Status) then
  6409.         RAB2.ROP.TPT := TRUE;
  6410.         RAB2.RBF := RAB1.RBF;
  6411.         RAB2.RSZ := RAB1.RSZ;
  6412.         STR.Put(Status, RAB2);
  6413.         if not CH.Success(Status) then
  6414.         Raise_Error(RAB2.STS);
  6415.         raise Output_File_Error;
  6416.         end if;
  6417.     else
  6418.         if RAB1.STS = STR.RMS_EOF then
  6419.         exit Read_Write;
  6420.         end if;
  6421.         Raise_Error(RAB1.STS);
  6422.         raise Input_File_Error;
  6423.     end if;
  6424.     end loop Read_Write;
  6425.  
  6426.     STR.Close(Status, FAB1);
  6427.     if not CH.Success(Status) then
  6428.     Raise_Error(FAB1.STS);
  6429.     raise Input_File_Error;
  6430.     end if;
  6431.  
  6432.     STR.Close(Status, FAB2);
  6433.     if not CH.Success(Status) then
  6434.     Raise_Error(FAB2.STS);
  6435.     raise Output_File_Error;
  6436.     end if;
  6437.  
  6438. end Copy_Append;
  6439.                                                                     pragma page;
  6440. -----------------------------------------------------------------------------
  6441.             -- Visible Operations --
  6442. -----------------------------------------------------------------------------
  6443.  
  6444. procedure Rename (
  6445.     Old_File : in STRING;
  6446.     New_File : in STRING
  6447.     ) is
  6448.  
  6449.     Old_FAB : STR.FAB_Type;
  6450.     Old_NAM : STR.NAM_Type;
  6451.     Old_ES  : File_String;
  6452.     Old_RS  : File_String;
  6453.     New_FAB : STR.FAB_Type;
  6454.     New_NAM : STR.NAM_Type;
  6455.     New_ES  : File_String; 
  6456.     New_RS  : File_String; 
  6457.     Status  : CH.Cond_Value_Type;
  6458.  
  6459. begin
  6460.  
  6461.     Set_FAB_NAM(File => Old_File, FAB => Old_FAB, NAM => Old_NAM, ES => Old_ES);
  6462.     Old_NAM.RSA := Old_RS'address; 
  6463.     Old_NAM.RSS := SYS.Unsigned_Byte(Old_RS'length);
  6464.  
  6465.     Set_FAB_NAM(File => New_File, FAB => New_FAB, NAM => New_NAM, ES => New_ES);
  6466.     New_NAM.RSA := New_RS'address; 
  6467.     New_NAM.RSS := SYS.Unsigned_Byte(New_RS'length);
  6468.  
  6469.     STR.Rename(Status, OldFAB => Old_FAB, NewFAB => New_FAB);
  6470.     if CH.Success(Status) then
  6471.     return;
  6472.     end if;
  6473.  
  6474.     Raise_Error(Old_FAB.STS);
  6475.     raise Rename_Error;
  6476.  
  6477. end Rename;
  6478.                                                                     pragma page;
  6479. -----------------------------------------------------------------------------
  6480.  
  6481. procedure Delete (
  6482.     File : in STRING
  6483.     ) is
  6484.  
  6485.     FAB    : STR.FAB_Type;
  6486.     NAM    : STR.NAM_Type;
  6487.     ES     : File_String;
  6488.     RS     : File_String;
  6489.     FABX   : STR.FAB_Type;
  6490.     NAMX   : STR.NAM_Type;
  6491.     ESX    : File_String;
  6492.     Status : CH.Cond_Value_Type;
  6493.     Error  : BOOLEAN := FALSE;
  6494.  
  6495. begin
  6496.  
  6497.     Set_FAB_NAM(File => File, FAB => FAB, NAM => NAM, ES => ES);
  6498.     FAB.IFI := STR.FAB_IFI_Type_Init;
  6499.     NAM.RSA := RS'address; 
  6500.     NAM.RSS := Unsigned_Byte(RS'length);
  6501.  
  6502.     loop
  6503.     STR.Search(Status, FAB);
  6504.     if CH.Success(Status) then
  6505.         Set_FAB_NAM(File => RS(1 .. NATURAL(NAM.RSL)),
  6506.             FAB  => FABX,
  6507.             NAM  => NAMX,
  6508.             ES => ESX);
  6509.         STR.Erase(Status, FAB);
  6510.         if not CH.Success(Status) then
  6511.         Error := TRUE;
  6512.         end if;
  6513.     else
  6514.         if FAB.STS = STR.RMS_FNF then
  6515.         raise File_Not_Found;
  6516.         elsif FAB.STS = STR.RMS_NMF then
  6517.         exit;
  6518.         end if;
  6519.         Error := TRUE;
  6520.     end if;
  6521.     end loop;
  6522.     if Error then
  6523.     raise Delete_Error;
  6524.     end if;
  6525.  
  6526. end Delete;
  6527.                                                                     pragma page;
  6528. -----------------------------------------------------------------------------
  6529.  
  6530. procedure Copy (
  6531.     Input_File  : in STRING;
  6532.     Output_File : in STRING
  6533.     ) is
  6534.  
  6535. begin
  6536.  
  6537.     Copy_Append(File1 => Input_File,
  6538.         File2 => Output_File,
  6539.         CIF   => FALSE);
  6540.  
  6541. end Copy;
  6542.                                                                     pragma page;
  6543. -----------------------------------------------------------------------------
  6544.  
  6545. procedure Append (
  6546.     Input_File  : in STRING;
  6547.     Append_File : in STRING
  6548.     ) is
  6549.  
  6550. begin
  6551.  
  6552.     Copy_Append(File1 => Input_File,
  6553.         File2 => Append_File,
  6554.         CIF   => TRUE);
  6555.  
  6556. end Append;
  6557.                                                                     pragma page;
  6558. -----------------------------------------------------------------------------
  6559.  
  6560. function Parse_Line (
  6561.     Line : in STRING;
  6562.     Mode : in Mode_Type:= FULL
  6563.     ) return STRING is
  6564.  
  6565.     Index1 : INTEGER;
  6566.     Index2 : INTEGER;
  6567.  
  6568. begin
  6569.  
  6570.     case Mode is
  6571.     when NO_DIRECTORY | FILE_ONLY | NAME_ONLY | TYPE_ONLY =>
  6572.         for i in Line'range loop
  6573.         if Line(i) = ']' then
  6574.             Index1 := i + 1;
  6575.             exit;
  6576.         end if;
  6577.         end loop;
  6578.         if Mode = TYPE_ONLY then
  6579.         for i in Index1 .. Line'last loop
  6580.             if Line(i) = '.' then
  6581.             Index1 := i + 1;
  6582.             exit;
  6583.             end if;
  6584.         end loop;
  6585.         end if;
  6586.     when others =>
  6587.         Index1 := Line'first;
  6588.     end case;
  6589.     case Mode is
  6590.     when NO_VERSION | FILE_ONLY | NAME_ONLY | TYPE_ONLY =>
  6591.         for i in reverse Line'range loop
  6592.         if Line(i) = ';' then
  6593.             Index2 := i - 1;
  6594.             exit;
  6595.         end if;
  6596.         end loop;
  6597.         if Mode = NAME_ONLY then
  6598.         for i in reverse 1 .. Index2 loop
  6599.             if Line(i) = '.' then
  6600.             Index2 := i - 1;
  6601.             exit;
  6602.             end if;
  6603.         end loop;
  6604.         end if;
  6605.     when others =>
  6606.         Index2 := Line'last;
  6607.     end case;
  6608.     return Line(Index1 .. Index2);
  6609.  
  6610. end Parse_Line;
  6611.  
  6612. -----------------------------------------------------------------------------
  6613.  
  6614. function creation_Date(    --| Return the creation date of a file
  6615.     File: in STRING    --| Name of a file
  6616.     ) return STRING --| Raises: File_Not_Found
  6617.  
  6618. is
  6619.     use Starlet;
  6620.     fab: fab_type := fab_type_init;         -- file access block
  6621.     xab: xab_type(xab_c_dat) := xabdat_init;    -- date xab
  6622.     status: condition_handling.cond_value_type;
  6623.     date_time_buffer: String(1..64);
  6624.     date_time_length: system.unsigned_word;
  6625.  
  6626. begin
  6627.     -- initialize fab fields
  6628.     fab.fna := file'address;
  6629.     fab.fns := file'length;
  6630.     fab.xab := xab'address;    
  6631.     -- open file to fill access blocks
  6632.     open(status, fab);
  6633.     if not condition_handling.success(status) then
  6634.         -- you could condition_handling.signal(status);
  6635.         raise File_Not_Found;
  6636.     end if;
  6637.  
  6638.     -- convert time quadword
  6639.     -- xab.cdt = creation date
  6640.     -- xab.dat_rdt = revision date
  6641.     --
  6642.     asctim(status, date_time_length, date_time_buffer, xab.cdt);
  6643.     if not condition_handling.success(status) then
  6644.         -- you could condition_handling.signal(status);
  6645.         close(status, fab);
  6646.         raise Date_Error;
  6647.     end if;
  6648.     close(status, fab); -- check status if you want
  6649.     return date_time_buffer(1..integer(date_time_length));
  6650. end creation_Date;
  6651.  
  6652.  
  6653. ----------------------------------------------------------------    
  6654.  
  6655. function modification_Date(    --| Return the modification date of a file
  6656.     File: in STRING        --| Name of a file
  6657.     ) return STRING --| Raises: File_Not_Found
  6658.  
  6659. --| Effects: Return a string containing the date and time that File
  6660. --| was last modified in the form "mm/dd/yy hh:mm:ss.cc".
  6661. is
  6662.     use Starlet;
  6663.     fab: fab_type := fab_type_init;         -- file access block
  6664.     xab: xab_type(xab_c_dat) := xabdat_init;    -- date xab
  6665.     status: condition_handling.cond_value_type;
  6666.     date_time_buffer: String(1..64);
  6667.     date_time_length: system.unsigned_word;
  6668.  
  6669. begin
  6670.     -- initialize fab fields
  6671.     fab.fna := file'address;
  6672.     fab.fns := file'length;
  6673.     fab.xab := xab'address;    
  6674.     -- open file to fill access blocks
  6675.     open(status, fab);
  6676.     if not condition_handling.success(status) then
  6677.         -- you could condition_handling.signal(status);
  6678.         raise File_Not_Found;
  6679.     end if;
  6680.  
  6681.     -- convert time quadword
  6682.     -- xab.cdt = creation date
  6683.     -- xab.dat_rdt = revision date
  6684.     --
  6685.     asctim(status, date_time_length, date_time_buffer, xab.dat_rdt);
  6686.     if not condition_handling.success(status) then
  6687.         -- you could condition_handling.signal(status);
  6688.         close(status, fab);
  6689.         raise Date_Error;
  6690.     end if;
  6691.     close(status, fab); -- check status if you want
  6692.     return date_time_buffer(1..integer(date_time_length));
  6693.  
  6694. end modification_Date;
  6695.  
  6696.  
  6697. ----------------------------------------------------------------    
  6698.  
  6699. function Expand (
  6700.     File : in STRING;
  6701.     Mode : in Mode_Type := FULL
  6702.     ) return SL.List is
  6703.  
  6704.     FAB      : STR.FAB_Type;
  6705.     NAM      : STR.NAM_Type;
  6706.     ES       : File_String;
  6707.     RS       : File_String;
  6708.     Status   : CH.Cond_Value_Type;
  6709.     Files    : SL.List;
  6710.     New_List : BOOLEAN := TRUE;
  6711.  
  6712. begin
  6713.  
  6714.     Set_FAB_NAM(File => File, FAB => FAB, NAM => NAM, ES => ES);
  6715.     FAB.IFI := STR.FAB_IFI_Type_Init;
  6716.     NAM.RSA := RS'address; 
  6717.     NAM.RSS := SYS.Unsigned_Byte(RS'length);
  6718.  
  6719.     SP.Mark;
  6720.     loop
  6721.     STR.Search(Status, FAB);
  6722.     if CH.Success(Status) then
  6723.         if New_List then
  6724.         Files := SL.Create;
  6725.         New_List := FALSE;
  6726.         end if;
  6727.         SL.Attach(Files, SP.Make_Persistent(Parse_Line(RS(1 .. INTEGER(NAM.RSL)), Mode)));
  6728.     else
  6729.         if FAB.STS = STR.RMS_NMF then
  6730.         return Files;
  6731.         end if;
  6732.         Raise_Error(FAB.STS);
  6733.         raise Expand_Error;
  6734.     end if;
  6735.     end loop;
  6736.     SP.Release;
  6737.  
  6738. end Expand;
  6739.                                                                     pragma page;
  6740. -----------------------------------------------------------------------------
  6741.  
  6742. procedure Destroy (
  6743.     Name_List : in out SL.List
  6744.     ) is
  6745.  
  6746.     Iterator : SL.ListIter;
  6747.     Name     : SP.String_Type;
  6748.  
  6749. begin
  6750.  
  6751.     Iterator := SL.MakeListIter(Name_List);
  6752.     while (SL.More(Iterator)) loop
  6753.     SL.Next(Iterator, Name);
  6754.     SP.Flush(Name);
  6755.     end loop;
  6756.     SL.Destroy(Name_List);
  6757.  
  6758. end Destroy;
  6759.                                                                     pragma page;
  6760. -----------------------------------------------------------------------------
  6761.  
  6762. function Strip_Dir (
  6763.     Long_Name : in STRING
  6764.     ) return STRING is
  6765.  
  6766. begin
  6767.  
  6768.     for N in Long_Name'First..Long_Name'Last loop
  6769.     if Long_Name(N) = ']' then
  6770.         declare
  6771.         R: constant string(1..Long_Name'Last - N)
  6772.             := Long_Name(N+1..Long_Name'Last);
  6773.         begin
  6774.         return R;
  6775.         end;
  6776.     end if;
  6777.     end loop;
  6778.     return Long_Name;
  6779.  
  6780. end Strip_Dir;
  6781.                                                                     pragma page;
  6782. -----------------------------------------------------------------------------
  6783.  
  6784. function Parse_Filename (
  6785.     Name : in STRING;
  6786.     Mode : in Mode_Type := FULL
  6787.     ) return STRING is
  6788.  
  6789.     FAB    : STR.FAB_Type;
  6790.     NAM    : STR.NAM_Type;
  6791.     ES     : File_String;
  6792.  
  6793. begin
  6794.  
  6795.     Set_FAB_NAM(File => Name, FAB => FAB, NAM => NAM, ES => ES);
  6796.     return Parse_Line(ES(1 .. INTEGER(NAM.ESL)), Mode);
  6797.  
  6798. end Parse_Filename;
  6799.                                                                     pragma page;
  6800. -----------------------------------------------------------------------------
  6801.  
  6802. procedure Check_Directory_Format(
  6803.     Directory : in STRING
  6804.     ) is
  6805.  
  6806. begin
  6807.  
  6808.     if Directory'Length < 2 then
  6809.     raise Parse_Error;
  6810.     end if;
  6811.     if Directory(Directory'last) /= ']' then
  6812.     raise Parse_Error;
  6813.     end if;
  6814.     for i in Directory'range loop
  6815.     if Directory(i) = '[' then
  6816.         return;
  6817.     end if;
  6818.     end loop;
  6819.     raise Parse_Error;
  6820.  
  6821. end Check_Directory_Format;
  6822.  
  6823. -----------------------------------------------------------------------------
  6824.  
  6825. function Path_Name(
  6826.     Directory : in STRING;
  6827.     File      : in STRING;
  6828.     Absolute  : in BOOLEAN := FALSE
  6829.     ) return STRING is
  6830.  
  6831.     FAB      : STR.FAB_Type;
  6832.     NAM      : STR.NAM_Type;
  6833.     ES       : File_String;
  6834.     RS       : File_String;
  6835.     Relative : BOOLEAN := FALSE;
  6836.     CD       : SP.String_Type;
  6837.  
  6838. begin
  6839.  
  6840.     Check_Directory_Format(Directory);
  6841.  
  6842.     if not Absolute then
  6843.     return Directory & File;
  6844.     end if;
  6845.  
  6846.     for i in Directory'range loop
  6847.     if Directory(i) = '[' then
  6848.         if Directory(i+1) = '.' then
  6849.         Relative := TRUE;
  6850.         end if;
  6851.         exit;
  6852.     end if;
  6853.     end loop;
  6854.  
  6855.     begin
  6856.     if File = "" then
  6857.         if Relative and Absolute then
  6858.         Set_FAB_NAM(File => "[].;", FAB => FAB, NAM => NAM, ES => ES);
  6859.         return ES(1 .. INTEGER(NAM.ESL)-3) &
  6860.                Directory(2 .. Directory'length);
  6861.         else
  6862.         Set_FAB_NAM(File => Directory & ".;", FAB => FAB, NAM => NAM, ES => ES);
  6863.         return ES(1 .. INTEGER(NAM.ESL)-2);
  6864.         end if;
  6865.     else
  6866.         if Relative and Absolute then
  6867.         Set_FAB_NAM(File => "[].;", FAB => FAB, NAM => NAM, ES => ES);
  6868.         return ES(1 .. INTEGER(NAM.ESL)-3) &
  6869.                Directory(2 .. Directory'length) & File;
  6870.         else
  6871.         Set_FAB_NAM(File => Directory & File, FAB => FAB, NAM => NAM, ES => ES);
  6872.         return ES(1 .. INTEGER(NAM.ESL));
  6873.         end if;
  6874.     end if;
  6875.  
  6876.     exception
  6877.     when others =>
  6878.         return Directory & File;
  6879.     end;
  6880.  
  6881. end Path_Name;
  6882.                                                                     pragma page;
  6883. -----------------------------------------------------------------------------
  6884.  
  6885. procedure Create_Dir(
  6886.     Status :    out INTEGER;
  6887.     Dir    : in     STRING);
  6888.  
  6889.     pragma Interface(VAXRTL, Create_Dir);
  6890.     pragma Import_Valued_Procedure(Internal        => Create_Dir,
  6891.                    External        => "LIB$CREATE_DIR",
  6892.                    Parameter_Types => (INTEGER, STRING),
  6893.                    Mechanism       => (Value, Descriptor(S)));
  6894.  
  6895. -----------------------------------------------------------------------------
  6896.  
  6897. procedure Create_Directory(
  6898.     Directory : in STRING
  6899.     ) is
  6900.  
  6901.     Stat  : INTEGER;
  6902.  
  6903. begin
  6904.  
  6905.     Create_Dir(Stat, Directory);
  6906.     if Stat rem 2 = 0 then
  6907.     raise Create_Error;
  6908.     end if;
  6909.  
  6910. end Create_Directory;
  6911.                                                                     pragma page;
  6912. -----------------------------------------------------------------------------
  6913.  
  6914. function Is_Directory(
  6915.     Directory : in STRING
  6916.     ) return BOOLEAN is
  6917.  
  6918.     FAB : STR.FAB_Type;
  6919.     NAM : STR.NAM_Type;
  6920.     ES  : File_String;
  6921.     RS  : File_String;
  6922.  
  6923. begin
  6924.  
  6925.     Check_Directory_Format(Directory);
  6926.     begin
  6927.     Set_FAB_NAM(File => Directory & ".;", FAB => FAB, NAM => NAM, ES => ES);
  6928.     exception
  6929.     when File_Not_Found
  6930.        | File_Already_Exists
  6931.        | File_Locked
  6932.        | Privilege_Violation =>
  6933.         return TRUE;
  6934.     when Directory_Not_Found =>
  6935.         return FALSE;
  6936.     when others =>
  6937.         raise;
  6938.     end;
  6939.     return TRUE;
  6940.  
  6941. end Is_Directory;
  6942.  
  6943. -----------------------------------------------------------------------------
  6944.  
  6945. end  File_Manager;
  6946.                                                                     pragma page;
  6947. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6948. --STACK.SPC
  6949. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6950. -- $Source: /nosc/work/abstractions/stack/RCS/stack.spc,v $
  6951. -- $Revision: 1.5 $ -- $Date: 85/02/01 09:57:17 $ -- $Author: ron $
  6952.  
  6953. -- $Source: /nosc/work/abstractions/stack/RCS/stack.spc,v $
  6954. -- $Revision: 1.5 $ -- $Date: 85/02/01 09:57:17 $ -- $Author: ron $
  6955.  
  6956. with lists;     --| Implementation uses lists.  (private)
  6957.  
  6958. generic
  6959.     type elem_type is private;   --| Component element type.
  6960.  
  6961. package stack_pkg is
  6962.  
  6963. --| Overview:
  6964. --| This package provides the stack abstract data type.  Element type is
  6965. --| a generic formal parameter to the package.  There are no explicit
  6966. --| bounds on the number of objects that can be pushed onto a given stack.
  6967. --| All standard stack operations are provided.
  6968. --|
  6969. --| The following is a complete list of operations, written in the order
  6970. --| in which they appear in the spec.  Overloaded subprograms are followed
  6971. --| by (n), where n is the number of subprograms of that name.
  6972. --|
  6973. --| Constructors:
  6974. --|        create 
  6975. --|        push
  6976. --|        pop (2)
  6977. --|        copy
  6978. --| Query Operations:
  6979. --|        top
  6980. --|        size
  6981. --|        is_empty
  6982. --| Heap Management: 
  6983. --|        destroy
  6984.  
  6985.  
  6986. --| Notes:
  6987. --| Programmer: Ron Kownacki
  6988.  
  6989.     type stack is private;       --| The stack abstract data type.
  6990.     
  6991.   -- Exceptions:
  6992.   
  6993.     uninitialized_stack: exception;
  6994.         --| Raised on attempt to manipulate an uninitialized stack object.
  6995.     --| The initialization operations are create and copy.
  6996.  
  6997.     empty_stack: exception;
  6998.         --| Raised by some operations when empty.
  6999.  
  7000.  
  7001.   -- Constructors:
  7002.     
  7003.     function create
  7004.         return stack;
  7005.     
  7006.       --| Effects:
  7007.       --| Return the empty stack.
  7008.  
  7009.     procedure push(s: in out stack;
  7010.                    e:        elem_type);
  7011.  
  7012.       --| Raises: uninitialized_stack
  7013.       --| Effects:
  7014.       --| Push e onto the top of s.
  7015.       --| Raises uninitialized_stack iff s has not been initialized.
  7016.       
  7017.     procedure pop(s: in out stack);
  7018.       
  7019.       --| Raises: empty_stack, uninitialized_stack
  7020.       --| Effects:
  7021.       --| Pops the top element from s, and throws it away.
  7022.       --| Raises empty_stack iff s is empty.
  7023.       --| Raises uninitialized_stack iff s has not been initialized.
  7024.  
  7025.     procedure pop(s: in out stack;
  7026.           e: out    elem_type);
  7027.  
  7028.       --| Raises: empty_stack, uninitialized_stack
  7029.       --| Effects:
  7030.       --| Pops the top element from s, returns it as the e parameter.
  7031.       --| Raises empty_stack iff s is empty.
  7032.       --| Raises uninitialized_stack iff s has not been initialized.
  7033.       
  7034.     function copy(s: stack)
  7035.     return stack;
  7036.       
  7037.       --| Raises: uninitialized_stack
  7038.       --| Return a copy of s.
  7039.       --| Stack assignment and passing stacks as subprogram parameters
  7040.       --| result in the sharing of a single stack value by two stack
  7041.       --| objects; changes to one will be visible through the others.
  7042.       --| copy can be used to prevent this sharing.
  7043.       --| Raises uninitialized_stack iff s has not been initialized.
  7044.   
  7045.       
  7046.   -- Queries:
  7047.  
  7048.     function top(s: stack)
  7049.         return elem_type;
  7050.  
  7051.       --| Raises: empty_stack, uninitialized_stack
  7052.       --| Effects:
  7053.       --| Return the element on the top of s.  Raises empty_stack iff s is
  7054.       --| empty.
  7055.       --| Raises uninitialized_stack iff s has not been initialized.
  7056.       
  7057.     function size(s: stack)
  7058.         return natural;
  7059.  
  7060.       --| Raises: uninitialized_stack
  7061.       --| Effects:
  7062.       --| Return the current number of elements in s.
  7063.       --| Raises uninitialized_stack iff s has not been initialized.
  7064.  
  7065.     function is_empty(s: stack)
  7066.         return boolean;
  7067.  
  7068.       --| Raises: uninitialized_stack
  7069.       --| Effects:
  7070.       --| Return true iff s is empty.
  7071.       --| Raises uninitialized_stack iff s has not been initialized.
  7072.  
  7073.  
  7074.   -- Heap Management:
  7075.  
  7076.     procedure destroy(s: in out stack);
  7077.     
  7078.       --| Effects:
  7079.       --| Return the space consumed by s to the heap.  No effect if s is
  7080.       --| uninitialized.  In any case, leaves s in uninitialized state.
  7081.  
  7082.  
  7083. private
  7084.  
  7085.     package elem_list_pkg is new lists(elem_type);
  7086.     subtype elem_list is elem_list_pkg.list;
  7087.  
  7088.     type stack_rec is
  7089.         record
  7090.             size: natural := 0;
  7091.             elts: elem_list := elem_list_pkg.create;
  7092.         end record;
  7093.     
  7094.     type stack is access stack_rec;
  7095.  
  7096.     --| Let an instance of the representation type, r, be denoted by the
  7097.     --| pair, <size, elts>.  Dot selection is used to refer to these
  7098.     --| components.
  7099.     --|
  7100.     --| Representation Invariants:
  7101.     --|     r /= null
  7102.     --|     elem_list_pkg.length(r.elts) = r.size.
  7103.     --|
  7104.     --| Abstraction Function:
  7105.     --|     A(<size, elem_list_pkg.create>) = stack_pkg.create.
  7106.     --|     A(<size, elem_list_pkg.attach(e, l)>) = push(A(<size, l>), e).
  7107.  
  7108. end stack_pkg;
  7109.  
  7110.  
  7111. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7112. --STACK.BDY
  7113. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7114. -- $Source: /nosc/work/abstractions/stack/RCS/stack.bdy,v $
  7115. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:19:36 $ -- $Author: ron $
  7116.  
  7117. -- $Source: /nosc/work/abstractions/stack/RCS/stack.bdy,v $
  7118. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:19:36 $ -- $Author: ron $
  7119.  
  7120. with unchecked_deallocation;
  7121.  
  7122. package body stack_pkg is
  7123.  
  7124. --| Overview:
  7125. --| Implementation scheme is totally described by the statements of the
  7126. --| representation invariants and abstraction function that appears in
  7127. --| the package specification.  The implementation is so trivial that
  7128. --| further documentation is unnecessary.
  7129.  
  7130.     use elem_list_pkg;
  7131.     
  7132.     
  7133.   -- Constructors:
  7134.     
  7135.     function create
  7136.         return stack is
  7137.     begin
  7138.     return new stack_rec'(size => 0, elts => create);
  7139.     end create;
  7140.     
  7141.     procedure push(s: in out stack;
  7142.                    e:        elem_type) is
  7143.     begin
  7144.         s.size := s.size + 1;
  7145.         s.elts := attach(e, s.elts);
  7146.     exception
  7147.         when constraint_error =>
  7148.             raise uninitialized_stack;
  7149.     end push;
  7150.  
  7151.     procedure pop(s: in out stack) is
  7152.     begin
  7153.         DeleteHead(s.elts);
  7154.         s.size := s.size - 1;
  7155.     exception
  7156.         when EmptyList =>
  7157.             raise empty_stack;
  7158.     when constraint_error =>
  7159.         raise uninitialized_stack;
  7160.     end pop;
  7161.  
  7162.     procedure pop(s: in out stack;
  7163.                   e: out    elem_type) is
  7164.     begin
  7165.         e := FirstValue(s.elts);
  7166.         DeleteHead(s.elts);
  7167.         s.size := s.size - 1;
  7168.     exception
  7169.         when EmptyList =>
  7170.             raise empty_stack;
  7171.     when constraint_error =>
  7172.         raise uninitialized_stack;
  7173.     end pop;
  7174.     
  7175.     function copy(s: stack)
  7176.         return stack is
  7177.     begin
  7178.     if s = null then raise uninitialized_stack; end if;
  7179.     
  7180.     return new stack_rec'(size => s.size,
  7181.                   elts => copy(s.elts));
  7182.     end;
  7183.  
  7184.     
  7185.   -- Queries:
  7186.  
  7187.     function top(s: stack)
  7188.         return elem_type is
  7189.     begin
  7190.         return FirstValue(s.elts);
  7191.     exception
  7192.         when EmptyList =>
  7193.         raise empty_stack;
  7194.     when constraint_error =>
  7195.         raise uninitialized_stack;
  7196.     end top;
  7197.  
  7198.     function size(s: stack)
  7199.         return natural is
  7200.     begin
  7201.         return s.size;
  7202.     exception
  7203.         when constraint_error =>
  7204.         raise uninitialized_stack;
  7205.     end size;
  7206.  
  7207.     function is_empty(s: stack)
  7208.         return boolean is
  7209.     begin
  7210.         return s.size = 0;
  7211.     exception
  7212.         when constraint_error =>
  7213.         raise uninitialized_stack;
  7214.     end is_empty;
  7215.  
  7216.  
  7217.   -- Heap Management:
  7218.     
  7219.     procedure destroy(s: in out stack) is
  7220.         procedure free_stack is
  7221.         new unchecked_deallocation(stack_rec, stack);
  7222.     begin
  7223.     destroy(s.elts);
  7224.     free_stack(s);
  7225.     exception
  7226.         when constraint_error =>    -- stack is null
  7227.             return; 
  7228.     end destroy;
  7229.    
  7230. end stack_pkg;
  7231. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7232. --SUTILS.SPC
  7233. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7234. with String_Pkg;
  7235. with Stack_Pkg;
  7236. with String_Lists;
  7237.  
  7238. package String_Utilities is
  7239.  
  7240. --| Functions for scanning tokens from strings.
  7241.                                                                     pragma page;
  7242. --| Overview
  7243. --| This package provides a set of functions used to scan tokens from
  7244. --| strings.  After the function make_Scanner is called to convert a string
  7245. --| into a string Scanner, the following functions may be called to scan
  7246. --| various tokens from the string:
  7247. --|-
  7248. --| Make_Scanner    Given a string returns a Scanner
  7249. --| Make_Scanner*    Given a string returns a Scanner
  7250. --| More        Return TRUE iff unscanned characters remain
  7251. --| Forward             Bump the Scanner
  7252. --| Backward        Bump back the Scanner
  7253. --| Get            Return character 
  7254. --| Next        Return character and bump the Scanner
  7255. --| Get_String*        Return Generic_String_Type in Scanner
  7256. --| Get_Remainder*    Return Generic_String_Type in Scanner from current Index
  7257. --| Get_Segment*    Return Generic_String_Type in Scanner as specified
  7258. --| Mark        Mark the current Index for Restore 
  7259. --| Unmark        Remove the previous mark from the Scanner
  7260. --| Restore        Restore the previously marked Index
  7261. --| Position        Return the current position of the Scanner
  7262. --| Destroy_Scanner    Free storage used by Scanner
  7263. --| Is_Word        Return TRUE iff Scanner is at a non-blank character
  7264. --| Scan_Word*        Return sequence of non blank characters
  7265. --| Is_Number        Return TRUE iff Scanner is at a digit
  7266. --| Scan_Number*    Return sequence of decimal digits
  7267. --| Scan_Number        Return integer number
  7268. --| Is_Signed_Number    Return TRUE iff Scanner is at a digit or sign
  7269. --| Scan_Signed_Number*    Return sequence of decimal digits with optional sign (+/-)
  7270. --| Scan_Signed_Number  Return integer number
  7271. --| Is_Space        Return TRUE iff Scanner is at a space or tab
  7272. --| Scan_Space*        Return sequence of spaces or tabs
  7273. --| Skip_Space        Advance Scanner past white space
  7274. --| Is_Ada_Id        Return TRUE iff Scanner is at first character of a possible Ada id
  7275. --| Scan_Ada_Id*    Scan up to the character which are valid Ada identifier
  7276. --| Is_Quoted        Return TRUE iff Scanner is at a double quote
  7277. --| Scan_Quoted*    Scan quoted string, embedded quotes doubled
  7278. --| Is_Enclosed        Return TRUE iff Scanner is at an enclosing character
  7279. --| Scan_Enclosed*    Scan enclosed string, embedded enclosing character doubled
  7280. --| Is_Sequence        Return TRUE iff Scanner is at some character in sequence
  7281. --| Is_Sequence*    Return TRUE iff Scanner is at some character in sequence
  7282. --| Scan_Sequenc* (2)    Scan user specified sequence of chars
  7283. --| Is_Not_Sequence    Return TRUE iff Scanner is not at the characters in sequence
  7284. --| Is_Not_Sequence*    Return TRUE iff Scanner is not at the characters in sequence
  7285. --| Scan_Not_Sequence* (2)
  7286. --|            Scan string up to but not including a given sequence of chars
  7287. --| Is_Literal            Return TRUE iff Scanner is at literal
  7288. --| Is_Literal*            Return TRUE iff Scanner is at literal
  7289. --| Scan_Literal* (2)    Scan user specified literal
  7290. --| Is_Not_Literal    Return TRUE iff Scanner is not a given literal
  7291. --| Is_Not_Literal*    Return TRUE iff Scanner is not a given literal
  7292. --| Scan_Not_Literal* (2)
  7293. --|            Scan string up to but not including a given literal
  7294. --| Strip_Leading    Strip leading characters from a given string
  7295. --| Strip_Leading* (3)    Strip leading characters from a given string
  7296. --| Strip_Trailing    Strip trailing characters from a given string
  7297. --| Strip_Trailing* (3)    Strip trailing characters from a given string
  7298. --| Strip        Strip both leading and trailing characters
  7299. --| Strip* (3)        Strip both leading and trailing characters
  7300. --| Left_Justify    Left justify a given string
  7301. --| Left_Justify* (3)    Left justify a given string
  7302. --| Right_Justify    Right justify a given string
  7303. --| Right_Justify* (3)    Right justify a given string
  7304. --| Center        Center a given string
  7305. --| Center* (3)        Center a given string
  7306. --| Expand        Fill and justify a given string 
  7307. --| Expand* (3)        Fill and justify a given string
  7308. --| Format        Format a given string
  7309. --| Format*        Format a given string
  7310. --| Image        Convert an integer to a string
  7311. --| Image*        Convert an integer to a string
  7312. --| Value        Convert a string to an integer
  7313. --| Value*        Convert a string to an integer
  7314. --| Match        Return TRUE if a string matches another 
  7315. --| Match* (3)        Return TRUE if a string matches another 
  7316. --|
  7317. --|     nb : Operations followed by an asterisk (*) are generic operations
  7318. --|+
  7319.                                                                     pragma page;
  7320. ----------------------------------------------------------------
  7321.  
  7322. White_Space   : constant STRING := " " & ASCII.HT;
  7323. Number        : constant STRING := "0123456789";
  7324. Alphabetic    : constant STRING := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  7325. Alphameric    : constant STRING := Alphabetic & Number;
  7326.  
  7327. ----------------------------------------------------------------
  7328.  
  7329. package SL renames String_Lists;
  7330.  
  7331. package SP renames String_Pkg;
  7332.  
  7333. ----------------------------------------------------------------
  7334.  
  7335. type Scanner is private;    --| Scanner type
  7336.  
  7337. type Justification_Mode is (NONE, LEFT, RIGHT, CENTER, EXPAND);
  7338.  
  7339. ----------------------------------------------------------------
  7340.  
  7341. Out_Of_Bounds      : exception;    --| Raised when a operation is attempted on a
  7342.                 --| Scanner that has passed the end
  7343. Scanner_Not_Marked : exception;    --| Raised when a Unmark or Restore is attemped
  7344.                 --| on a Scanner that has not been marked
  7345. Non_Numeric_String : exception; --| Raised when an attempt is made to take the
  7346.                 --| value of a string that is not a number
  7347. Number_Too_Large   : exception; --| Raised when an attempt is made to scan a
  7348.                 --| number outside the implemented range
  7349.                                                                     pragma page;
  7350. ----------------------------------------------------------------
  7351.  
  7352. function Make_Scanner(            --| Construct a Scanner from S.
  7353.     S : in STRING            --| String to be scanned.
  7354.     ) return Scanner;
  7355.  
  7356. --| Effects: Construct a Scanner from S.
  7357. --| N/A: Raises, Modifies, Errors
  7358.  
  7359. ----------------------------------------------------------------
  7360.  
  7361. function More(                --| Check if Scanner is exhausted
  7362.     T : in Scanner            --| Scanner to check
  7363.     ) return BOOLEAN;
  7364.  
  7365. --| Effects: Return TRUE iff additional characters remain to be scanned.
  7366. --| N/A: Raises, Modifies, Errors
  7367.  
  7368. ----------------------------------------------------------------
  7369.  
  7370. procedure Forward(            --| Bump scanner
  7371.     T : in Scanner            --| Scanner
  7372.     );
  7373.  
  7374. --| Effects: Update the scanner position.
  7375. --| N/A: Raises, Modifies, Errors
  7376.  
  7377. ----------------------------------------------------------------
  7378.  
  7379. procedure Backward(            --| Bump back scanner
  7380.     T : in Scanner            --| Scanner
  7381.     );
  7382.  
  7383. --| Effects: Update the scanner position.
  7384. --| N/A: Raises, Modifies, Errors
  7385.  
  7386. ----------------------------------------------------------------
  7387.  
  7388. function Get(                --| Return character
  7389.     T : in     Scanner            --| Scanner to check
  7390.     ) return CHARACTER;
  7391.  
  7392. --| Raises: Out_Of_Bounds
  7393. --| Effects: Return character at the current Scanner position.
  7394. --| The scanner position remains unchanged.
  7395. --| N/A: Modifies, Errors
  7396.                                                                     pragma page;
  7397. ----------------------------------------------------------------
  7398.  
  7399. procedure Next(                --| Return character and bump scanner
  7400.     T : in     Scanner;            --| Scanner to check
  7401.     C :    out CHARACTER        --| Character to be returned
  7402.     );
  7403.  
  7404. --| Raises: Out_Of_Bounds
  7405. --| Effects: Return character at the current Scanner position and update
  7406. --| the position.
  7407. --| N/A: Modifies, Errors
  7408.  
  7409. ----------------------------------------------------------------
  7410.  
  7411. function Position(            --| Return current Scanner position
  7412.     T : in Scanner            --| Scanner to check
  7413.     ) return POSITIVE;
  7414.  
  7415. --| Raises: Out_Of_Bounds
  7416. --| Effects: Return a positive integer indicating the current Scanner position,
  7417. --| N/A: Modifies, Errors
  7418.  
  7419. ----------------------------------------------------------------
  7420.  
  7421. procedure Mark(
  7422.     T : in Scanner
  7423.     );
  7424.  
  7425. --| Effects: Mark the current index for possible future use
  7426. --| N/A: Raises, Modifies, Errors
  7427.  
  7428. ----------------------------------------------------------------
  7429.  
  7430. procedure Unmark(
  7431.     T : in Scanner
  7432.     );
  7433.  
  7434. --| Raises: Scanner_Not_Marked
  7435. --| Effects: removes previous mark from the scanner without change to the index
  7436. --| N/A: Modifies, Errors
  7437.  
  7438. ----------------------------------------------------------------
  7439.  
  7440. procedure Restore(
  7441.     T : in Scanner
  7442.     );
  7443.  
  7444. --| Raises: Scanner_Not_Marked
  7445. --| Effects: Restore the index to the previously marked value
  7446. --| N/A: Modifies, Errors
  7447.  
  7448. ----------------------------------------------------------------
  7449.  
  7450. procedure Destroy_Scanner(        --| Free Scanner storage
  7451.     T : in out Scanner            --| Scanner to be freed
  7452.     );
  7453.  
  7454. --| Effects: Free space occupied by the Scanner.
  7455. --| N/A: Raises, Modifies, Errors
  7456.                                                                     pragma page;
  7457. ----------------------------------------------------------------
  7458.  
  7459. function Is_Number(            --| Return TRUE iff Scanner is at a decimal digit
  7460.     T : in Scanner            --| The string being scanned
  7461.     ) return BOOLEAN;
  7462.  
  7463. --| Effects: Return TRUE iff Scan_Number would return a non-null string.
  7464. --| N/A: Raises, Modifies, Errors
  7465.  
  7466. ----------------------------------------------------------------
  7467.  
  7468. procedure Scan_Number(            --| Scan sequence of digits
  7469.     T      : in     Scanner;        --| String to be scanned
  7470.     Found  :    out BOOLEAN;        --| TRUE iff one or more digits found
  7471.     Result :    out INTEGER;        --| Number scanned from string
  7472.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7473.     );
  7474.  
  7475. --| Effects: Scan T for a sequence of digits.
  7476. --| If at least one is found, return Found => TRUE, Result => <the digits>.
  7477. --| Otherwise return Found => FALSE and Result is unpredictable.
  7478. --| N/A: Raises, Modifies, Errors
  7479.  
  7480. ----------------------------------------------------------------
  7481.  
  7482. function Is_Signed_Number(        --| Check if Scanner is at a decimal digit or
  7483.                     --| sign (+/-)
  7484.     T : in Scanner            --| The string being scanned
  7485.     ) return BOOLEAN;
  7486.  
  7487. --| Effects: Return TRUE iff Scan_Signed_Number would return a non-null string.
  7488. --| N/A: Raises, Modifies, Errors
  7489.  
  7490. ----------------------------------------------------------------
  7491.  
  7492. procedure Scan_Signed_Number(        --| Scan signed sequence of digits 
  7493.     T      : in     Scanner;        --| String to be scanned
  7494.     Found  :    out BOOLEAN;        --| TRUE iff one or more digits found
  7495.     Result :    out INTEGER;        --| Number scanned from string
  7496.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7497.     );
  7498.  
  7499. --| Effects: Scan T for a sequence of digits preceeded with optional sign.
  7500. --| If at least one digit is found, return Found => TRUE, Result => <digits>.
  7501. --| Otherwise return Found => FALSE and Result is unpredictable.
  7502. --| N/A: Raises, Modifies, Errors
  7503.                                                                     pragma page;
  7504. ----------------------------------------------------------------
  7505.  
  7506. function Is_Word(            --| Check if Scanner is at the start of a word.
  7507.     T : in Scanner            --| Scanner to check
  7508.     ) return BOOLEAN;
  7509.  
  7510. --| Effects: Return TRUE iff Scanner is at the start of a word.
  7511. --| N/A: Raises, Modifies, Errors
  7512.  
  7513. ----------------------------------------------------------------
  7514.  
  7515. function Is_Space(            --| Check if T is at a space or tab
  7516.     T : in Scanner            --| The string being scanned
  7517.     ) return BOOLEAN;
  7518.  
  7519. --| Effects: Return TRUE iff Scan_Space would return a non-null string.
  7520. --| N/A: Raises, Modifies, Errors
  7521.  
  7522. ----------------------------------------------------------------
  7523.  
  7524. procedure Skip_Space(            --| Skip white space
  7525.     T : in Scanner            --| String to be scanned
  7526.     );
  7527.  
  7528. --| Effects: Scan T past all white space (spaces and tabs).  
  7529. --| N/A: Raises, Modifies, Errors
  7530.  
  7531. ----------------------------------------------------------------
  7532.  
  7533. function Is_Ada_Id(            --| Check if T is at an Ada identifier
  7534.     T : in Scanner            --| The string being scanned
  7535.     ) return BOOLEAN;
  7536.  
  7537. --| Effects: Return TRUE iff Scan_Ada_Id would return a non-null string.
  7538. --| N/A: Raises, Modifies, Errors
  7539.  
  7540. ----------------------------------------------------------------
  7541.  
  7542. function Is_Quoted(            --| Check if T is at a double quote
  7543.     T : in Scanner            --| The string being scanned
  7544.     ) return BOOLEAN;
  7545.  
  7546. --| Effects: Return TRUE iff T is at a quoted string (eg. ... "Hello" ...).
  7547. --| N/A: Raises, Modifies, Errors
  7548.  
  7549. ----------------------------------------------------------------
  7550.  
  7551. function Is_Enclosed(            --| Check if T is at an enclosing character
  7552.     B : in CHARACTER;            --| Enclosing open character
  7553.     E : in CHARACTER;            --| Enclosing close character
  7554.     T : in Scanner            --| The string being scanned
  7555.     ) return BOOLEAN;
  7556.  
  7557. --| Effects: Return TRUE iff T as encosed by B and E (eg. ... [ABC] ...).
  7558. --| N/A: Raises, Modifies, Errors
  7559.                                                                     pragma page;
  7560. ----------------------------------------------------------------
  7561.  
  7562. function Is_Sequence(            --| Check if T is at some sequence characters 
  7563.     Chars : in STRING;            --| Characters to be scanned
  7564.     T     : in Scanner            --| The string being scanned
  7565.     ) return BOOLEAN;
  7566.  
  7567. --| Effects: Return TRUE iff T is at some character of Chars.
  7568. --| N/A: Raises, Modifies, Errors
  7569.  
  7570. ----------------------------------------------------------------
  7571.  
  7572. function Is_Not_Sequence(        --| Check if T is at some sequence of characters 
  7573.     Chars : in STRING;            --| Characters to be scanned
  7574.     T     : in Scanner            --| The string being scanned
  7575.     ) return BOOLEAN;
  7576.  
  7577. --| Effects: Return TRUE iff T is not at some character of Chars.
  7578. --| N/A: Raises, Modifies, Errors
  7579.  
  7580. ----------------------------------------------------------------
  7581.  
  7582. function Is_Literal(            --| Check if T is at literal Chars
  7583.     Chars : in STRING;            --| Characters to be scanned
  7584.     T     : in Scanner            --| The string being scanned
  7585.     ) return BOOLEAN;
  7586.  
  7587. --| Effects: Return TRUE iff T is at literal Chars.
  7588. --| N/A: Raises, Modifies, Errors
  7589.  
  7590. ----------------------------------------------------------------
  7591.  
  7592. function Is_Not_Literal(        --| Check if T is not at literal Chars
  7593.     Chars : in STRING;            --| Characters to be scanned
  7594.     T     : in Scanner            --| The string being scanned
  7595.     ) return BOOLEAN;
  7596.  
  7597. --| Effects: Return TRUE iff T is not at literal Chars
  7598. --| N/A: Raises, Modifies, Errors
  7599.                                                                 pragma page;
  7600. ----------------------------------------------------------------
  7601.  
  7602. function Strip_Leading(        --| Strip leading characters from a given string
  7603.     Text : in STRING;        --| Input string
  7604.     Char : in STRING := " " & ASCII.HT
  7605.                 --| Character(s) to be stripped
  7606.     ) return STRING;        --| Result string 
  7607.  
  7608. --| Effects: The specified leading characters are stripped from the input text
  7609. --| N/A: Modifies, Raises, Errors
  7610.  
  7611. ----------------------------------------------------------------
  7612.  
  7613. function Strip_Trailing(    --| Strip trailing characters from a given string
  7614.     Text : in STRING;        --| Input string
  7615.     Char : in STRING := " " & ASCII.HT
  7616.                 --| Character(s) to be stripped
  7617.     ) return STRING;        --| Result string 
  7618.  
  7619. --| Effects: The given trailing characters are stripped from the input text
  7620. --| N/A: Modifies, Raises, Errors
  7621.  
  7622. ----------------------------------------------------------------
  7623.  
  7624. function Strip(         --| Strip both leading and trailing characters  
  7625.                 --| from a given string
  7626.     Text : in STRING;        --| Input string
  7627.     Char : in STRING := " " & ASCII.HT
  7628.                 --| Character(s) to be stripped
  7629.     ) return STRING;        --| Result string 
  7630.  
  7631. --| Effects: The specified characters are stripped from the input text in both
  7632. --| leading and trailing positions
  7633. --| N/A: Modifies, Raises, Errors
  7634.                                                                 pragma page;
  7635. ----------------------------------------------------------------
  7636.  
  7637. function Left_Justify(        --| Left justify a given string
  7638.     Text : in STRING;        --| Input string
  7639.     Len  : in POSITIVE;        --| Output string length
  7640.     Char : in CHARACTER := ' '    --| Fill character
  7641.     ) return STRING;        --| Result string 
  7642.  
  7643. --| Effects: The specified input string is placed left justified and padded if
  7644. --| needed with the fill character.
  7645. --| The Len specifies the result string length.
  7646. --| N/A: Modifies, Raises, Errors
  7647.  
  7648. ----------------------------------------------------------------
  7649.  
  7650. function Right_Justify(        --| Right justify a given string
  7651.     Text : in STRING;        --| Input string
  7652.     Len  : in POSITIVE;        --| Output string length
  7653.     Char : in CHARACTER := ' '    --| Fill character
  7654.     ) return STRING;        --| Result string 
  7655.  
  7656. --| Effects: The specified input string is placed right justified and padded if
  7657. --| needed with the fill character.
  7658. --| The Len specifies the result string length.
  7659. --| N/A: Modifies, Raises, Errors
  7660.  
  7661. ----------------------------------------------------------------
  7662.  
  7663. function Center(        --| Center a given string
  7664.     Text : in STRING;        --| Input string
  7665.     Len  : in POSITIVE;        --| Output string length
  7666.     Char : in CHARACTER := ' '    --| Fill character
  7667.     ) return STRING;        --| Result string 
  7668.  
  7669. --| Effects: The specified input string is placed centered and padded if needed
  7670. --| with the fill character.
  7671. --| The Len specifies the result string length.
  7672. --| N/A: Modifies, Raises, Errors
  7673.  
  7674. ----------------------------------------------------------------
  7675.  
  7676. function Expand(        --| Expand a given string to Len
  7677.     Text : in STRING;        --| Input string
  7678.     Len  : in POSITIVE        --| Output string length
  7679.     ) return STRING;        --| Result string 
  7680.  
  7681. --| Effects: The specified input string is expanded to Len with blanks.
  7682. --| (eg. "Expand this string to 40 chars" when Len equals 40 will be
  7683. --| "Expand   this   string   to   40   chars")
  7684. --| N/A: Modifies, Raises, Errors
  7685.                                                                 pragma page;
  7686. ----------------------------------------------------------------
  7687.  
  7688. function Format(        --| Format a given string
  7689.     Text    : in STRING;    --| Input string
  7690.     Len     : in POSITIVE;    --| Length of each folded line
  7691.     Del     : in CHARACTER := ' ';
  7692.                 --| Delimiting character
  7693.     Justify : in Justification_Mode := NONE
  7694.                 --| Justification mode
  7695.     ) return SL.List;
  7696.  
  7697. --| Effects: The specified string is folded into as many lines of Len as needed.
  7698. --| The character Del indicated an element of the input string where the
  7699. --| line may be "broken".  Returned list consists of persistent string types
  7700. --| thus must be flushed (or DestroyDeep with Flush).
  7701. --| N/A: Modifies, Raises, Errors
  7702.  
  7703. ----------------------------------------------------------------
  7704.  
  7705. function Image(            --| Convert an integer to a string
  7706.     Num  : in INTEGER;        --| Input number
  7707.     Len  : in NATURAL   := 0;    --| Length of the output string
  7708.     Fill : in CHARACTER := ' '    --| Fill character
  7709.     ) return STRING;
  7710.  
  7711. --| Effects: The specified integer is converted into a string of length Len.
  7712. --| Len of 0 implies that the converted integer fills the string.
  7713. --| If Len (other thatn 0) is too small to contain the converted string
  7714. --| the number is truncated.
  7715. --| N/A: Modifies, Raises, Errors
  7716.  
  7717. ----------------------------------------------------------------
  7718.  
  7719. function Value(            --| Convert a string to an integer
  7720.     Text : in STRING        --| String to be converted
  7721.     ) return INTEGER;
  7722.  
  7723. --| Raises: Non_Numeric_String, Number_Too_Large
  7724. --| Effects: The specified string is converted into an equivalent integer.
  7725. --| The string must have the syntax of an Ada INTEGER (LRM 2.4.1)
  7726. --| N/A: Modifies, Errors
  7727.  
  7728. ----------------------------------------------------------------
  7729.  
  7730. function Match(            --| Match two strings
  7731.     Pattern    : in STRING;    --| String to match
  7732.     Target     : in STRING;    --| String to be searched
  7733.     Wildcard   : in CHARACTER := '*';
  7734.                 --| Wildcard character
  7735.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  7736.                 --| Case sensitivity in comparison
  7737.     ) return BOOLEAN;
  7738.  
  7739. --| Effects: The specified Pattern containing Wildcard character(s) are
  7740. --| searched on Target.  If Target satisfies the condition in Pattern
  7741. --| returns TRUE.
  7742. --| (eg. Match("A*B*", "AzzzBzzz") will return TRUE
  7743. --|      Match("A*B*", "zzzABzzz") will return FALSE)
  7744. --| N/A: Raises, Modifies, Errors
  7745.  
  7746. ----------------------------------------------------------------
  7747.                                                                 pragma page;
  7748. generic
  7749.  
  7750.     type Generic_String_Type is private;
  7751.     with function To_Generic (X : in STRING) return Generic_String_Type;
  7752.     with function From_Generic (X : in Generic_String_Type) return STRING;
  7753.  
  7754. package Generic_String_Utilities is
  7755.  
  7756. ----------------------------------------------------------------
  7757.  
  7758. function Make_Scanner(            --| Construct a Scanner from S.
  7759.     S : in Generic_String_Type        --| String to be scanned.
  7760.     ) return Scanner;
  7761.  
  7762. --| Effects: Construct a Scanner from S.
  7763. --| N/A: Raises, Modifies, Errors
  7764.  
  7765. ----------------------------------------------------------------
  7766.  
  7767. function Get_String(            --| Return contents of Scanner
  7768.     T    : in Scanner            --| Scanner
  7769.     ) return Generic_String_Type;
  7770.  
  7771. --| Effects: Return a Generic_String_Type corresponding to the contents
  7772. --| of the Scanner
  7773. --| N/A: Raises, Modifies, Errors
  7774.  
  7775. ----------------------------------------------------------------
  7776.  
  7777. function Get_Remainder(            --| Return contents of Scanner from index
  7778.     T : in Scanner
  7779.     ) return Generic_String_Type;
  7780.  
  7781. --| Effects: Return a Generic_String_Type starting at the current index
  7782. --| of the Scanner
  7783. --| N/A: Raises, Modifies, Errors
  7784.  
  7785. ----------------------------------------------------------------
  7786.  
  7787. function Get_Segment(            --| Return contents of Scanner
  7788.     T    : in Scanner;            --| Scanner
  7789.     From : in POSITIVE;            --| Starting position
  7790.     To   : in POSITIVE            --| Ending position
  7791.     ) return Generic_String_Type;
  7792.  
  7793. --| Effects: Return a Generic_String_Type corresponding to the contents
  7794. --| of the Scanner starting at From and end at but NOT including To.
  7795. --| (eg. Given a scanner T that contains : $123.45
  7796. --|  Get_Segment(T, 2, 5) will return a Generic_String_Type containing 123
  7797. --| N/A: Raises, Modifies, Errors
  7798.  
  7799. ----------------------------------------------------------------
  7800.  
  7801. procedure Scan_Word(            --| Scan sequence of non blank characters
  7802.     T      : in     Scanner;        --| String to be scanned
  7803.     Found  :    out BOOLEAN;        --| TRUE iff a word found
  7804.     Result :    out Generic_String_Type;--| Word scanned from string
  7805.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7806.     );
  7807.  
  7808. --| Effects: Scan T for a sequence of non blank 
  7809. --| characters.  If at least one is found, return Found => TRUE, 
  7810. --| Result => <the characters>.
  7811. --| Otherwise return Found => FALSE and Result is unpredictable.
  7812.  
  7813. --| N/A: Raises, Modifies, Errors
  7814.  
  7815. ----------------------------------------------------------------
  7816.                                                                 pragma page;
  7817. procedure Scan_Number(            --| Scan sequence of digits
  7818.     T      : in     Scanner;        --| String to be scanned
  7819.     Found  :    out BOOLEAN;        --| TRUE iff one or more digits found
  7820.     Result :    out Generic_String_Type;--| Number scanned from string
  7821.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7822.     );
  7823.  
  7824. --| Effects: Scan T for a sequence of digits.
  7825. --| If at least one is found, return Found => TRUE, Result => <the digits>.
  7826. --| Otherwise return Found => FALSE and Result is unpredictable.
  7827. --| N/A: Raises, Modifies, Errors
  7828.  
  7829. ----------------------------------------------------------------
  7830.  
  7831. procedure Scan_Signed_Number(        --| Scan signed sequence of digits 
  7832.     T      : in     Scanner;        --| String to be scanned
  7833.     Found  :    out BOOLEAN;        --| TRUE iff one or more digits found
  7834.     Result :    out Generic_String_Type;--| Number scanned from string
  7835.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7836.     );
  7837.  
  7838. --| Effects: Scan T for a sequence of digits preceeded with optional sign.
  7839. --| If at least one digit is found, return Found => TRUE, 
  7840. --| Result => <the digits>.
  7841. --| Otherwise return Found => FALSE and Result is unpredictable.
  7842. --| N/A: Raises, Modifies, Errors
  7843.  
  7844. ----------------------------------------------------------------
  7845.  
  7846. procedure Scan_Space(            --| Scan sequence of white space characters
  7847.     T      : in     Scanner;        --| String to be scanned
  7848.     Found  :    out BOOLEAN;        --| TRUE iff space found
  7849.     Result :    out Generic_String_Type    --| Spaces scanned from string
  7850.     );
  7851.  
  7852. --| Effects: Scan T past all white space (spaces
  7853. --| and tabs.  If at least one is found, return Found => TRUE,
  7854. --| Result => <the characters>.
  7855. --| Otherwise return Found => FALSE and Result is unpredictable.
  7856. --| N/A: Raises, Modifies, Errors
  7857.                                                                 pragma page;
  7858. ----------------------------------------------------------------
  7859.  
  7860. procedure Scan_Ada_Id(            --| Scan Ada identifier
  7861.     T      : in     Scanner;        --| String to be scanned
  7862.     Found  :    out BOOLEAN;        --| TRUE iff an Ada identifier found
  7863.     Result :    out Generic_String_Type;--| Identifier scanned from string
  7864.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7865.     );
  7866.  
  7867. --| Effects: Scan T for a valid Ada identifier.
  7868. --| If one is found, return Found => TRUE, Result => <the characters>.
  7869. --| Otherwise return Found => FALSE and Result is unpredictable.
  7870. --| N/A: Raises, Modifies, Errors
  7871.  
  7872. ----------------------------------------------------------------
  7873.  
  7874. procedure Scan_Quoted(            --| Scan a quoted string
  7875.     T      : in     Scanner;        --| String to be scanned
  7876.     Found  :    out BOOLEAN;        --| TRUE iff a quoted string found
  7877.     Result :    out Generic_String_Type;--| Quoted string scanned from string
  7878.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7879.     );
  7880.  
  7881. --| Effects: Scan at T for an opening quote
  7882. --| followed by a sequence of characters and ending with a closing
  7883. --| quote.  If successful, return Found => TRUE, Result => <the characters>.
  7884. --| Otherwise return Found => FALSE and Result is unpredictable.
  7885. --| A pair of quotes within the quoted string is converted to a single quote.
  7886. --| The outer quotes are stripped. 
  7887. --| N/A: Raises, Modifies, Errors
  7888.  
  7889. ----------------------------------------------------------------
  7890.  
  7891. procedure Scan_Enclosed(        --| Scan an enclosed string
  7892.     B      : in CHARACTER;        --| Enclosing open character
  7893.     E      : in CHARACTER;        --| Enclosing close character
  7894.     T      : in     Scanner;        --| String to be scanned
  7895.     Found  :    out BOOLEAN;        --| TRUE iff a quoted string found
  7896.     Result :    out Generic_String_Type;--| Quoted string scanned from string
  7897.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7898.     );
  7899.  
  7900. --| Effects: Scan at T for an enclosing character
  7901. --| followed by a sequence of characters and ending with an enclosing character.
  7902. --| If successful, return Found => TRUE, Result => <the characters>.
  7903. --| Otherwise return Found => FALSE and Result is unpredictable.
  7904. --| The enclosing characters are stripped. 
  7905. --| N/A: Raises, Modifies, Errors
  7906.                                                                 pragma page;
  7907. ----------------------------------------------------------------
  7908.  
  7909. function Is_Sequence(            --| Check if T is at some sequence characters 
  7910.     Chars : in Generic_String_Type;    --| Characters to be scanned
  7911.     T     : in Scanner            --| The string being scanned
  7912.     ) return BOOLEAN;
  7913.  
  7914. --| Effects: Return TRUE iff T is at some character of Chars.
  7915. --| N/A: Raises, Modifies, Errors
  7916.  
  7917. ----------------------------------------------------------------
  7918.  
  7919. procedure Scan_Sequence(        --| Scan arbitrary sequence of characters
  7920.     Chars  : in     Generic_String_Type;--| Characters that should be scanned
  7921.     T      : in     Scanner;        --| String to be scanned
  7922.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  7923.     Result :    out Generic_String_Type;--| Sequence scanned from string
  7924.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7925.     );
  7926.  
  7927. --| Effects: Scan T for a sequence of characters C such that C appears in 
  7928. --| Char.  If at least one is found, return Found => TRUE, 
  7929. --| Result => <the characters>.
  7930. --| Otherwise return Found => FALSE and Result is unpredictable.
  7931. --| N/A: Raises, Modifies, Errors
  7932.  
  7933. ----------------------------------------------------------------
  7934.  
  7935. procedure Scan_Sequence(        --| Scan arbitrary sequence of characters
  7936.     Chars  : in     STRING;        --| Characters that should be scanned
  7937.     T      : in     Scanner;        --| String to be scanned
  7938.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  7939.     Result :    out Generic_String_Type;--| Sequence scanned from string
  7940.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7941.     );
  7942.  
  7943. --| Effects: Scan T for a sequence of characters C such that C appears in 
  7944. --| Char.  If at least one is found, return Found => TRUE, 
  7945. --| Result => <the characters>.
  7946. --| Otherwise return Found => FALSE and Result is unpredictable.
  7947. --| N/A: Raises, Modifies, Errors
  7948.                                                                 pragma page;
  7949. ----------------------------------------------------------------
  7950.  
  7951. function Is_Not_Sequence(        --| Check if T is not at some seuqnce of character 
  7952.     Chars : in Generic_String_Type;    --| Characters to be scanned
  7953.     T     : in Scanner            --| The string being scanned
  7954.     ) return BOOLEAN;
  7955.  
  7956. --| Effects: Return TRUE iff T is not at some character of Chars.
  7957. --| N/A: Raises, Modifies, Errors
  7958.  
  7959. ----------------------------------------------------------------
  7960.  
  7961. procedure Scan_Not_Sequence(        --| Scan arbitrary sequence of characters
  7962.     Chars  : in     Generic_String_Type;--| Characters that should be scanned
  7963.     T      : in     Scanner;        --| String to be scanned
  7964.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  7965.     Result :    out Generic_String_Type;--| Sequence scanned from string
  7966.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7967.     );
  7968.  
  7969. --| Effects: Scan T for a sequence of characters C such that C does not appear
  7970. --| in Chars.  If at least one such C is found, return Found => TRUE, 
  7971. --| Result => <the characters>.
  7972. --| Otherwise return Found => FALSE and Result is unpredictable.
  7973. --| N/A: Raises, Modifies, Errors
  7974.  
  7975. ----------------------------------------------------------------
  7976.  
  7977. procedure Scan_Not_Sequence(        --| Scan arbitrary sequence of characters
  7978.     Chars  : in     STRING;        --| Characters that should be scanned
  7979.     T      : in     Scanner;        --| String to be scanned
  7980.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  7981.     Result :    out Generic_String_Type;--| Sequence scanned from string
  7982.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  7983.     );
  7984.  
  7985. --| Effects: Scan T for a sequence of characters C such that C does not appear
  7986. --| in Chars.  If at least one such C is found, return Found => TRUE, 
  7987. --| Result => <the characters>.
  7988. --| Otherwise return Found => FALSE and Result is unpredictable.
  7989. --| N/A: Raises, Modifies, Errors
  7990.                                                                 pragma page;
  7991. ----------------------------------------------------------------
  7992.  
  7993. function Is_Literal(            --| Check if T is at literal Chars
  7994.     Chars : in Generic_String_Type;    --| Characters to be scanned
  7995.     T     : in Scanner            --| The string being scanned
  7996.     ) return BOOLEAN;
  7997.  
  7998. --| Effects: Return TRUE iff T is at literal Chars.
  7999. --| N/A: Raises, Modifies, Errors
  8000.  
  8001. ----------------------------------------------------------------
  8002.  
  8003. procedure Scan_Literal(            --| Scan arbitrary literal
  8004.     Chars  : in     STRING;        --| Literal that should be scanned
  8005.     T      : in     Scanner;        --| String to be scanned
  8006.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  8007.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  8008.     );
  8009.  
  8010. --| Effects: Scan T for a litral Chars such that Char matches the sequence
  8011. --| of characters in T.  If found, return Found => TRUE, 
  8012. --| Otherwise return Found => FALSE
  8013. --| N/A: Raises, Modifies, Errors
  8014.  
  8015. ----------------------------------------------------------------
  8016.  
  8017. procedure Scan_Literal(            --| Scan arbitrary literal
  8018.     Chars  : in     Generic_String_Type;--| Literal that should be scanned
  8019.     T      : in     Scanner;        --| String to be scanned
  8020.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  8021.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  8022.     );
  8023.  
  8024. --| Effects: Scan T for a litral Chars such that Char matches the sequence
  8025. --| of characters in T.  If found, return Found => TRUE, 
  8026. --| Otherwise return Found => FALSE
  8027. --| N/A: Raises, Modifies, Errors
  8028.                                                                 pragma page;
  8029. ----------------------------------------------------------------
  8030.  
  8031. function Is_Not_Literal(        --| Check if T is not at literal Chars
  8032.     Chars : in Generic_String_Type;    --| Characters to be scanned
  8033.     T     : in Scanner            --| The string being scanned
  8034.     ) return BOOLEAN;
  8035.  
  8036. --| Effects: Return TRUE iff T is not at literal Chars
  8037. --| N/A: Raises, Modifies, Errors
  8038.  
  8039. ----------------------------------------------------------------
  8040.  
  8041. procedure Scan_Not_Literal(        --| Scan arbitrary literal
  8042.     Chars  : in     STRING;        --| Literal that should be scanned
  8043.     T      : in     Scanner;        --| String to be scanned
  8044.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  8045.     Result :    out Generic_String_Type;--| String up to literal
  8046.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  8047.     );
  8048.  
  8049. --| Effects: Scan T for a litral Chars such that Char does not match the
  8050. --| sequence of characters in T.  If found, return Found => TRUE, 
  8051. --| Otherwise return Found => FALSE
  8052. --| N/A: Raises, Modifies, Errors
  8053.  
  8054. ----------------------------------------------------------------
  8055.  
  8056. procedure Scan_Not_Literal(        --| Scan arbitrary literal
  8057.     Chars  : in     Generic_String_Type;--| Literal that should be scanned
  8058.     T      : in     Scanner;        --| String to be scanned
  8059.     Found  :    out BOOLEAN;        --| TRUE iff a sequence found
  8060.     Result :    out Generic_String_Type;--| String up to literal
  8061.     Skip   : in     BOOLEAN := FALSE    --| Skip white spaces before scan
  8062.     );
  8063.  
  8064. --| Effects: Scan T for a litral Chars such that Char does not match the
  8065. --| sequence of characters in T.  If found, return Found => TRUE, 
  8066. --| Otherwise return Found => FALSE
  8067. --| N/A: Raises, Modifies, Errors
  8068.  
  8069.                                                                 pragma page;
  8070. ----------------------------------------------------------------
  8071.  
  8072. function Strip_Leading(            --| Strip leading characters from a given string
  8073.     Text : in Generic_String_Type;    --| Input string
  8074.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8075.     ) return STRING;            --| Result string 
  8076.  
  8077. --| Effects: The specified leading characters are stripped from the input text.
  8078. --| N/A: Modifies, Raises, Errors
  8079.  
  8080. ----------------------------------------------------------------
  8081.  
  8082. function Strip_Leading(            --| Strip leading characters from a given string
  8083.     Text : in STRING;            --| Input string
  8084.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8085.     ) return Generic_String_Type;    --| Result string 
  8086.  
  8087. --| Effects: The specified leading characters are stripped from the input text.
  8088. --| N/A: Modifies, Raises, Errors
  8089.  
  8090. ----------------------------------------------------------------
  8091.  
  8092. function Strip_Leading(            --| Strip leading characters from a given string
  8093.     Text : in Generic_String_Type;    --| Input string
  8094.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8095.     ) return Generic_String_Type;    --| Result string 
  8096.  
  8097. --| Effects: The specified leading characters are stripped from the input text.
  8098. --| N/A: Modifies, Raises, Errors
  8099.                                                                 pragma page;
  8100. ----------------------------------------------------------------
  8101.  
  8102. function Strip_Trailing(        --| Strip trailing characters from a given string
  8103.     Text : in Generic_String_Type;    --| Input string
  8104.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8105.     ) return STRING;            --| Result string 
  8106.  
  8107. --| Effects: The specified trailing characters are stripped from the input text.
  8108. --| N/A: Modifies, Raises, Errors
  8109.  
  8110. ----------------------------------------------------------------
  8111.  
  8112. function Strip_Trailing(        --| Strip trailing characters from a given string
  8113.     Text : in STRING;            --| Input string
  8114.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8115.     ) return Generic_String_Type;    --| Result string 
  8116.  
  8117. --| Effects: The specified trailing characters are stripped from the input text.
  8118. --| N/A: Modifies, Raises, Errors
  8119.  
  8120. ----------------------------------------------------------------
  8121.  
  8122. function Strip_Trailing(        --| Strip trailing characters from a given string
  8123.     Text : in Generic_String_Type;    --| Input string
  8124.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8125.     ) return Generic_String_Type;    --| Result string 
  8126.  
  8127. --| Effects: The specified trailing characters are stripped from the input text.
  8128. --| N/A: Modifies, Raises, Errors
  8129.                                                                 pragma page;
  8130. ----------------------------------------------------------------
  8131.  
  8132. function Strip(             --| Strip both leading and trailing
  8133.                     --| characters from a given string
  8134.     Text : in Generic_String_Type;    --| Input string
  8135.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8136.     ) return STRING;            --| Result string 
  8137.  
  8138. --| Effects: The specified characters if any are stripped from the input text
  8139. --| in both leading and trailing positions.
  8140. --| N/A: Modifies, Raises, Errors
  8141.  
  8142. ----------------------------------------------------------------
  8143.  
  8144. function Strip(             --| Strip both leading and trailing
  8145.                     --| characters from a given string
  8146.     Text : in STRING;            --| Input string
  8147.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8148.     ) return Generic_String_Type;    --| Result string 
  8149.  
  8150. --| Effects: The specified characters if any are stripped from the input text
  8151. --| in both leading and trailing positions.
  8152. --| N/A: Modifies, Raises, Errors
  8153.  
  8154. ----------------------------------------------------------------
  8155.  
  8156. function Strip(                --| Strip both leading and trailing
  8157.                     --| characters from a given string
  8158.     Text : in Generic_String_Type;    --| Input string
  8159.     Char : in STRING := " " & ASCII.HT    --| Character(s) to be stripped
  8160.     ) return Generic_String_Type;    --| Result string 
  8161.  
  8162. --| Effects: The specified characters if any are stripped from the input text
  8163. --| in both leading and trailing positions.
  8164. --| N/A: Modifies, Raises, Errors
  8165.                                                                 pragma page;
  8166. ----------------------------------------------------------------
  8167.  
  8168. function Left_Justify(            --| Left justify a given string
  8169.     Text : in Generic_String_Type;    --| Input string
  8170.     Len  : in POSITIVE;            --| Output string length
  8171.     Char : in CHARACTER := ' '        --| Fill character
  8172.     ) return STRING;            --| Result string 
  8173.  
  8174. --| Effects: The specified input string is placed left justified and padded if
  8175. --| needed with the fill character.
  8176. --| The Len specifies the result string length.
  8177. --| N/A: Modifies, Raises, Errors
  8178.  
  8179. ----------------------------------------------------------------
  8180.  
  8181. function Left_Justify(            --| Left justify a given string
  8182.     Text : in STRING;            --| Input string
  8183.     Len  : in POSITIVE;            --| Output string length
  8184.     Char : in CHARACTER := ' '        --| Fill character
  8185.     ) return Generic_String_Type;    --| Result string 
  8186.  
  8187. --| Effects: The specified input string is placed left justified and padded if
  8188. --| needed with the fill character.
  8189. --| The Len specifies the result string length.
  8190. --| N/A: Modifies, Raises, Errors
  8191.  
  8192. ----------------------------------------------------------------
  8193.  
  8194. function Left_Justify(            --| Left justify a given string
  8195.     Text : in Generic_String_Type;    --| Input string
  8196.     Len  : in POSITIVE;            --| Output string length
  8197.     Char : in CHARACTER := ' '        --| Fill character
  8198.     ) return Generic_String_Type;    --| Result string 
  8199.  
  8200. --| Effects: The specified input string is placed left justified and padded if
  8201. --| needed with the fill character.
  8202. --| The Len specifies the result string length.
  8203. --| N/A: Modifies, Raises, Errors
  8204.                                                                 pragma page;
  8205. ----------------------------------------------------------------
  8206.  
  8207. function Right_Justify(            --| Right justify a given string
  8208.     Text : in Generic_String_Type;    --| Input string
  8209.     Len  : in POSITIVE;            --| Output string length
  8210.     Char : in CHARACTER := ' '        --| Fill character
  8211.     ) return STRING;            --| Result string 
  8212.  
  8213. --| Effects: The specified input string is placed right justified and padded if
  8214. --| needed with the fill character.
  8215. --| The Len specifies the result string length.
  8216. --| N/A: Modifies, Raises, Errors
  8217.  
  8218. ----------------------------------------------------------------
  8219.  
  8220. function Right_Justify(            --| Right justify a given string
  8221.     Text : in STRING;            --| Input string
  8222.     Len  : in POSITIVE;            --| Output string length
  8223.     Char : in CHARACTER := ' '        --| Fill character
  8224.     ) return Generic_String_Type;    --| Result string 
  8225.  
  8226. --| Effects: The specified input string is placed left justified and padded if
  8227. --| needed with the fill character.
  8228. --| The Len specifies the result string length.
  8229. --| N/A: Modifies, Raises, Errors
  8230.  
  8231. ----------------------------------------------------------------
  8232.  
  8233. function Right_Justify(            --| Right justify a given string
  8234.     Text : in Generic_String_Type;    --| Input string
  8235.     Len  : in POSITIVE;            --| Output string length
  8236.     Char : in CHARACTER := ' '        --| Fill character
  8237.     ) return Generic_String_Type;    --| Result string 
  8238.  
  8239. --| Effects: The specified input string is placed left justified and padded if
  8240. --| needed with the fill character.
  8241. --| The Len specifies the result string length.
  8242. --| N/A: Modifies, Raises, Errors
  8243.                                                                 pragma page;
  8244. ----------------------------------------------------------------
  8245.  
  8246. function Center(            --| Center a given string
  8247.     Text : in Generic_String_Type;    --| Input string
  8248.     Len  : in POSITIVE;            --| Output string length
  8249.     Char : in CHARACTER := ' '        --| Fill character
  8250.     ) return STRING;            --| Result string 
  8251.  
  8252. --| Effects: The specified input string is placed centered and padded if needed
  8253. --| with the fill character.
  8254. --| The Len specifies the result string length.
  8255. --| N/A: Modifies, Raises, Errors
  8256.  
  8257. ----------------------------------------------------------------
  8258.  
  8259. function Center(            --| Center a given string
  8260.     Text : in STRING;            --| Input string
  8261.     Len  : in POSITIVE;            --| Output string length
  8262.     Char : in CHARACTER := ' '        --| Fill character
  8263.     ) return Generic_String_Type;    --| Result string 
  8264.  
  8265. --| Effects: The specified input string is placed centered and padded if needed
  8266. --| with the fill character.
  8267. --| The Len specifies the result string length.
  8268. --| N/A: Modifies, Raises, Errors
  8269.  
  8270. ----------------------------------------------------------------
  8271.  
  8272. function Center(            --| Center a given string
  8273.     Text : in Generic_String_Type;    --| Input string
  8274.     Len  : in POSITIVE;            --| Output string length
  8275.     Char : in CHARACTER := ' '        --| Fill character
  8276.     ) return Generic_String_Type;    --| Result string 
  8277.  
  8278. --| Effects: The specified input string is placed centered and padded if needed
  8279. --| with the fill character.
  8280. --| The Len specifies the result string length.
  8281. --| N/A: Modifies, Raises, Errors
  8282.                                                                 pragma page;
  8283. ----------------------------------------------------------------
  8284.  
  8285. function Expand(            --| Expand a given string to Len
  8286.     Text : in Generic_String_Type;    --| Input string
  8287.     Len  : in POSITIVE            --| Output string length
  8288.     ) return STRING;            --| Result string 
  8289.  
  8290. --| Effects: The specified input string is expanded to Len with blanks.
  8291. --| (eg. "Expand this string to 40 chars" when Len equals 40 will be
  8292. --| "Expand   this   string   to   40   chars")
  8293. --| N/A: Modifies, Raises, Errors
  8294.  
  8295. ----------------------------------------------------------------
  8296.  
  8297. function Expand(            --| Expand a given string to Len
  8298.     Text : in STRING;            --| Input string
  8299.     Len  : in POSITIVE            --| Output string length
  8300.     ) return Generic_String_Type;    --| Result string 
  8301.  
  8302. --| Effects: The specified input string is expanded to Len with blanks.
  8303. --| (eg. "Expand this string to 40 chars" when Len equals 40 will be
  8304. --| "Expand   this   string   to   40   chars")
  8305. --| N/A: Modifies, Raises, Errors
  8306.  
  8307. ----------------------------------------------------------------
  8308.  
  8309. function Expand(            --| Expand a given string to Len
  8310.     Text : in Generic_String_Type;    --| Input string
  8311.     Len  : in POSITIVE            --| Output string length
  8312.     ) return Generic_String_Type;    --| Result string 
  8313.  
  8314. --| Effects: The specified input string is expanded to Len with blanks.
  8315. --| (eg. "Expand this string to 40 chars" when Len equals 40 will be
  8316. --| "Expand   this   string   to   40   chars")
  8317. --| N/A: Modifies, Raises, Errors
  8318.                                                                 pragma page;
  8319. ----------------------------------------------------------------
  8320.  
  8321. function Format(            --| Format a given string
  8322.     Text    : in Generic_String_Type;    --| Input string
  8323.     Len     : in POSITIVE;        --| Length of each folded line
  8324.     Del     : in CHARACTER := ' ';    --| Delimiting character
  8325.     Justify : in Justification_Mode := NONE
  8326.                     --| Justification mode
  8327.     ) return SL.List;
  8328.  
  8329. --| Effects: The specified string is folded into as many lines of Len as needed.
  8330. --| The character Del indicated an element of the input string where the
  8331. --| line may be "broken".  Returned list consists of persistent string types
  8332. --| thus must be flushed (or DestroyDeep with Flush).
  8333. --| N/A: Modifies, Raises, Errors
  8334.  
  8335. ----------------------------------------------------------------
  8336.  
  8337. function Image(                --| Convert an integer to a string
  8338.     Num  : in INTEGER;            --| Input number
  8339.     Len  : in NATURAL   := 0;        --| Length of the output string
  8340.     Fill : in CHARACTER := ' '        --| Fill character
  8341.     ) return Generic_String_Type;
  8342.  
  8343. --| Effects: The specified integer is converted into a string of length Len.
  8344. --| Len of 0 implies that the converted integer fills the string.
  8345. --| If Len (other thatn 0) is too small to contain the converted string
  8346. --| the number is truncated.
  8347. --| N/A: Modifies, Raises, Errors
  8348.  
  8349. ----------------------------------------------------------------
  8350.  
  8351. function Value(                --| Convert a string to an integer
  8352.     Text : in Generic_String_Type    --| Input string
  8353.     ) return INTEGER;
  8354.  
  8355. --| Raises: Non_Numeric_String, Number_Too_Large
  8356. --| Effects: The specified string is converted into an equivalent integer.
  8357. --| The string must have the syntax of an Ada INTEGER (LRM 2.4.1)
  8358. --| N/A: Modifies, Errors
  8359.  
  8360. ----------------------------------------------------------------
  8361.  
  8362. function Match(            --| Match two strings
  8363.     Pattern    : in Generic_String_Type;
  8364.                 --| String to match
  8365.     Target     : in STRING;    --| String to be searched
  8366.     Wildcard   : in CHARACTER := '*';
  8367.                 --| Wildcard character
  8368.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  8369.                 --| Case sensitivity in comparison
  8370.     ) return BOOLEAN;
  8371.  
  8372. --| Effects: The specified Pattern containing Wildcard character(s) are
  8373. --| searched on Target.  If Target satisfies the condition in Pattern
  8374. --| returns TRUE.
  8375. --| N/A: Raises, Modifies, Errors
  8376.  
  8377. ----------------------------------------------------------------
  8378.  
  8379. function Match(            --| Match two strings
  8380.     Pattern    : in STRING;    --| String to match
  8381.     Target     : in Generic_String_Type;
  8382.                 --| String to be searched
  8383.     Wildcard   : in CHARACTER := '*';
  8384.                 --| Wildcard character
  8385.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  8386.                 --| Case sensitivity in comparison
  8387.     ) return BOOLEAN;
  8388.  
  8389. --| Effects: The specified Pattern containing Wildcard character(s) are
  8390. --| searched on Target.  If Target satisfies the condition in Pattern
  8391. --| returns TRUE.
  8392. --| N/A: Raises, Modifies, Errors
  8393.  
  8394. ----------------------------------------------------------------
  8395.  
  8396. function Match(            --| Match two strings
  8397.     Pattern    : in Generic_String_Type;
  8398.                 --| String to match
  8399.     Target     : in Generic_String_Type;
  8400.                 --| String to be searched
  8401.     Wildcard   : in CHARACTER := '*';
  8402.                 --| Wildcard character
  8403.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  8404.                 --| Case sensitivity in comparison
  8405.     ) return BOOLEAN;
  8406.  
  8407. --| Effects: The specified Pattern containing Wildcard character(s) are
  8408. --| searched on Target.  If Target satisfies the condition in Pattern
  8409. --| returns TRUE.
  8410. --| N/A: Raises, Modifies, Errors
  8411.  
  8412. ----------------------------------------------------------------
  8413.  
  8414. end Generic_String_Utilities;
  8415.  
  8416.  
  8417. private
  8418.                                                                     pragma List(off);
  8419.     package ST is new Stack_Pkg(POSITIVE);
  8420.  
  8421.     type Scan_Record is
  8422.     record
  8423.         text  : SP.String_Type;    --| Copy of string being scanned
  8424.         index : POSITIVE := 1;    --| Current position of Scanner
  8425.         mark  : ST.Stack := ST.Create;
  8426.                     --| Marks
  8427.     end record;
  8428.  
  8429.     type Scanner is access Scan_Record;
  8430.                                                                     pragma List(on);
  8431. end String_Utilities;
  8432.                                                                     pragma page;
  8433. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8434. --SUTILS.BDY
  8435. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8436. with Unchecked_Deallocation;
  8437.  
  8438. package body String_Utilities is
  8439.  
  8440. ----------------------------------------------------------------
  8441.  
  8442. procedure Free_Scanner is
  8443.     new Unchecked_Deallocation(Scan_Record, Scanner);
  8444.  
  8445. ----------------------------------------------------------------
  8446.  
  8447. function Is_Valid(
  8448.     T : in Scanner
  8449.     ) return BOOLEAN is
  8450.  
  8451. begin
  8452.  
  8453.     return T /= null;
  8454.  
  8455. end Is_Valid;
  8456.  
  8457. ----------------------------------------------------------------
  8458.  
  8459. function Make_Scanner(
  8460.     S : in STRING
  8461.     ) return Scanner is
  8462.  
  8463.     T : Scanner := new Scan_Record;
  8464.  
  8465. begin
  8466.  
  8467.     T.text := SP.Make_Persistent(S);
  8468.     return T;
  8469.  
  8470. end Make_Scanner;
  8471.  
  8472. ----------------------------------------------------------------
  8473.  
  8474. procedure Destroy_Scanner(
  8475.     T : in out Scanner
  8476.     ) is
  8477.  
  8478. begin
  8479.  
  8480.     if Is_Valid(T) then
  8481.     SP.Flush(T.text);
  8482.     ST.Destroy(T.mark);
  8483.     Free_Scanner(T);
  8484.     end if;
  8485.  
  8486. end Destroy_Scanner;
  8487.  
  8488. ----------------------------------------------------------------
  8489.  
  8490. function More(
  8491.     T : in Scanner
  8492.     ) return BOOLEAN is
  8493.  
  8494. begin
  8495.  
  8496.     if Is_Valid(T) and then T.index <= SP.Length(T.text) then
  8497.     return TRUE;
  8498.     else
  8499.     return FALSE;
  8500.     end if;
  8501.  
  8502. end More;
  8503.  
  8504. ----------------------------------------------------------------
  8505.  
  8506. function Get(
  8507.     T : in Scanner
  8508.     ) return CHARACTER is
  8509.  
  8510. begin
  8511.  
  8512.     if not More(T) then
  8513.     raise Out_Of_Bounds;
  8514.     end if;
  8515.     return SP.Fetch(T.text, T.index);
  8516.  
  8517. end Get;
  8518.  
  8519. ----------------------------------------------------------------
  8520.  
  8521. procedure Forward(
  8522.     T : in Scanner
  8523.     ) is
  8524.  
  8525. begin
  8526.  
  8527.     if Is_Valid(T) then
  8528.     if SP.Length(T.text) >= T.index then
  8529.         T.index := T.index + 1;
  8530.     end if;
  8531.     end if;
  8532.  
  8533. end Forward;
  8534.  
  8535. ----------------------------------------------------------------
  8536.  
  8537. procedure Backward(
  8538.     T : in Scanner
  8539.     ) is
  8540.  
  8541. begin
  8542.  
  8543.     if Is_Valid(T) then
  8544.     if T.index > 1 then
  8545.         T.index := T.index - 1;
  8546.     end if;
  8547.     end if;
  8548.  
  8549. end Backward;
  8550.  
  8551. ----------------------------------------------------------------
  8552.  
  8553. procedure Next(
  8554.     T : in     Scanner;
  8555.     C :    out CHARACTER
  8556.     ) is
  8557.  
  8558. begin
  8559.  
  8560.     C := Get(T);
  8561.     T.index := T.index + 1;
  8562.  
  8563. end Next;
  8564.  
  8565. ----------------------------------------------------------------
  8566.  
  8567. function Position(
  8568.     T : in Scanner
  8569.     ) return POSITIVE is
  8570.  
  8571. begin
  8572.  
  8573.     if not More(T) then
  8574.     raise Out_Of_Bounds;
  8575.     end if;
  8576.     return T.index;
  8577.  
  8578. end Position;
  8579.  
  8580. ----------------------------------------------------------------
  8581.  
  8582. procedure Mark(
  8583.     T : in Scanner
  8584.     ) is
  8585.  
  8586. begin
  8587.  
  8588.     if Is_Valid(T) then
  8589.     ST.Push(T.mark, T.index);
  8590.     end if;
  8591.  
  8592. end Mark;
  8593.  
  8594. ----------------------------------------------------------------
  8595.  
  8596. procedure Unmark(
  8597.     T : in Scanner
  8598.     ) is
  8599.  
  8600.     Num : POSITIVE;
  8601.  
  8602. begin
  8603.  
  8604.     if Is_Valid(T) and then not ST.Is_Empty(T.mark) then
  8605.         ST.Pop(T.mark, Num);
  8606.     else
  8607.     raise Scanner_Not_Marked;
  8608.     end if;
  8609.  
  8610. end Unmark;
  8611.  
  8612. ----------------------------------------------------------------
  8613.  
  8614. procedure Restore(
  8615.     T : in Scanner
  8616.     ) is
  8617.  
  8618. begin
  8619.  
  8620.     if Is_Valid(T) and then not ST.Is_Empty(T.mark) then
  8621.     ST.Pop(T.mark, T.index);
  8622.     else
  8623.     raise Scanner_Not_Marked;
  8624.     end if;
  8625.  
  8626. end Restore;
  8627.  
  8628. ----------------------------------------------------------------
  8629.  
  8630. function Is_Any(
  8631.     T : in Scanner;
  8632.     Q : in STRING
  8633.     ) return BOOLEAN is
  8634.  
  8635.     N     : NATURAL;
  8636.  
  8637. begin
  8638.  
  8639.     if not More(T) then
  8640.     return FALSE;
  8641.     end if;
  8642.     SP.Mark;
  8643.     N := SP.Match_Any(T.text, Q, T.index);
  8644.     if N /= T.index then
  8645.     N := 0;
  8646.     end if;
  8647.     SP.Release;
  8648.     return N /= 0;
  8649.  
  8650. end Is_Any;
  8651.  
  8652. ----------------------------------------------------------------
  8653.  
  8654. procedure Scan_Any(
  8655.     T      : in     Scanner;
  8656.     Q      : in     STRING;
  8657.     Found  :    out BOOLEAN;
  8658.     Result : in out SP.String_Type
  8659.     ) is
  8660.  
  8661.     S_Str : SP.String_Type;
  8662.     N     : NATURAL;
  8663.  
  8664. begin
  8665.  
  8666.     if Is_Any(T, Q) then
  8667.     N := SP.Match_None(T.text, Q, T.index);
  8668.     if N = 0 then
  8669.         N := SP.Length(T.text) + 1;
  8670.     end if;
  8671.     Result  := SP."&"(Result, SP.Substr(T.text, T.index, N - T.index));
  8672.     T.index := N;    
  8673.     Found   := TRUE;
  8674.     else
  8675.     Found := FALSE;
  8676.     end if;
  8677.  
  8678. end Scan_Any;
  8679.  
  8680. ----------------------------------------------------------------
  8681.  
  8682. function Quoted_String(
  8683.     T : in Scanner
  8684.     ) return INTEGER is
  8685.  
  8686.     Count : INTEGER := 0;
  8687.     I     : POSITIVE;
  8688.     N     : NATURAL;
  8689.  
  8690. begin
  8691.  
  8692.     if not More(T) then
  8693.     return Count;
  8694.     end if;
  8695.     I := T.index;
  8696.     while Is_Any(T, """") loop
  8697.     T.index := T.index + 1;
  8698.     if not More(T) then
  8699.         T.index := I;
  8700.         return 0;
  8701.     end if;
  8702.     SP.Mark;
  8703.     N := SP.Match_Any(T.text, """", T.index);
  8704.     SP.Release;
  8705.     if N = 0 then
  8706.         T.index := I;
  8707.         return 0;
  8708.     end if;
  8709.     T.index := N + 1;
  8710.     end loop;
  8711.     Count := T.index - I;
  8712.     T.index := I;
  8713.     return Count;
  8714.  
  8715. end Quoted_String;
  8716.  
  8717. ----------------------------------------------------------------
  8718.  
  8719. function Enclosed_String(
  8720.     B : in CHARACTER;
  8721.     E : in CHARACTER;
  8722.     T : in Scanner
  8723.     ) return NATURAL is
  8724.  
  8725.     Count : NATURAL := 1;
  8726.     I     : POSITIVE;
  8727.     Inx_B : NATURAL;
  8728.     Inx_E : NATURAL;
  8729.     Depth : NATURAL := 1;
  8730.  
  8731. begin
  8732.  
  8733.     if not Is_Any(T, B & "") then
  8734.     return 0;
  8735.     end if;
  8736.     I := T.index;
  8737.     T.index := T.index + 1;
  8738.     while Depth /= 0 loop
  8739.     if not More(T) then
  8740.         T.index := I;
  8741.         return 0;
  8742.     end if;
  8743.     SP.Mark;
  8744.     Inx_B   := SP.Match_Any(T.text, B & "", T.index);
  8745.     Inx_E   := SP.Match_Any(T.text, E & "", T.index);
  8746.     SP.Release;
  8747.     if Inx_E = 0 then
  8748.         T.index := I;
  8749.         return 0;
  8750.     end if;
  8751.     if Inx_B /= 0 and then Inx_B < Inx_E then
  8752.         Depth := Depth + 1;
  8753.     else
  8754.         Inx_B := Inx_E;
  8755.         Depth := Depth - 1;
  8756.     end if;
  8757.     T.index := Inx_B + 1;
  8758.     end loop;
  8759.     Count := T.index - I;
  8760.     T.index := I;
  8761.     return Count;
  8762.  
  8763. end Enclosed_String;
  8764.  
  8765. ----------------------------------------------------------------
  8766.  
  8767. function Is_Word(
  8768.     T : in Scanner
  8769.     ) return BOOLEAN is
  8770.  
  8771. begin
  8772.  
  8773.     if not More(T) then
  8774.     return FALSE;
  8775.     else
  8776.     return not Is_Any(T, White_Space);
  8777.     end if;
  8778.  
  8779. end Is_Word;
  8780.  
  8781. ----------------------------------------------------------------
  8782.  
  8783. function Is_Number(
  8784.     T : in Scanner
  8785.     ) return BOOLEAN is
  8786.  
  8787. begin
  8788.  
  8789.     return Is_Any(T, Number);
  8790.  
  8791. end Is_Number;
  8792.  
  8793. ----------------------------------------------------------------
  8794.  
  8795. function Get_Number(
  8796.     T      : in     Scanner
  8797.     ) return STRING is
  8798.  
  8799.     C     : CHARACTER;
  8800.     F     : BOOLEAN;
  8801.     S_Str : SP.String_Type;
  8802.  
  8803. begin
  8804.  
  8805.     SP.Mark;
  8806.     while Is_Number(T) loop
  8807.     Scan_Any(T, Number, F, S_Str);
  8808.     if More(T) then
  8809.         C := Get(T);
  8810.         if C = '_' then
  8811.         T.index := T.index + 1;
  8812.         if Is_Number(T) then
  8813.             S_Str := SP."&"(S_Str, "_");
  8814.         else
  8815.             T.index := T.index - 1;
  8816.         end if;
  8817.         end if;
  8818.     end if;
  8819.     end loop;
  8820.     declare
  8821.     S : STRING (1 .. SP.Length(S_Str));
  8822.     begin
  8823.     S := SP.Value(S_Str);
  8824.     SP.Release;
  8825.     return S;
  8826.     end;
  8827.  
  8828. end Get_Number;
  8829.  
  8830. ----------------------------------------------------------------
  8831.  
  8832. procedure Scan_Number(
  8833.     T      : in     Scanner;
  8834.     Found  :    out BOOLEAN;
  8835.     Result :    out INTEGER;
  8836.     Skip   : in     BOOLEAN := FALSE
  8837.     ) is
  8838.  
  8839. begin
  8840.  
  8841.     if Skip then
  8842.     Skip_Space(T);
  8843.     end if;
  8844.     if Is_Number(T) then
  8845.     begin
  8846.         Mark(T);
  8847.         Result := INTEGER'Value(Get_Number(T));
  8848.         Unmark(T);
  8849.     exception
  8850.         when CONSTRAINT_ERROR =>
  8851.         Restore(T);
  8852.         raise Number_Too_Large;
  8853.     end;
  8854.     Found := TRUE;
  8855.     else
  8856.     Found := FALSE;     
  8857.     end if;
  8858.  
  8859. end Scan_Number;
  8860.  
  8861. ----------------------------------------------------------------
  8862.  
  8863. function Is_Signed_Number(
  8864.     T : in Scanner
  8865.     ) return BOOLEAN is
  8866.  
  8867.     I : POSITIVE;
  8868.     C : CHARACTER;
  8869.     F : BOOLEAN;
  8870.  
  8871. begin
  8872.  
  8873.     if not More(T) then
  8874.     return FALSE;
  8875.     end if;
  8876.     I := T.index;
  8877.     C := Get(T);
  8878.     if C = '+' or C = '-' then
  8879.     T.index := T.index + 1;
  8880.     end if;
  8881.     F := Is_Any(T, Number);
  8882.     T.index := I;
  8883.     return F;
  8884.  
  8885. end Is_Signed_Number;
  8886.  
  8887. ----------------------------------------------------------------
  8888.  
  8889. function Get_Signed_Number(
  8890.     T      : in     Scanner
  8891.     ) return STRING is
  8892.  
  8893.     C     : CHARACTER;
  8894.  
  8895. begin
  8896.  
  8897.     C := Get(T);
  8898.     if C = '+' or C = '-' then
  8899.     T.index := T.index + 1;
  8900.     return C & Get_Number(T);
  8901.     else
  8902.     return Get_Number(T);
  8903.     end if;    
  8904.  
  8905. end Get_Signed_Number;
  8906.  
  8907. ----------------------------------------------------------------
  8908.  
  8909. procedure Scan_Signed_Number(
  8910.     T      : in     Scanner;
  8911.     Found  :    out BOOLEAN;
  8912.     Result :    out INTEGER;
  8913.     Skip   : in     BOOLEAN := FALSE
  8914.     ) is
  8915.  
  8916. begin
  8917.  
  8918.     if Skip then
  8919.     Skip_Space(T);
  8920.     end if;
  8921.     if Is_Signed_Number(T) then
  8922.     begin
  8923.         Mark(T);
  8924.         Result := INTEGER'Value(Get_Signed_Number(T));
  8925.         Unmark(T);
  8926.     exception
  8927.         when CONSTRAINT_ERROR =>
  8928.         Restore(T);
  8929.         raise Number_Too_Large;
  8930.     end;
  8931.     Found := TRUE;
  8932.     else
  8933.     Found := FALSE;
  8934.     end if;
  8935.  
  8936. end Scan_Signed_Number;
  8937.  
  8938. ----------------------------------------------------------------
  8939.  
  8940. function Is_Space(
  8941.     T : in Scanner
  8942.     ) return BOOLEAN is
  8943.  
  8944. begin
  8945.  
  8946.     return Is_Any(T, White_Space);
  8947.  
  8948. end Is_Space;
  8949.  
  8950. ----------------------------------------------------------------
  8951.  
  8952. procedure Skip_Space(
  8953.     T : in Scanner
  8954.     ) is
  8955.  
  8956.     S_Str : SP.String_Type;
  8957.     Found : BOOLEAN;
  8958.  
  8959. begin
  8960.  
  8961.     SP.Mark;
  8962.     Scan_Any(T, White_Space, Found, S_Str);
  8963.     SP.Release;
  8964.  
  8965. end Skip_Space;
  8966.  
  8967. ----------------------------------------------------------------
  8968.  
  8969. function Is_Ada_Id(
  8970.     T : in Scanner
  8971.     ) return BOOLEAN is
  8972.  
  8973. begin
  8974.  
  8975.     return Is_Any(T, Alphabetic);
  8976.  
  8977. end Is_Ada_Id;
  8978.  
  8979. ----------------------------------------------------------------
  8980.  
  8981. function Is_Quoted(
  8982.     T : in Scanner
  8983.     ) return BOOLEAN is
  8984.  
  8985. begin
  8986.  
  8987.     if Quoted_String(T) = 0 then
  8988.     return FALSE;
  8989.     else
  8990.     return TRUE;
  8991.     end if;
  8992.  
  8993. end Is_Quoted;
  8994.  
  8995. ----------------------------------------------------------------
  8996.  
  8997. function Is_Enclosed(
  8998.     B : in CHARACTER;
  8999.     E : in CHARACTER;
  9000.     T : in Scanner
  9001.     ) return BOOLEAN is
  9002.  
  9003. begin
  9004.  
  9005.     if Enclosed_String(B, E, T) = 0 then
  9006.     return FALSE;
  9007.     else
  9008.     return TRUE;
  9009.     end if;
  9010.  
  9011. end Is_Enclosed;
  9012.  
  9013. ----------------------------------------------------------------
  9014.  
  9015. function Is_Sequence(
  9016.     Chars  : in STRING;
  9017.     T      : in Scanner
  9018.     ) return BOOLEAN is
  9019.  
  9020. begin
  9021.  
  9022.     return Is_Any(T, Chars);
  9023.  
  9024. end Is_Sequence;
  9025.  
  9026. ----------------------------------------------------------------
  9027.  
  9028. function Is_Not_Sequence(
  9029.     Chars  : in STRING;
  9030.     T      : in Scanner
  9031.     ) return BOOLEAN is
  9032.  
  9033.     N : NATURAL;
  9034.  
  9035. begin
  9036.  
  9037.     if not More(T) then
  9038.     return FALSE;
  9039.     end if;
  9040.     SP.Mark;
  9041.     N := SP.Match_Any(T.text, Chars, T.index);
  9042.     if N = T.index then
  9043.     N := 0;
  9044.     end if;
  9045.     SP.Release;
  9046.     return N /= 0;
  9047.  
  9048. end Is_Not_Sequence;
  9049.  
  9050. ----------------------------------------------------------------
  9051.  
  9052. function Is_Literal(
  9053.     Chars  : in STRING;
  9054.     T      : in Scanner
  9055.     ) return BOOLEAN is
  9056.  
  9057.     N : NATURAL;
  9058.  
  9059. begin
  9060.  
  9061.     if not More(T) then
  9062.     return FALSE;
  9063.     end if;
  9064.     N := SP.Match_S(T.text, Chars, T.index);
  9065.     if N /= T.index then
  9066.     N := 0;
  9067.     end if;
  9068.     return N /= 0;
  9069.  
  9070. end Is_Literal;
  9071.  
  9072. ----------------------------------------------------------------
  9073.  
  9074. function Is_Not_Literal(
  9075.     Chars : in STRING;
  9076.     T     : in Scanner
  9077.     ) return BOOLEAN is
  9078.  
  9079.     N     : NATURAL;
  9080.  
  9081. begin
  9082.  
  9083.     if not More(T) then
  9084.     return FALSE;
  9085.     end if;
  9086.     SP.Mark;
  9087.     N := SP.Match_S(T.text, Chars, T.index);
  9088.     if N = T.index then
  9089.     N := 0;
  9090.     end if;
  9091.     SP.Release;
  9092.     return N /= 0;
  9093.  
  9094. end Is_Not_Literal;
  9095.  
  9096. ----------------------------------------------------------------
  9097.  
  9098. function Match_Character(
  9099.     T    : in CHARACTER;
  9100.     Char : in STRING
  9101.     ) return BOOLEAN is
  9102.  
  9103. begin
  9104.         
  9105.     for j in Char'range loop
  9106.     if T = Char(j) then
  9107.         return TRUE;
  9108.     end if;
  9109.     end loop;
  9110.     return FALSE;
  9111.  
  9112. end Match_Character;
  9113.  
  9114. ----------------------------------------------------------------
  9115.  
  9116. function Strip_Leading(
  9117.     Text : in STRING;
  9118.     Char : in STRING := " " & ASCII.HT
  9119.     ) return STRING is
  9120.  
  9121. begin
  9122.  
  9123.     for i in Text'range loop
  9124.     if not Match_Character(Text(i), Char) then
  9125.         return Text(i .. Text'last);
  9126.     end if;
  9127.     end loop;
  9128.     return "";
  9129.  
  9130. end Strip_Leading;
  9131.  
  9132. ----------------------------------------------------------------
  9133.  
  9134. function Strip_Trailing(
  9135.     Text : in STRING;
  9136.     Char : in STRING := " " & ASCII.HT
  9137.     ) return STRING is
  9138.  
  9139. begin
  9140.  
  9141.     for i in reverse Text'range loop
  9142.     if not Match_Character(Text(i), Char) then
  9143.         return Text(Text'first .. i);
  9144.     end if;
  9145.     end loop;
  9146.     return "";
  9147.  
  9148. end Strip_Trailing;
  9149.  
  9150. ----------------------------------------------------------------
  9151.  
  9152. function Strip(
  9153.     Text : in STRING;
  9154.     Char : in STRING := " " & ASCII.HT
  9155.     ) return STRING is
  9156.  
  9157. begin 
  9158.  
  9159.     return Strip_Leading(STRING'(Strip_Trailing(Text, Char)), Char);
  9160.  
  9161. end Strip;
  9162.  
  9163. ----------------------------------------------------------------
  9164.  
  9165. function Justify_String(
  9166.     Text : in STRING;
  9167.     Len  : in POSITIVE;
  9168.     Char : in CHARACTER;
  9169.     Mode : in Justification_Mode
  9170.     ) return STRING is
  9171.  
  9172.     Out_String  : STRING (1 .. Len) := (others => Char);
  9173.     Temp_String : SP.String_Type;
  9174.     Index       : INTEGER;
  9175.  
  9176. begin
  9177.  
  9178.     SP.Mark;
  9179.     Temp_String := SP.Create(Out_String & Text & Out_String); 
  9180.     case Mode is
  9181.     when LEFT =>
  9182.         Index := Len + 1;
  9183.     when RIGHT =>
  9184.         Index := SP.Length(Temp_String) - Len*2 + 1;
  9185.     when CENTER =>
  9186.         Index := (SP.Length(Temp_String) - Len)/2 + 2;
  9187.     when others =>
  9188.         Index := Len + 1;
  9189.     end case;
  9190.     Out_String := SP.Value(SP.Substr(Temp_String, Index, Len));
  9191.     SP.Release;
  9192.     return Out_String;
  9193.  
  9194. end Justify_String;
  9195.  
  9196. ----------------------------------------------------------------
  9197.  
  9198. function Left_Justify(
  9199.     Text : in STRING;
  9200.     Len  : in POSITIVE;
  9201.     Char : in CHARACTER := ' '
  9202.     ) return STRING is
  9203.  
  9204. begin
  9205.  
  9206.     return Justify_String(Text, Len, Char, LEFT);
  9207.  
  9208. end Left_Justify;
  9209.  
  9210. ----------------------------------------------------------------
  9211.  
  9212. function Right_Justify(
  9213.     Text : in STRING;
  9214.     Len  : in POSITIVE;
  9215.     Char : in CHARACTER := ' '
  9216.     ) return STRING is
  9217.  
  9218. begin
  9219.  
  9220.     return Justify_String(Text, Len, Char, RIGHT);
  9221.  
  9222. end Right_Justify;
  9223.  
  9224. ----------------------------------------------------------------
  9225.  
  9226. function Center(
  9227.     Text : in STRING;
  9228.     Len  : in POSITIVE;
  9229.     Char : in CHARACTER := ' '
  9230.     ) return STRING is
  9231.  
  9232. begin
  9233.  
  9234.     return Justify_String(Text, Len, Char, CENTER);
  9235.  
  9236. end Center;
  9237.  
  9238. ----------------------------------------------------------------
  9239.  
  9240. function Expand(
  9241.     Text : in STRING;
  9242.     Len  : in POSITIVE
  9243.     ) return STRING is
  9244.  
  9245.     Out_String : STRING (1 .. Len);
  9246.     Count      : INTEGER := 0;
  9247.     Size       : INTEGER;
  9248.     Inx1, Inx2 : INTEGER;
  9249.     S_Str      : SP.String_Type;
  9250.  
  9251. begin
  9252.  
  9253.     if Len <= Text'length then
  9254.     return Justify_String(Text, Len, ' ', LEFT);
  9255.     end if;
  9256.     for i in Text'range loop
  9257.     if Text(i) = ' ' then
  9258.         Count := Count + 1;
  9259.     end if;
  9260.     end loop;
  9261.     if Count = 0 then
  9262.     return Justify_String(Text, Len, ' ', LEFT);
  9263.     end if;
  9264.     SP.Mark;
  9265.     S_Str := SP.Create(Text);
  9266.     Size := (Len - Text'length)/ Count;
  9267.     Inx1 := Count/2 - ((Len - Text'length) rem Count)/2 + 1;
  9268.     Inx2 := Inx1 + ((Len - Text'length) rem Count) - 1;
  9269.     declare
  9270.     Fill : STRING(1 .. Size) := (others => ' ');
  9271.     begin
  9272.     for i in reverse 1 .. SP.Length(S_Str) loop
  9273.         if SP.Fetch(S_Str, i) = ' ' then
  9274.         S_Str := SP.Insert(S_Str, Fill, i);
  9275.         if Inx1 <= Count and Count <= Inx2 then
  9276.             S_Str := SP.Insert(S_Str, " ", i);
  9277.         end if;
  9278.         Count := Count - 1;
  9279.         end if;
  9280.     end loop;
  9281.     end;
  9282.     Out_String := SP.Value(S_Str);
  9283.     SP.Release;
  9284.     return Out_String;
  9285.  
  9286. end Expand;
  9287.  
  9288. ----------------------------------------------------------------
  9289.  
  9290. function Format(
  9291.     Text    : in STRING;
  9292.     Len     : in POSITIVE;
  9293.     Del     : in CHARACTER := ' ';
  9294.     Justify : in Justification_Mode := NONE
  9295.     ) return SL.List is
  9296.  
  9297.     Out_String  : STRING(1 .. Len);
  9298.     Temp_String : SP.String_Type;
  9299.     S_Str       : SP.String_Type;
  9300.     Out_List    : SL.List := SL.Create;
  9301.     Index1      : INTEGER;
  9302.     Index2      : INTEGER;
  9303.  
  9304. begin
  9305.  
  9306.     SP.Mark;
  9307.     Temp_String := SP.Create(Text);
  9308.     while SP.Length(Temp_String) > 0 loop 
  9309.     if SP.Length(Temp_String) > Len then
  9310.         Index1 := Len;
  9311.         Index2 := Index1;
  9312.         if Del /= ASCII.NUL then
  9313.         for i in reverse 2 .. Index1 + 1 loop
  9314.             if SP.Fetch(Temp_String, i) = Del then
  9315.             Index1 := i - 1;            
  9316.             Index2 := i;            
  9317.             exit;
  9318.             end if;
  9319.         end loop;
  9320.         end if;
  9321.     else
  9322.         Index1 := SP.Length(Temp_String);
  9323.         Index2 := Index1;
  9324.     end if;
  9325.     S_Str := SP.Substr(Temp_String, 1, Index1);
  9326.     Temp_String := SP.Substr(Temp_String, Index2 + 1, SP.Length(Temp_String) - Index2);
  9327.     case Justify is
  9328.         when LEFT | NONE =>
  9329.         SL.Attach(Out_List, SP.Make_Persistent(
  9330.             STRING'(Justify_String(SP.Value(S_Str), Len, ' ', LEFT))));
  9331.         when RIGHT =>
  9332.         SL.Attach(Out_List, SP.Make_Persistent(
  9333.             STRING'(Justify_String(SP.Value(S_Str), Len, ' ', RIGHT))));
  9334.         when CENTER =>
  9335.         SL.Attach(Out_List, SP.Make_Persistent(
  9336.             STRING'(Justify_String(SP.Value(S_Str), Len, ' ', CENTER))));
  9337.         when EXPAND =>
  9338.         if SP.Length(Temp_String) > 0 then
  9339.             SL.Attach(Out_List, SP.Make_Persistent(
  9340.             STRING'(Expand(SP.Value(S_Str), Len))));
  9341.         else
  9342.             SL.Attach(Out_List, SP.Make_Persistent(
  9343.             STRING'(Justify_String(SP.Value(S_Str), Len, ' ', LEFT))));
  9344.         end if;
  9345.     end case;
  9346.     end loop;
  9347.     SP.Release;
  9348.     return Out_List;
  9349.  
  9350. end Format;
  9351.  
  9352. ----------------------------------------------------------------
  9353.  
  9354. function Image(
  9355.     Num  : in INTEGER;
  9356.     Len  : in NATURAL   := 0;
  9357.     Fill : in CHARACTER := ' '
  9358.     ) return STRING is
  9359.  
  9360.     S_Str  : SP.String_Type;
  9361.     Places : INTEGER := Len;
  9362.     Size   : INTEGER;
  9363.  
  9364. begin
  9365.  
  9366.     SP.Mark;
  9367.     S_Str := SP.Create(INTEGER'image(Num));
  9368.     if SP.Fetch(S_Str, 1) = ' ' then
  9369.     S_Str := SP.Substr(S_Str, 2, SP.Length(S_Str) - 1);
  9370.     end if;
  9371.     Size   := SP.Length(S_Str);
  9372.     if Len = 0 then
  9373.     Places := Size;
  9374.     end if;
  9375.     declare
  9376.     Temp_Text : STRING (1 .. Places);
  9377.     begin
  9378.     for i in 1 .. Places - Size loop
  9379.         Temp_Text(i) := Fill;
  9380.     end loop;
  9381.     Temp_Text(Places - Size + 1 .. Temp_Text'last) := SP.Value(S_Str);
  9382.     SP.Release;
  9383.     return Temp_Text;
  9384.     end;
  9385.     return "";
  9386.  
  9387. end Image;
  9388.  
  9389. ----------------------------------------------------------------
  9390.  
  9391. function Value(
  9392.     Text : in STRING
  9393.     ) return INTEGER is
  9394.  
  9395.     Found      : BOOLEAN;
  9396.     Underscore : BOOLEAN := TRUE;
  9397.  
  9398. begin
  9399.  
  9400.     return INTEGER'Value(Text);
  9401.  
  9402. exception
  9403.     when CONSTRAINT_ERROR =>
  9404.     for i in Text'range loop
  9405.         Found := FALSE;
  9406.         for j in Number'range loop
  9407.         if Text(i) = Number(j) then
  9408.             Underscore := FALSE;
  9409.             Found := TRUE;
  9410.             exit;
  9411.         end if;
  9412.         end loop;
  9413.         if not Found then
  9414.         if Text(i) /= '_' then
  9415.             raise Non_Numeric_String;
  9416.         elsif Underscore then
  9417.             raise Non_Numeric_String;
  9418.         else
  9419.             Underscore := TRUE;
  9420.         end if;
  9421.         end if;
  9422.     end loop;
  9423.     raise Number_Too_Large;
  9424.  
  9425. end Value;
  9426.  
  9427. ----------------------------------------------------------------
  9428.  
  9429. function Match(
  9430.     Pattern    : in STRING;
  9431.     Target     : in STRING;
  9432.     Wildcard   : in CHARACTER := '*';
  9433.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  9434.     ) return BOOLEAN is
  9435.  
  9436.     type State_Type is (NONE, TEXT, WILD);
  9437.  
  9438.     List     : SL.List := SL.Create;
  9439.     Iterator : SL.ListIter;
  9440.     Inx      : INTEGER;
  9441.     R_Str    : SP.String_Type;
  9442.     S_Str    : SP.String_Type;
  9443.     Found    : BOOLEAN;
  9444.     Previous : State_Type;
  9445.     Current  : State_Type;
  9446.     Old_Opt  : SP.Comparison_Option;
  9447.  
  9448. begin
  9449.  
  9450.     Inx := Pattern'first;
  9451.     SP.Mark;
  9452.     for i in Pattern'range loop
  9453.     if Pattern(i) = Wildcard then
  9454.         if i > Inx then
  9455.         SL.Attach(List, SP.Create(Pattern(Inx .. i - 1)));
  9456.         end if;
  9457.         SL.Attach(List, SP.Create("" & Wildcard));
  9458.         Inx := i + 1;
  9459.     end if;
  9460.     end loop;
  9461.     if Inx <= Pattern'last then
  9462.     SL.Attach(List, SP.Create(Pattern(Inx .. Pattern'last)));
  9463.     end if;
  9464.  
  9465.     Iterator := SL.MakeListIter(List);
  9466.     Found := SL.More(Iterator);
  9467.     Current := NONE;    
  9468.     Inx := Target'first;
  9469.     Old_Opt := SP.Get_Comparison_Option;
  9470.     SP.Set_Comparison_Option(Comparison);
  9471.     while SL.More(Iterator) loop
  9472.     SL.Next(Iterator, S_Str);
  9473.     Previous := Current;
  9474.     if SP.Equal(S_Str, "" & Wildcard) then
  9475.         Current := WILD;
  9476.     else
  9477.         Current := TEXT;
  9478.     end if;
  9479.     if Current = TEXT then
  9480.         Found := FALSE;
  9481.         SP.Mark;
  9482.         if Previous = NONE and then
  9483.            Target'length >= Inx + SP.Length(S_Str) - 1 and then 
  9484.            SP.Equal(S_Str, SP.Create(Target(Inx .. Inx + SP.Length(S_Str) - 1))) then
  9485.         Inx   := Inx + SP.Length(S_Str);
  9486.         Found := TRUE;
  9487.         elsif Previous = WILD then
  9488.         for i in Inx .. Target'last - SP.Length(S_Str) + 1 loop
  9489.             SP.Mark;
  9490.             if SP.Equal(S_Str, SP.Create(Target(i .. i + SP.Length(S_Str) - 1))) then
  9491.             Inx   := i + SP.Length(S_Str);
  9492.             Found := TRUE;
  9493.             end if;
  9494.             SP.Release;
  9495.         end loop;
  9496.         end if;
  9497.         SP.Release;
  9498.     end if;
  9499.     exit when not Found;
  9500.     end loop;
  9501.     if Current = TEXT then
  9502.     Found := Inx >= Target'length;
  9503.     end if;
  9504.     SP.Release;
  9505.     SL.Destroy(List);
  9506.     SP.Set_Comparison_Option(Old_Opt);
  9507.     return Found;
  9508.  
  9509. end Match;
  9510.  
  9511. ----------------------------------------------------------------
  9512.                                                                     pragma page;
  9513. package body Generic_String_Utilities is
  9514.  
  9515. ----------------------------------------------------------------
  9516.  
  9517. function Make_Scanner(
  9518.     S : in Generic_String_Type
  9519.     ) return Scanner is
  9520.  
  9521. begin
  9522.  
  9523.     return Make_Scanner(From_Generic(S));
  9524.  
  9525. end Make_Scanner;
  9526.  
  9527. ----------------------------------------------------------------
  9528.  
  9529. function Get_String(
  9530.     T    : in Scanner
  9531.     ) return Generic_String_Type is
  9532.  
  9533. begin
  9534.  
  9535.     if Is_Valid(T) then
  9536.     return To_Generic(SP.Value(T.text));
  9537.     else
  9538.     return To_Generic("");
  9539.     end if;
  9540.  
  9541. end Get_String;
  9542.  
  9543. ----------------------------------------------------------------
  9544.  
  9545. function Get_Remainder(
  9546.     T : in Scanner
  9547.     ) return Generic_String_Type is
  9548.  
  9549.     S_Str : SP.String_Type;
  9550.     G_Str : Generic_String_Type;
  9551.  
  9552. begin
  9553.  
  9554.     if More(T) then
  9555.     SP.Mark;
  9556.     S_Str := SP.Substr(T.text, T.index, SP.Length(T.text) - T.index + 1);
  9557.     declare
  9558.         S : STRING (1 .. SP.Length(S_Str));
  9559.     begin
  9560.         S := SP.Value(S_Str);
  9561.         SP.Release;
  9562.         return To_Generic(S);
  9563.     end;
  9564.     else
  9565.     return To_Generic("");
  9566.     end if;
  9567.  
  9568. end Get_Remainder;
  9569.  
  9570. ----------------------------------------------------------------
  9571.  
  9572. function Get_Segment(
  9573.     T    : in Scanner;
  9574.     From : in POSITIVE;
  9575.     To   : in POSITIVE
  9576.     ) return Generic_String_Type is
  9577.  
  9578. begin
  9579.  
  9580.     if Is_Valid(T) and then
  9581.        From < To and then 
  9582.        To <= SP.Length(T.text) then
  9583.     return To_Generic(SP.Value(T.text)(From .. To - 1));
  9584.     else
  9585.     return To_Generic("");
  9586.     end if;
  9587.     
  9588.  
  9589. end Get_Segment;
  9590.  
  9591. ----------------------------------------------------------------
  9592.  
  9593. procedure Scan_Word(
  9594.     T      : in     Scanner;
  9595.     Found  :    out BOOLEAN;
  9596.     Result :    out Generic_String_Type;
  9597.     Skip   : in     BOOLEAN := FALSE
  9598.     ) is
  9599.  
  9600.     S_Str : SP.String_Type;
  9601.     N     : NATURAL;
  9602.  
  9603. begin
  9604.  
  9605.     if Skip then
  9606.     Skip_Space(T);
  9607.     end if;
  9608.     if Is_Word(T) then
  9609.     Found   := TRUE;
  9610.     SP.Mark;
  9611.     N := SP.Match_Any(T.text, White_Space, T.index);
  9612.     if N = 0 then
  9613.         N := SP.Length(T.text) + 1;
  9614.     end if;
  9615.     S_Str := SP.Substr(T.text, T.index, N - T.index);
  9616.     T.index := N;    
  9617.     declare
  9618.         S : STRING (1 .. SP.Length(S_Str));
  9619.     begin
  9620.         S := SP.Value(S_Str);
  9621.         SP.Release;
  9622.         Result  := To_Generic(S);
  9623.     end;
  9624.     else
  9625.     Found   := FALSE;
  9626.     end if;
  9627.  
  9628. end Scan_Word;
  9629.  
  9630. ----------------------------------------------------------------
  9631.  
  9632. procedure Scan_Number(
  9633.     T      : in     Scanner;
  9634.     Found  :    out BOOLEAN;
  9635.     Result :    out Generic_String_Type;
  9636.     Skip   : in     BOOLEAN := FALSE
  9637.     ) is
  9638.  
  9639. begin
  9640.  
  9641.     if Skip then
  9642.     Skip_Space(T);
  9643.     end if;
  9644.     if Is_Number(T) then
  9645.     Found := TRUE;
  9646.     Result := To_Generic(Get_Number(T));
  9647.     else
  9648.     Found := FALSE;
  9649.     end if;
  9650.  
  9651. end Scan_Number;
  9652.  
  9653. ----------------------------------------------------------------
  9654.  
  9655. procedure Scan_Signed_Number(
  9656.     T      : in     Scanner;
  9657.     Found  :    out BOOLEAN;
  9658.     Result :    out Generic_String_Type;
  9659.     Skip   : in     BOOLEAN := FALSE
  9660.     ) is
  9661.  
  9662. begin
  9663.  
  9664.     if Skip then
  9665.     Skip_Space(T);
  9666.     end if;
  9667.     if Is_Signed_Number(T) then
  9668.     Found := TRUE;
  9669.     Result := To_Generic(Get_Signed_Number(T));
  9670.     else
  9671.     Found := FALSE;
  9672.     end if;
  9673.  
  9674. end Scan_Signed_Number;
  9675.  
  9676. ----------------------------------------------------------------
  9677.  
  9678. procedure Scan_Space(
  9679.     T      : in     Scanner;
  9680.     Found  :    out BOOLEAN;
  9681.     Result :    out Generic_String_Type
  9682.     ) is
  9683.  
  9684.     S_Str : SP.String_Type;
  9685.  
  9686. begin
  9687.  
  9688.     if Is_Any(T, White_Space) then
  9689.     SP.Mark;
  9690.     Scan_Any(T, White_Space, Found, S_Str);
  9691.     declare
  9692.         S : STRING (1 .. SP.Length(S_Str));
  9693.     begin
  9694.         S := SP.Value(S_Str);
  9695.         SP.Release;
  9696.         Result := To_Generic(S);
  9697.     end;
  9698.     else
  9699.     Found := FALSE;
  9700.     end if;
  9701.  
  9702. end Scan_Space;
  9703.  
  9704. ----------------------------------------------------------------
  9705.  
  9706. procedure Scan_Ada_Id(
  9707.     T      : in     Scanner;
  9708.     Found  :    out BOOLEAN;
  9709.     Result :    out Generic_String_Type;
  9710.     Skip   : in     BOOLEAN := FALSE
  9711.     ) is
  9712.  
  9713.     S_Str : SP.String_Type;
  9714.     Num   : NATURAL;
  9715.     Mark  : POSITIVE;
  9716.  
  9717. begin
  9718.  
  9719.     if Skip then
  9720.     Skip_Space(T);
  9721.     end if;
  9722.     if Is_Ada_Id(T) then
  9723.     SP.Mark;
  9724.     Mark := T.index;
  9725.     Scan_Any(T, Alphabetic & Number & '_', Found, S_Str);
  9726.     Num := SP.Match_S(S_Str, "__");
  9727.     if Num /= 0 then
  9728.         S_Str := SP.Substr(S_Str, 1, Num -1);
  9729.         Mark := Mark + Num - 1;
  9730.     else
  9731.         Num := SP.Length(S_Str);
  9732.         if SP.Fetch(S_Str, Num) = '_' then
  9733.         S_Str := SP.Substr(S_Str, 1, Num - 1);
  9734.         Mark := Mark + Num - 1;
  9735.         else
  9736.         Mark := Mark + Num;
  9737.         end if;
  9738.     end if;
  9739.     T.index := Mark;
  9740.     declare
  9741.         S : STRING (1 .. SP.Length(S_Str));
  9742.     begin
  9743.         S := SP.Value(S_Str);
  9744.         SP.Release;
  9745.         Result := To_Generic(S);
  9746.     end;
  9747.     else
  9748.     Found := FALSE;
  9749.     end if;
  9750.  
  9751. end Scan_Ada_Id;
  9752.  
  9753. ----------------------------------------------------------------
  9754.  
  9755. procedure Scan_Quoted(
  9756.     T      : in     Scanner;
  9757.     Found  :    out BOOLEAN;
  9758.     Result :    out Generic_String_Type;
  9759.     Skip   : in     BOOLEAN := FALSE
  9760.     ) is
  9761.  
  9762.     S_Str : SP.String_Type;
  9763.     Count : INTEGER;
  9764.  
  9765. begin
  9766.  
  9767.     if Skip then
  9768.     Skip_Space(T);
  9769.     end if;
  9770.     Count := Quoted_String(T);
  9771.     if Count /= 0 then
  9772.     Found := TRUE;
  9773.     Count := Count - 2;
  9774.     T.index := T.index + 1;
  9775.     if Count /= 0 then
  9776.         SP.Mark;
  9777.         S_Str := SP.Substr(T.text, T.index, POSITIVE(Count));
  9778.         declare
  9779.         S : STRING (1 .. SP.Length(S_Str));
  9780.         begin
  9781.         S := SP.Value(S_Str);
  9782.         SP.Release;
  9783.         Result := To_Generic(S);
  9784.         end;
  9785.     else
  9786.         Result := To_Generic("");
  9787.     end if;
  9788.     T.index := T.index + Count + 1;
  9789.     else
  9790.     Found := FALSE;
  9791.     end if;
  9792.  
  9793. end Scan_Quoted;
  9794.  
  9795. ----------------------------------------------------------------
  9796.  
  9797. procedure Scan_Enclosed(
  9798.     B      : in     CHARACTER;
  9799.     E      : in     CHARACTER;
  9800.     T      : in     Scanner;
  9801.     Found  :    out BOOLEAN;
  9802.     Result :    out Generic_String_Type;
  9803.     Skip   : in     BOOLEAN := FALSE
  9804.     ) is
  9805.  
  9806.     S_Str : SP.String_Type;
  9807.     Count : NATURAL;
  9808.  
  9809. begin
  9810.  
  9811.     if Skip then
  9812.     Skip_Space(T);
  9813.     end if;
  9814.     Count := Enclosed_String(B, E, T);
  9815.     if Count /= 0 then
  9816.     Found := TRUE;
  9817.     Count := Count - 2;
  9818.     T.index := T.index + 1;
  9819.     if Count /= 0 then
  9820.         SP.Mark;
  9821.         S_Str := SP.Substr(T.text, T.index, POSITIVE(Count));
  9822.         declare
  9823.         S : STRING (1 .. SP.Length(S_Str));
  9824.         begin
  9825.         S := SP.Value(S_Str);
  9826.         SP.Release;
  9827.         Result := To_Generic(S);
  9828.         end;
  9829.     else
  9830.         Result := To_Generic("");
  9831.     end if;
  9832.     T.index := T.index + Count + 1;
  9833.     else
  9834.     Found := FALSE;
  9835.     end if;
  9836.  
  9837. end Scan_Enclosed;
  9838.  
  9839. ----------------------------------------------------------------
  9840.  
  9841. function Is_Sequence(
  9842.     Chars  : in Generic_String_Type;
  9843.     T      : in Scanner
  9844.     ) return BOOLEAN is
  9845.  
  9846. begin
  9847.  
  9848.     return Is_Any(T, From_Generic(Chars));
  9849.  
  9850. end Is_Sequence;
  9851.  
  9852. ----------------------------------------------------------------
  9853.  
  9854. procedure Scan_Sequence(
  9855.     Chars  : in     Generic_String_Type;
  9856.     T      : in     Scanner;
  9857.     Found  :    out BOOLEAN;
  9858.     Result :    out Generic_String_Type;
  9859.     Skip   : in     BOOLEAN := FALSE
  9860.     ) is
  9861.  
  9862. begin
  9863.  
  9864.     Scan_Sequence(From_Generic(Chars), T, Found, Result, Skip);
  9865.  
  9866. end Scan_Sequence;
  9867.  
  9868. ----------------------------------------------------------------
  9869.  
  9870. procedure Scan_Sequence(
  9871.     Chars  : in     STRING;
  9872.     T      : in     Scanner;
  9873.     Found  :    out BOOLEAN;
  9874.     Result :    out Generic_String_Type;
  9875.     Skip   : in     BOOLEAN := FALSE
  9876.     ) is
  9877.  
  9878.     I     : POSITIVE;
  9879.     Count : INTEGER := 0;
  9880.     S_Str : SP.String_Type;
  9881.  
  9882. begin
  9883.  
  9884.     if Skip then
  9885.     Skip_Space(T);
  9886.     end if;
  9887.     if not Is_Valid(T) then
  9888.     Found := FALSE;
  9889.     return;
  9890.     end if;
  9891.     I := T.index;
  9892.     while Is_Any(T, Chars) loop
  9893.     T.index := T.index + 1;
  9894.     Count := Count + 1;
  9895.     end loop;
  9896.     if Count /= 0 then
  9897.     Found  := TRUE;
  9898.     SP.Mark;
  9899.     S_Str := SP.Substr(T.text, I, POSITIVE(Count));
  9900.     declare
  9901.         S : STRING (1 .. SP.Length(S_Str));
  9902.     begin
  9903.         S := SP.Value(S_Str);
  9904.         SP.Release;
  9905.         Result := To_Generic(S);
  9906.     end;
  9907.     else
  9908.     Found := FALSE;
  9909.     end if;
  9910.  
  9911. end Scan_Sequence;
  9912.  
  9913. ----------------------------------------------------------------
  9914.  
  9915. function Is_Not_Sequence(
  9916.     Chars  : in Generic_String_Type;
  9917.     T      : in Scanner
  9918.     ) return BOOLEAN is
  9919.  
  9920. begin
  9921.  
  9922.     return Is_Not_Sequence(From_Generic(Chars), T);
  9923.  
  9924. end Is_Not_Sequence;
  9925.  
  9926. ----------------------------------------------------------------
  9927.  
  9928. procedure Scan_Not_Sequence(
  9929.     Chars  : in     STRING;
  9930.     T      : in     Scanner;
  9931.     Found  :    out BOOLEAN;
  9932.     Result :    out Generic_String_Type;
  9933.     Skip   : in     BOOLEAN := FALSE
  9934.     ) is
  9935.  
  9936.     S_Str : SP.String_Type;
  9937.     N     : NATURAL;
  9938.  
  9939. begin
  9940.  
  9941.     if Skip then
  9942.     Skip_Space(T);
  9943.     end if;
  9944.     if Is_Not_Sequence(Chars, T) then
  9945.     Found   := TRUE;
  9946.     SP.Mark;
  9947.     N := SP.Match_Any(T.text, Chars, T.index);
  9948.     S_Str := SP.Substr(T.text, T.index, N - T.index);
  9949.     T.index := N;
  9950.     declare
  9951.         S : STRING (1 .. SP.Length(S_Str));
  9952.     begin
  9953.         S := SP.Value(S_Str);
  9954.         SP.Release;
  9955.         Result := To_Generic(S);
  9956.     end;
  9957.     else
  9958.     Found := FALSE;
  9959.     end if;
  9960.  
  9961. end Scan_Not_Sequence;
  9962.  
  9963. ----------------------------------------------------------------
  9964.  
  9965. procedure Scan_Not_Sequence(
  9966.     Chars  : in     Generic_String_Type;
  9967.     T      : in     Scanner;
  9968.     Found  :    out BOOLEAN;
  9969.     Result :    out Generic_String_Type;
  9970.     Skip   : in     BOOLEAN := FALSE
  9971.     ) is
  9972.  
  9973. begin
  9974.  
  9975.     Scan_Not_Sequence(From_Generic(Chars), T, Found, Result, Skip);
  9976.  
  9977. end Scan_Not_Sequence;
  9978.  
  9979. ----------------------------------------------------------------
  9980.  
  9981. function Is_Literal(
  9982.     Chars  : in Generic_String_Type;
  9983.     T      : in Scanner
  9984.     ) return BOOLEAN is
  9985.  
  9986. begin
  9987.  
  9988.     return Is_Literal(From_Generic(Chars), T);
  9989.  
  9990. end Is_Literal;
  9991.  
  9992. ----------------------------------------------------------------
  9993.  
  9994. procedure Scan_Literal(
  9995.     Chars  : in     STRING;
  9996.     T      : in     Scanner;
  9997.     Found  :    out BOOLEAN;
  9998.     Skip   : in     BOOLEAN := FALSE
  9999.     ) is
  10000.  
  10001. begin
  10002.  
  10003.     if Skip then
  10004.     Skip_Space(T);
  10005.     end if;
  10006.     if Is_Literal(Chars, T) then
  10007.     T.index := T.index + Chars'length;
  10008.     Found   := TRUE;
  10009.     else
  10010.     Found   := FALSE;
  10011.     end if;
  10012.  
  10013. end Scan_Literal;
  10014.  
  10015. ----------------------------------------------------------------
  10016.  
  10017. procedure Scan_Literal(
  10018.     Chars  : in     Generic_String_Type;
  10019.     T      : in     Scanner;
  10020.     Found  :    out BOOLEAN;
  10021.     Skip   : in     BOOLEAN := FALSE
  10022.     ) is
  10023.  
  10024.     F : BOOLEAN;
  10025.  
  10026. begin
  10027.  
  10028.     Scan_Literal(From_Generic(Chars), T, Found, Skip);
  10029.  
  10030. end Scan_Literal;
  10031.  
  10032. ----------------------------------------------------------------
  10033.  
  10034. function Is_Not_Literal(
  10035.     Chars : in Generic_String_Type;
  10036.     T     : in Scanner
  10037.     ) return BOOLEAN is
  10038.  
  10039. begin
  10040.  
  10041.     return Is_Not_Literal(From_Generic(Chars), T);
  10042.  
  10043. end Is_Not_Literal;
  10044.  
  10045. ----------------------------------------------------------------
  10046.  
  10047. procedure Scan_Not_Literal(
  10048.     Chars  : in     STRING;
  10049.     T      : in     Scanner;
  10050.     Found  :    out BOOLEAN;
  10051.     Result :    out Generic_String_Type;
  10052.     Skip   : in     BOOLEAN := FALSE
  10053.     ) is
  10054.  
  10055.     S_Str : SP.String_Type;
  10056.     N     : NATURAL;
  10057.  
  10058. begin
  10059.  
  10060.     if Skip then
  10061.     Skip_Space(T);
  10062.     end if;
  10063.     if Is_Not_Literal(Chars, T) then
  10064.     Found   := TRUE;
  10065.     SP.Mark;
  10066.     N := SP.Match_S(T.text, Chars, T.index);
  10067.     S_Str := SP.Substr(T.text, T.index, N - T.index);
  10068.     T.index := N;
  10069.     declare
  10070.         S : STRING (1 .. SP.Length(S_Str));
  10071.     begin
  10072.         S := SP.Value(S_Str);
  10073.         SP.Release;
  10074.         Result := To_Generic(S);
  10075.     end;
  10076.     else
  10077.     Found := FALSE;
  10078.     end if;
  10079.  
  10080. end Scan_Not_Literal;
  10081.  
  10082. ----------------------------------------------------------------
  10083.  
  10084. procedure Scan_Not_Literal(
  10085.     Chars  : in     Generic_String_Type;
  10086.     T      : in     Scanner;
  10087.     Found  :    out BOOLEAN;
  10088.     Result :    out Generic_String_Type;
  10089.     Skip   : in     BOOLEAN := FALSE
  10090.     ) is
  10091.  
  10092. begin
  10093.  
  10094.     Scan_Not_Literal(From_Generic(Chars), T, Found, Result, Skip);
  10095.  
  10096. end Scan_Not_Literal;
  10097.  
  10098. ----------------------------------------------------------------
  10099.  
  10100. function Strip_Leading(
  10101.     Text : in Generic_String_Type;
  10102.     Char : in STRING := " " & ASCII.HT
  10103.     ) return STRING is
  10104.  
  10105. begin
  10106.  
  10107.     return Strip_Leading(From_Generic(Text), Char);
  10108.  
  10109. end Strip_Leading;
  10110.  
  10111. ----------------------------------------------------------------
  10112.  
  10113. function Strip_Leading(
  10114.     Text : in STRING;
  10115.     Char : in STRING := " " & ASCII.HT
  10116.     ) return Generic_String_Type is
  10117.  
  10118. begin
  10119.  
  10120.     return To_Generic(STRING'(Strip_Leading(Text, Char)));
  10121.  
  10122. end Strip_Leading;
  10123.  
  10124. ----------------------------------------------------------------
  10125.  
  10126. function Strip_Leading(
  10127.     Text : in Generic_String_Type;
  10128.     Char : in STRING := " " & ASCII.HT
  10129.     ) return Generic_String_Type is
  10130.  
  10131.     G_Str : Generic_String_Type;
  10132.  
  10133. begin
  10134.  
  10135.     return To_Generic(STRING'(Strip_Leading(From_Generic(Text), Char)));
  10136.  
  10137. end Strip_Leading;
  10138.  
  10139. ----------------------------------------------------------------
  10140.  
  10141. function Strip_Trailing(
  10142.     Text : in Generic_String_Type;
  10143.     Char : in STRING := " " & ASCII.HT
  10144.     ) return STRING is
  10145.  
  10146. begin
  10147.  
  10148.     return Strip_Trailing(From_Generic(Text), Char);
  10149.  
  10150. end Strip_Trailing;
  10151.  
  10152. ----------------------------------------------------------------
  10153.  
  10154. function Strip_Trailing(
  10155.     Text : in STRING;
  10156.     Char : in STRING := " " & ASCII.HT
  10157.     ) return Generic_String_Type is
  10158.  
  10159. begin
  10160.  
  10161.     return To_Generic(STRING'(Strip_Trailing(Text, Char)));
  10162.  
  10163. end Strip_Trailing;
  10164.  
  10165. ----------------------------------------------------------------
  10166.  
  10167. function Strip_Trailing(
  10168.     Text : in Generic_String_Type;
  10169.     Char : in STRING := " " & ASCII.HT
  10170.     ) return Generic_String_Type is
  10171.  
  10172. begin
  10173.  
  10174.     return To_Generic(STRING'(Strip_Trailing(From_Generic(Text), Char)));
  10175.  
  10176. end Strip_Trailing;
  10177.  
  10178. ----------------------------------------------------------------
  10179.  
  10180. function Strip( 
  10181.     Text : in Generic_String_Type;
  10182.     Char : in STRING := " " & ASCII.HT
  10183.     ) return STRING is
  10184.  
  10185. begin
  10186.  
  10187.     return Strip_Leading(STRING'(Strip_Trailing(From_Generic(Text), Char)), Char);
  10188.  
  10189. end Strip;
  10190.  
  10191. ----------------------------------------------------------------
  10192.  
  10193. function Strip(
  10194.     Text : in STRING;
  10195.     Char : in STRING := " " & ASCII.HT
  10196.     ) return Generic_String_Type is
  10197.  
  10198. begin
  10199.  
  10200.     return To_Generic(STRING'(Strip_Leading(STRING'(Strip_Trailing(Text, Char)), Char)));
  10201.  
  10202. end Strip;
  10203.  
  10204. ----------------------------------------------------------------
  10205.  
  10206. function Strip(
  10207.     Text : in Generic_String_Type;
  10208.     Char : in STRING := " " & ASCII.HT
  10209.     ) return Generic_String_Type is
  10210.  
  10211. begin
  10212.  
  10213.     return To_Generic(STRING'(Strip_Leading(STRING'(Strip_Trailing(From_Generic(Text), Char)), Char)));
  10214.  
  10215. end Strip;
  10216.  
  10217. ----------------------------------------------------------------
  10218.  
  10219. function Left_Justify(
  10220.     Text : in Generic_String_Type;
  10221.     Len  : in POSITIVE;
  10222.     Char : in CHARACTER := ' '
  10223.     ) return STRING is
  10224.  
  10225. begin
  10226.  
  10227.     return Justify_String(From_Generic(Text), Len, Char, LEFT);
  10228.  
  10229. end Left_Justify;
  10230.  
  10231. ----------------------------------------------------------------
  10232.  
  10233. function Left_Justify(
  10234.     Text : in STRING;
  10235.     Len  : in POSITIVE;
  10236.     Char : in CHARACTER := ' '
  10237.     ) return Generic_String_Type is
  10238.  
  10239. begin
  10240.  
  10241.     return To_Generic(Justify_String(Text, Len, Char, LEFT));
  10242.  
  10243. end Left_Justify;
  10244.  
  10245. ----------------------------------------------------------------
  10246.  
  10247. function Left_Justify(
  10248.     Text : in Generic_String_Type;
  10249.     Len  : in POSITIVE;
  10250.     Char : in CHARACTER := ' '
  10251.     ) return Generic_String_Type is
  10252.  
  10253. begin
  10254.  
  10255.     return To_Generic(Justify_String(From_Generic(Text), Len, Char, LEFT));
  10256.  
  10257. end Left_Justify;
  10258.  
  10259. ----------------------------------------------------------------
  10260.  
  10261. function Right_Justify(
  10262.     Text : in Generic_String_Type;
  10263.     Len  : in POSITIVE;
  10264.     Char : in CHARACTER := ' '
  10265.     ) return STRING is
  10266.  
  10267. begin
  10268.  
  10269.     return Justify_String(From_Generic(Text), Len, Char, RIGHT);
  10270.  
  10271. end Right_Justify;
  10272.  
  10273. ----------------------------------------------------------------
  10274.  
  10275. function Right_Justify(
  10276.     Text : in STRING;
  10277.     Len  : in POSITIVE;
  10278.     Char : in CHARACTER := ' '
  10279.     ) return Generic_String_Type is
  10280.  
  10281. begin
  10282.  
  10283.     return To_Generic(Justify_String(Text, Len, Char, RIGHT));
  10284.  
  10285. end Right_Justify;
  10286.  
  10287. ----------------------------------------------------------------
  10288.  
  10289. function Right_Justify(
  10290.     Text : in Generic_String_Type;
  10291.     Len  : in POSITIVE;
  10292.     Char : in CHARACTER := ' '
  10293.     ) return Generic_String_Type is
  10294.  
  10295. begin
  10296.  
  10297.     return To_Generic(Justify_String(From_Generic(Text), Len, Char, RIGHT));
  10298.  
  10299. end Right_Justify;
  10300.  
  10301. ----------------------------------------------------------------
  10302.  
  10303. function Center(
  10304.     Text : in Generic_String_Type;
  10305.     Len  : in POSITIVE;
  10306.     Char : in CHARACTER := ' '
  10307.     ) return STRING is
  10308.  
  10309. begin
  10310.  
  10311.     return Justify_String(From_Generic(Text), Len, Char, CENTER);
  10312.  
  10313. end Center;
  10314.  
  10315. ----------------------------------------------------------------
  10316.  
  10317. function Center(
  10318.     Text : in STRING;
  10319.     Len  : in POSITIVE;
  10320.     Char : in CHARACTER := ' '
  10321.     ) return Generic_String_Type is
  10322.  
  10323. begin
  10324.  
  10325.     return To_Generic(Justify_String(Text, Len, Char, CENTER));
  10326.  
  10327. end Center;
  10328.  
  10329. ----------------------------------------------------------------
  10330.  
  10331. function Center(
  10332.     Text : in Generic_String_Type;
  10333.     Len  : in POSITIVE;
  10334.     Char : in CHARACTER := ' '
  10335.     ) return Generic_String_Type is
  10336.  
  10337. begin
  10338.  
  10339.     return To_Generic(Justify_String(From_Generic(Text), Len, Char, CENTER));
  10340.  
  10341. end Center;
  10342.  
  10343. ----------------------------------------------------------------
  10344.  
  10345. function Expand(
  10346.     Text : in Generic_String_Type;
  10347.     Len  : in POSITIVE
  10348.     ) return STRING is
  10349.  
  10350. begin
  10351.  
  10352.     return Expand(From_Generic(Text), Len);
  10353.  
  10354. end Expand;
  10355.  
  10356. ----------------------------------------------------------------
  10357.  
  10358. function Expand(
  10359.     Text : in STRING;
  10360.     Len  : in POSITIVE
  10361.     ) return Generic_String_Type is
  10362.  
  10363. begin
  10364.  
  10365.     return To_Generic(Expand(Text, Len));
  10366.  
  10367. end Expand;
  10368.  
  10369. ----------------------------------------------------------------
  10370.  
  10371. function Expand(
  10372.     Text : in Generic_String_Type;
  10373.     Len  : in POSITIVE
  10374.     ) return Generic_String_Type is
  10375.  
  10376. begin
  10377.  
  10378.     return To_Generic(Expand(From_Generic(Text), Len));
  10379.  
  10380. end Expand;
  10381.  
  10382. ----------------------------------------------------------------
  10383.  
  10384. function Format(
  10385.     Text    : in Generic_String_Type;
  10386.     Len     : in POSITIVE;
  10387.     Del     : in CHARACTER := ' ';
  10388.     Justify : in Justification_Mode := NONE
  10389.     ) return SL.List is
  10390.  
  10391. begin
  10392.  
  10393.     return Format(From_Generic(Text), Len, Del, Justify);
  10394.  
  10395. end Format;
  10396.  
  10397. ----------------------------------------------------------------
  10398.  
  10399. function Image(
  10400.     Num  : in INTEGER;
  10401.     Len  : in NATURAL   := 0;
  10402.     Fill : in CHARACTER := ' '
  10403.     ) return Generic_String_Type is
  10404.  
  10405. begin
  10406.  
  10407.     return To_Generic(STRING'(Image(Num, Len, Fill)));
  10408.  
  10409. end Image;
  10410.  
  10411. ----------------------------------------------------------------
  10412.  
  10413. function Value(
  10414.     Text : in Generic_String_Type
  10415.     ) return INTEGER is
  10416.  
  10417. begin
  10418.  
  10419.     return Value(STRING'(From_Generic(Text)));
  10420.  
  10421. end Value;
  10422.  
  10423. ----------------------------------------------------------------
  10424.  
  10425. function Match(
  10426.     Pattern    : in Generic_String_Type;
  10427.     Target     : in STRING;
  10428.     Wildcard   : in CHARACTER := '*';
  10429.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  10430.     ) return BOOLEAN is
  10431.  
  10432. begin
  10433.  
  10434.     return Match(From_Generic(Pattern),
  10435.          Target,
  10436.          Wildcard,
  10437.          Comparison);
  10438.  
  10439. end Match;
  10440.  
  10441. ----------------------------------------------------------------
  10442.  
  10443. function Match(
  10444.     Pattern    : in STRING;
  10445.     Target     : in Generic_String_Type;
  10446.     Wildcard   : in CHARACTER := '*';
  10447.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  10448.     ) return BOOLEAN is
  10449.  
  10450. begin
  10451.  
  10452.     return Match(Pattern,
  10453.          From_Generic(Target),
  10454.          Wildcard,
  10455.          Comparison);
  10456.  
  10457. end Match;
  10458.  
  10459. ----------------------------------------------------------------
  10460.  
  10461. function Match(
  10462.     Pattern    : in Generic_String_Type;
  10463.     Target     : in Generic_String_Type;
  10464.     Wildcard   : in CHARACTER := '*';
  10465.     Comparison : in SP.Comparison_Option := SP.CASE_SENSITIVE
  10466.     ) return BOOLEAN is
  10467.  
  10468. begin
  10469.  
  10470.     return Match(From_Generic(Pattern),
  10471.          From_Generic(Target),
  10472.          Wildcard,
  10473.          Comparison);
  10474.  
  10475. end Match;
  10476.  
  10477. ----------------------------------------------------------------
  10478.  
  10479.  
  10480. end Generic_String_Utilities;
  10481.  
  10482. end String_Utilities;
  10483.                                                                     pragma page;
  10484. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10485. --HOSTLIB.SPC
  10486. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10487.  
  10488. package Host_Lib is
  10489.  
  10490. --| Host dependent subprograms
  10491.  
  10492. --| Overview
  10493. --| This package provides a common interface to the user for functions whose
  10494. --| implementations are host dependent.
  10495. --|-
  10496. --| Set_Error              Directs default output to appropriate error output 
  10497. --| Reset_Error            Resets above
  10498. --| Put_Error              Writes an error message to appropriate error output
  10499. --| Return_Code            Sets return code
  10500. --| Invoke                 Runs a program
  10501. --| Get_Item               Returns specified item from the system
  10502. --| Read_No_Echo           Returns keyboard without echoing
  10503. --| Protection             Returns protection setting string
  10504. --| Get_Time               Obtains current date/time
  10505. --| Date                   Returns current date (MM/DD/YY)
  10506. --| Calendar_Date          Returns current date (eg. March 15, 1985)
  10507. --| Time                   Returns current time (HH:MM:SS)
  10508. --| Get_Terminal_Type      Returns attached terminal type
  10509. --| Enable_Interrupt_Trap  Enables trapping of interrupt from the keyboard
  10510. --| Disable_Interrupt_Trap Disables interrupt trapping
  10511. --| Ignore_Interrupts      Ignore interrupts from the keyboard
  10512. --| Interrupts_Ignored     Returns TRUE iff interrupt was ignored
  10513. --| Set_Interrupt_State    Sets the interrupt trapping state
  10514. --| Get_Interrupt_State    Returns the interrupt trapping state
  10515. --|+
  10516.  
  10517. ----------------------------------------------------------------
  10518.  
  10519. Uninitialized_Time_Value : exception;    --| Raised when time value not set
  10520. Terminal_Not_Attached    : exception;    --| Raised when no terminal attached
  10521. Unknown_Terminal_Type    : exception;    --| Raised when terminal unknown
  10522. Interrupt_Encountered    : exception;   --| Raised when Trap_Interrupts has
  10523.                                         --| been called and an interrupt was
  10524.                                         --| encountered.
  10525.  
  10526. ----------------------------------------------------------------
  10527.  
  10528. type Severity_Code is (            --| Systen independent error indication
  10529.     SUCCESS, INFORMATION, WARNING, ERROR, SEVERE
  10530.     );
  10531.  
  10532. type Item_Type is (            --| Items to be obtained from system
  10533.     ARGUMENTS, USER_NAME, ACCOUNT, PROGRAM_NAME, PROCESS_MODE,
  10534.     PROCESS_ID, TERMINAL_ADDRESS, DEVICE_TYPE
  10535.     );
  10536.  
  10537. type Time_Value is limited private;    --| Current date/time marker
  10538.  
  10539. type Format is (RAW, EDIT);        --| Return value format
  10540.  
  10541. type Permission is (YES, NO);        --| Protection status
  10542.  
  10543. type Protection_Category is (READ, WRITE, EXECUTE, DELETE);
  10544.  
  10545. type Protection_Specification is array (Protection_Category) of Permission;
  10546.  
  10547. type Terminal_Type is (            --| Known terminal types
  10548.     VT05,
  10549.     VK100,
  10550.     VT173,
  10551.     TQ_BTS,
  10552.     TEK401X,
  10553.     FOREIGN_TERMINAL_1,
  10554.     FOREIGN_TERMINAL_2,
  10555.     FOREIGN_TERMINAL_3,
  10556.     FOREIGN_TERMINAL_4,
  10557.     FOREIGN_TERMINAL_5,
  10558.     FOREIGN_TERMINAL_6,
  10559.     FOREIGN_TERMINAL_7,
  10560.     FOREIGN_TERMINAL_8,
  10561.     LA36,
  10562.     LA120,
  10563.     LA34,
  10564.     LA38,
  10565.     LA12,
  10566.     LA24,
  10567.     LQP02,
  10568.     LA84,
  10569.     VT52,
  10570.     VT55,
  10571.     DZ11,
  10572.     DZ32,
  10573.     DZ730,
  10574.     DMZ32,
  10575.     DHV,
  10576.     DHU,
  10577.     VT100,
  10578.     VT101,
  10579.     VT102,
  10580.     VT105,
  10581.     VT125,
  10582.     VT131,
  10583.     VT132,
  10584.     VT200_SERIES,
  10585.     PRO_SERIES,
  10586.         WORKSTATION,        -- Workstations
  10587.     VS100,
  10588.     VS125,
  10589.     VS300,
  10590.     VIRTUAL_DEVICE);
  10591.  
  10592. type Interrupt_State is (ENABLED, DISABLED, IGNORED);
  10593.  
  10594. ----------------------------------------------------------------
  10595.  
  10596. Max_Arg_Length : constant POSITIVE := 255;
  10597.                     --| Maximum chars per line
  10598.  
  10599. ----------------------------------------------------------------
  10600.  
  10601. procedure Set_Error;            --| Direct error output
  10602.  
  10603. --| Effects: Set the default output to an error output stream so that all
  10604. --| subsequent outputs without file_type specification is directed to the
  10605. --| error output.
  10606. --| N/A: Raises, Modifies, Errors
  10607.  
  10608. ----------------------------------------------------------------
  10609.  
  10610. procedure Reset_Error;            --| Resets the defualt output
  10611.  
  10612. --| Effects: Reset the default output to standard output.  (Used in conjunction
  10613. --| with Set_Error.
  10614. --| N/A: Raises, Modifies, Errors
  10615.  
  10616. ----------------------------------------------------------------
  10617.  
  10618. procedure Put_Error(            --| Write a error message
  10619.     Message : in STRING            --| Message to be written
  10620.     );
  10621.  
  10622. --| Effects: Writes the error message to the error output.  The message is
  10623. --| prepended with an appropriate error message indication.
  10624. --| N/A: Raises, Modifies, Errors
  10625.  
  10626. ----------------------------------------------------------------
  10627.  
  10628. function Return_Code(            --| Set return code
  10629.     Severity : in Severity_Code        --| Return code to be set
  10630.     ) return INTEGER;
  10631.  
  10632. --| Effects: Sets a system dependent return value based on the given return
  10633. --| indication.
  10634. --| N/A: Raises, Modifies, Errors
  10635.  
  10636. ----------------------------------------------------------------    
  10637.  
  10638. procedure Invoke(            --| Invoke a program
  10639.     Process  : in     STRING;        --| Name and arugment(s) of the program
  10640.     Severity :    out Severity_Code    --| Systen independent error indication
  10641.     );
  10642.  
  10643. --| Effects: Runs the specified program with the given arguments.
  10644. --| N/A: Raises, Modifies, Errors
  10645.  
  10646. ----------------------------------------------------------------    
  10647.  
  10648. function Get_Item(            --| Get specified item from system
  10649.     Item : in Item_Type;        --| Item to be obtained
  10650.     Form : in Format := EDIT        --| Format the result
  10651.     ) return STRING;
  10652.  
  10653. --| Raises : Terminal_Not_Attached, Unknown_Terminal_Type
  10654. --| Effects: Obtains the specified item from the system.
  10655. --| N/A: Modifies, Errors
  10656.  
  10657. ----------------------------------------------------------------    
  10658.  
  10659. function Read_No_Echo(            --| Read a string from keyboard
  10660.     Address : in STRING := Get_Item(TERMINAL_ADDRESS)
  10661.                     --| Terminal address
  10662.     ) return STRING;
  10663.  
  10664. --| Effects: Reads characters entered from the keyboard without echoing.
  10665. --| N/A: Raises, Modifies, Errors
  10666.  
  10667. ----------------------------------------------------------------    
  10668.  
  10669. function Protection(            --| Read a string from keyboard
  10670.     System : in Protection_Specification :=
  10671.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES);
  10672.                     --| Protection for system
  10673.     Owner  : in Protection_Specification :=
  10674.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES);
  10675.                     --| Protection for owner
  10676.     Group  : in Protection_Specification :=
  10677.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES);
  10678.                     --| Protection for group
  10679.     World  : in Protection_Specification :=
  10680.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES)
  10681.                     --| Protection for world
  10682.     ) return STRING;
  10683.  
  10684. --| Effects: Returns a string to be used in the FORM arugment of standard
  10685. --| I/O package Open/Create subprograms.
  10686. --| N/A: Raises, Modifies, Errors
  10687.  
  10688. ----------------------------------------------------------------
  10689.  
  10690. procedure Get_Time(            --| Get date/time
  10691.     Value : out Time_Value        --| Time value to be returned
  10692.     );
  10693.  
  10694. --| Effects: Obaints current date/time.
  10695. --| N/A: Raises, Modifies, Errors
  10696.  
  10697. ----------------------------------------------------------------
  10698.  
  10699. function "="(                --| Compare two date/time
  10700.     Left  : in Time_Value;
  10701.     Right : in Time_Value
  10702.     ) return BOOLEAN;
  10703.  
  10704. --| Raises : Uninitialized_Time_Value
  10705. --| Effects: TRUE if two date/times are equal; FALSE otherwise.
  10706. --| N/A: Modifies, Errors
  10707.  
  10708. ----------------------------------------------------------------
  10709.  
  10710. function "<"(                --| Compare two date/time
  10711.     Left  : in Time_Value;
  10712.     Right : in Time_Value
  10713.     ) return BOOLEAN;
  10714.  
  10715. --| Raises : Uninitialized_Time_Value
  10716. --| Effects: TRUE if Left is less than Right; FALSE otherwise.
  10717. --| N/A: Modifies, Errors
  10718.  
  10719. ----------------------------------------------------------------
  10720.  
  10721. function ">"(                --| Compare two date/time
  10722.     Left  : in Time_Value;
  10723.     Right : in Time_Value
  10724.     ) return BOOLEAN;
  10725.  
  10726. --| Raises : Uninitialized_Time_Value
  10727. --| Effects: TRUE if Left is greater than Right; FALSE otherwise.
  10728. --| N/A: Modifies, Errors
  10729.  
  10730. ----------------------------------------------------------------
  10731.  
  10732. function "<="(                --| Compare two date/time
  10733.     Left  : in Time_Value;
  10734.     Right : in Time_Value
  10735.     ) return BOOLEAN;
  10736.  
  10737. --| Raises : Uninitialized_Time_Value
  10738. --| Effects: TRUE if Left is less than or equal to Right; FALSE otherwise.
  10739. --| N/A: Modifies, Errors
  10740.  
  10741. ----------------------------------------------------------------
  10742.  
  10743. function ">="(                --| Compare two date/time
  10744.     Left  : in Time_Value;
  10745.     Right : in Time_Value
  10746.     ) return BOOLEAN;
  10747.  
  10748. --| Raises : Uninitialized_Time_Value
  10749. --| Effects: TRUE if Left is greater than or equal to Right; FALSE otherwise.
  10750. --| N/A: Modifies, Errors
  10751.  
  10752. ----------------------------------------------------------------
  10753.  
  10754. function Date(                --| Returns date
  10755.     Value : in Time_Value        --| Time value
  10756.     ) return STRING;
  10757.  
  10758. --| Raises : Uninitialized_Time_Value
  10759. --| Effects: Extract the date portion from Time_Value in MM/DD/YY format
  10760. --| N/A: Modifies, Errors
  10761.  
  10762. ----------------------------------------------------------------
  10763.  
  10764. function Calendar_Date(            --| Returns calendar date
  10765.     Value : in Time_Value        --| Time value
  10766.     ) return STRING;
  10767.  
  10768. --| Raises : Uninitialized_Time_Value
  10769. --| Effects: Extract the date portion from Time_Value in Month DD, Year format
  10770. --| (eg. March 15, 1985)
  10771. --| N/A: Modifies, Errors
  10772.  
  10773. ----------------------------------------------------------------
  10774.  
  10775. function Time(                --| Returns time
  10776.     Value : in Time_Value        --| Time value
  10777.     ) return STRING;
  10778.  
  10779. --| Raises : Uninitialized_Time_Value
  10780. --| Effects: Extract the time portion from Time_Value in HH:MM:SS format
  10781. --| N/A: Modifies, Errors
  10782.  
  10783. ----------------------------------------------------------------
  10784.    
  10785. function Get_Terminal_Type        --| Get terminal type
  10786.     return Terminal_Type;
  10787.  
  10788. --| Raises : Terminal_Not_Attached, Unknown_Terminal_Type
  10789. --| Effects: Obtains attached terminal type.
  10790. --| N/A: Modifies, Errors
  10791.  
  10792. ----------------------------------------------------------------
  10793.  
  10794. procedure Enable_Interrupt_Trap;    --| Traps interrupt from the keyboard
  10795.  
  10796. --| Raises : Interrupt_Encountered
  10797. --| Effects: Enables trapping of an interrupt encountered from the keyboard.
  10798. --| On an interrupt from the keyboard, this procedure will :
  10799. --|  1. Set state such that all further interrupts from the keyboard are ignored
  10800. --|  2. Raise Interrupt_Encountered exception
  10801. --| It is the user's responsibility to handle the ignore state after the
  10802. --| exception is raised (eg. disable the interrupt trapping to allow the
  10803. --| system to handle subsequent interrupts).
  10804. --|-
  10805. --|    begin
  10806. --|         (Process not requiring interrupt trap)
  10807. --|      Enable_Interrupt_Trap;
  10808. --|         (Process requiring interrupt trap)
  10809. --|      Ignore_Interrupts;
  10810. --|         (Post process [eg. clean up])
  10811. --|     exception
  10812. --|      when Interrupt_Encountered =>
  10813. --|         (Post process [eg. clean up])
  10814. --|    end;
  10815. --|    Disable_Interrupt_Trap
  10816. --|+
  10817. --| N/A: Modifies, Errors
  10818.  
  10819. ----------------------------------------------------------------    
  10820.  
  10821. procedure Disable_Interrupt_Trap;    --| Disables interrupt trapping
  10822.  
  10823. --| Effects: Disables trapping of interrupts encountered from the keyboard.
  10824. --| N/A: Raises, Modifies, Errors
  10825.  
  10826. ----------------------------------------------------------------    
  10827.  
  10828. procedure Ignore_Interrupts;        --| Ignore interrupts
  10829.  
  10830. --| Effects: Interrupts encountered from the keyboard are ignored.
  10831. --| The trap must subsequently be disabled (Disable_Interrupt_Trap). 
  10832. --| N/A: Raises, Modifies, Errors
  10833.  
  10834. ----------------------------------------------------------------    
  10835.  
  10836. function Interrupts_Ignored        --| Returns TRUE if any interrupts from
  10837.                     --| the keyboard were ignored
  10838.     return BOOLEAN;
  10839.  
  10840. --| Effects: Returns TRUE if any interrupts were encountered since the mode
  10841. --| was set to ignore interrupts.
  10842. --| N/A: Raises, Modifies, Errors
  10843.  
  10844. ----------------------------------------------------------------    
  10845.  
  10846. procedure Set_Interrupt_State(        --| Set interrupt state
  10847.     State : in Interrupt_State
  10848.     );
  10849.  
  10850. --| Effects: Set interrupt state
  10851. --| N/A: Raises, Modifies, Errors
  10852.  
  10853. ----------------------------------------------------------------    
  10854.  
  10855. function Get_Interrupt_State        --| Get interrupt state
  10856.     return Interrupt_State;
  10857.  
  10858. --| Effects: Returns interrupt state
  10859. --| N/A: Raises, Modifies, Errors
  10860.  
  10861. ----------------------------------------------------------------    
  10862.  
  10863. private
  10864.                                                                     pragma list(off);
  10865.     type Time_Value is
  10866.     record
  10867.         year  : INTEGER;
  10868.         month : INTEGER := 0;
  10869.         day   : INTEGER;
  10870.         time  : INTEGER;
  10871.     end record;
  10872.                                                                     pragma list(on);
  10873. end Host_Lib;
  10874.                                                                     pragma page;
  10875. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10876. --HOSTLIB.BDY
  10877. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10878. with System;                    use System;
  10879. with Starlet;
  10880. with Condition_Handling;
  10881. with Text_IO;
  10882. with Calendar;
  10883. with String_Pkg;
  10884. with String_Utilities;
  10885.  
  10886. package body Host_Lib is
  10887.  
  10888. ----------------------------------------------------------------    
  10889.  
  10890.     package SU  renames String_Utilities;
  10891.     package CAL renames Calendar;
  10892.     package SP  renames String_Pkg;
  10893.     package CD  renames Condition_Handling;
  10894.     package TIO renames Text_IO;
  10895.     package STL renames Starlet;
  10896.  
  10897. ----------------------------------------------------------------    
  10898.  
  10899.     Month_Name     : constant STRING := 
  10900.             "JanuarayFebruarnyMarchAprilMayJune" &
  10901.             "JulyAugustSeptemberOctoberNovemberDecember";
  10902.     Index_Array    : constant array (1..13) of INTEGER :=
  10903.             (1, 9, 18, 23, 28, 31, 35, 39, 45, 54, 61, 69, 77);
  10904.     Item_Array     : constant array (1..7) of INTEGER :=
  10905.             (STL.JPI_USERNAME,
  10906.              STL.JPI_ACCOUNT,
  10907.              STL.JPI_IMAGNAME,
  10908.              STL.JPI_MODE,
  10909.              STL.JPI_PID,
  10910.              STL.JPI_TERMINAL,
  10911.              STL.DVI_DEVTYPE);
  10912.  
  10913.     Terminal_Array : constant array (Terminal_Type) of INTEGER := (
  10914.             VT05            =>   1,
  10915.             VK100            =>   2,
  10916.             VT173            =>   3,
  10917.             TQ_BTS            =>   4,
  10918.             TEK401X            =>  10,
  10919.             FOREIGN_TERMINAL_1    =>  16,
  10920.             FOREIGN_TERMINAL_2    =>  17,
  10921.             FOREIGN_TERMINAL_3    =>  18,
  10922.             FOREIGN_TERMINAL_4    =>  19,
  10923.             FOREIGN_TERMINAL_5    =>  20,
  10924.             FOREIGN_TERMINAL_6    =>  21,
  10925.             FOREIGN_TERMINAL_7    =>  22,
  10926.             FOREIGN_TERMINAL_8    =>  23,
  10927.             LA36            =>  32,
  10928.             LA120            =>  33,
  10929.             LA34            =>  34,
  10930.             LA38            =>  35,
  10931.             LA12            =>  36,
  10932.             LA24            =>  37,
  10933.             LQP02            =>  38,
  10934.             LA84            =>  39,
  10935.             VT52            =>  64,
  10936.             VT55            =>  65,
  10937.             DZ11            =>  66,
  10938.             DZ32            =>  67,
  10939.             DZ730            =>  68,
  10940.             DMZ32            =>  69,
  10941.             DHV            =>  70,
  10942.             DHU            =>  71,
  10943.             VT100            =>  96,
  10944.             VT101            =>  97,
  10945.             VT102            =>  98,
  10946.             VT105            =>  99,
  10947.             VT125            => 100,
  10948.             VT131            => 101,
  10949.             VT132            => 102,
  10950.             VT200_SERIES        => 110,
  10951.             PRO_SERIES        => 111,
  10952.             WORKSTATION        =>   0,
  10953.             VS100            =>   1,
  10954.             VS125            =>   2,
  10955.             VS300            =>   3,
  10956.             VIRTUAL_DEVICE        =>   4);
  10957.  
  10958.     Control_Y       : constant UNSIGNED_LONGWORD := 2**CHARACTER'POS(ASCII.EM);
  10959.  
  10960.     TT_Name         : constant STRING := "TT:";
  10961.  
  10962. ----------------------------------------------------------------    
  10963.  
  10964.     Error_File_Type : TIO.FILE_TYPE;
  10965.     Error_Switch    : NATURAL;
  10966.     TT_Channel      : STL.Channel_Type;
  10967.     Condition       : CD.Cond_Value_Type;
  10968.     Status          : INTEGER;
  10969.     IOSB            : STL.IOSB_Type;
  10970.     Mask            : UNSIGNED_LONGWORD;
  10971.     Save_Mask       : UNSIGNED_LONGWORD;
  10972.     State           : Interrupt_State;
  10973.     Ignored_State   : BOOLEAN;
  10974.  
  10975. ----------------------- Local procedure ------------------------
  10976.  
  10977.     procedure Spawn(
  10978.     Status  :    out INTEGER;
  10979.     Process : in     STRING
  10980.     );
  10981.  
  10982.     pragma Interface(VAXRTL, Spawn);
  10983.     pragma Import_Valued_Procedure(
  10984.             Internal        => Spawn,
  10985.             External        => "Lib$Spawn",
  10986.             Parameter_Types => (INTEGER,
  10987.                         STRING),
  10988.             Mechanism       => (Value,
  10989.                         Descriptor(S)));
  10990.  
  10991. ----------------------------------------------------------------
  10992.  
  10993.     procedure Get_Foreign(
  10994.     Arguments : out STRING
  10995.     );
  10996.  
  10997.     pragma Interface(External, Get_Foreign);
  10998.     pragma Import_Valued_Procedure(Get_Foreign,
  10999.                        "Lib$Get_Foreign",
  11000.                        (STRING),
  11001.                        (Descriptor(S)));
  11002.  
  11003. ----------------------------------------------------------------    
  11004.  
  11005.     procedure Get_JPI(
  11006.     Status     :    out INTEGER;
  11007.     Item_Code  : in     INTEGER;
  11008.     Proc_Id    : in     ADDRESS := ADDRESS_ZERO;
  11009.     Proc_Name  : in     STRING  := STRING'NULL_PARAMETER;
  11010.     Out_Value  : in     ADDRESS := ADDRESS_ZERO;
  11011.     Out_String :    out STRING;
  11012.     Out_Len    :    out SHORT_INTEGER);
  11013.  
  11014.     pragma Interface(VAXRTL, Get_JPI);
  11015.     pragma Import_Valued_Procedure(
  11016.             Internal        => Get_JPI,
  11017.             External        => "LIB$GETJPI",
  11018.             Parameter_Types => (INTEGER,
  11019.                         INTEGER,
  11020.                         ADDRESS,
  11021.                         STRING,
  11022.                         ADDRESS,
  11023.                         STRING,
  11024.                         SHORT_INTEGER),
  11025.             Mechanism       => (Value,
  11026.                         Reference,
  11027.                         Value,
  11028.                         Descriptor(S),
  11029.                         Value,
  11030.                         Descriptor(S),
  11031.                         Reference));
  11032.  
  11033. ----------------------------------------------------------------    
  11034.  
  11035.     procedure Get_DVI(
  11036.     Status     :    out INTEGER;
  11037.     Item_Code  : in     INTEGER;
  11038.     Channel    : in     SHORT_INTEGER  := 0;
  11039.     Dev_Name   : in     STRING;
  11040.     Out_Value  : in     INTEGER := 0;
  11041.     Out_String :    out STRING;
  11042.     Out_Len    :    out SHORT_INTEGER);
  11043.  
  11044.     pragma Interface(VAXRTL, Get_DVI);
  11045.     pragma Import_Valued_Procedure(
  11046.             Internal        => Get_DVI,
  11047.             External        => "LIB$GETDVI",
  11048.             Parameter_Types => (INTEGER,
  11049.                         INTEGER,
  11050.                         SHORT_INTEGER,
  11051.                         STRING,
  11052.                         INTEGER,
  11053.                         STRING,
  11054.                         SHORT_INTEGER),
  11055.             Mechanism       => (Value,
  11056.                         Reference,
  11057.                         Reference,
  11058.                         Descriptor(S),
  11059.                         Reference,
  11060.                         Descriptor(S),
  11061.                         Reference));
  11062.  
  11063. ----------------------------------------------------------------
  11064.  
  11065.     function Get_Protection_String(
  11066.     Name : in STRING;
  11067.     Prot : in Protection_Specification
  11068.     ) return SP.String_Type is
  11069.  
  11070.     Str : SP.String_Type := SP.Create("");
  11071.  
  11072.     begin
  11073.  
  11074.     if Prot(Read) = YES then
  11075.         Str := SP."&"(Str, "R");
  11076.     end if;
  11077.     if Prot(Write) = YES then
  11078.         Str := SP."&"(Str, "W");
  11079.     end if;
  11080.     if Prot(Execute) = YES then
  11081.         Str := SP."&"(Str, "E");
  11082.     end if;
  11083.     if Prot(Delete) = YES then
  11084.         Str := SP."&"(Str, "D");
  11085.     end if;
  11086.     if SP.Length(Str) /= 0 then
  11087.         Str := SP."&"(Name & ':', Str);
  11088.         Str := SP."&"(Str, ",");
  11089.     end if;
  11090.     return Str;
  11091.  
  11092.     end Get_Protection_String;
  11093.  
  11094. ----------------------------------------------------------------    
  11095.  
  11096.     procedure Check_Time_Value(
  11097.     Value : Time_Value
  11098.     ) is
  11099.  
  11100.     begin
  11101.  
  11102.     if Value.month = 0 then
  11103.         raise Uninitialized_Time_Value;
  11104.     end if;
  11105.  
  11106.     end Check_Time_Value;
  11107.  
  11108. ----------------------------------------------------------------    
  11109.  
  11110.     function Compare(
  11111.     Left  : Time_Value;
  11112.     Right : Time_Value
  11113.     ) return INTEGER is
  11114.  
  11115.     Diff : INTEGER;
  11116.  
  11117.     begin
  11118.  
  11119.     Check_Time_Value(Left);
  11120.     Check_Time_Value(Right);
  11121.     Diff := Left.year - Right.year;
  11122.     if Diff /= 0 then
  11123.         return Diff;
  11124.     end if;
  11125.     Diff := Left.month - Right.month;
  11126.     if Diff /= 0 then
  11127.         return Diff;
  11128.     end if;
  11129.     Diff := Left.day - Right.day;
  11130.     if Diff /= 0 then
  11131.         return Diff;
  11132.     end if;
  11133.     return Left.time - Right.time;
  11134.  
  11135.     end Compare;
  11136.  
  11137. ----------------------------------------------------------------
  11138.  
  11139.     procedure Signal(Status : in CD.Cond_Value_Type);
  11140.  
  11141.     pragma Interface(VAXRTL, Signal);
  11142.     pragma Import_Procedure(Signal, "LIB$Signal", Mechanism =>(Value));
  11143.  
  11144. ----------------------------------------------------------------    
  11145.  
  11146.     procedure Control_Character_Handler is 
  11147.  
  11148.     begin
  11149.  
  11150.     Ignore_Interrupts;
  11151.  
  11152.     raise Interrupt_Encountered;
  11153.  
  11154.     end Control_Character_Handler;
  11155.  
  11156.     pragma Export_Procedure(Control_Character_Handler,
  11157.                 "Ada$Control_Character_Handler");
  11158.  
  11159. ----------------------------------------------------------------    
  11160.  
  11161.     procedure Control_Character_Ignore is 
  11162.  
  11163.     begin
  11164.  
  11165.     Ignore_Interrupts;
  11166.  
  11167.     Ignored_State := TRUE;
  11168.  
  11169.     end Control_Character_Ignore;
  11170.  
  11171.     pragma Export_Procedure(Control_Character_Ignore,
  11172.                 "Ada$Control_Character_Ignore");
  11173.  
  11174. ----------------------------------------------------------------    
  11175.  
  11176.     procedure Disable_Control(
  11177.     Status   :    out INTEGER;
  11178.     Mask     : in     UNSIGNED_LONGWORD;
  11179.     Old_Mask :    out UNSIGNED_LONGWORD
  11180.     );
  11181.  
  11182.     pragma Interface(VAXRTL, Disable_Control);
  11183.     pragma Import_Valued_Procedure(
  11184.             Internal        => Disable_Control,
  11185.             External        => "Lib$Disable_Ctrl",
  11186.             Parameter_Types => (INTEGER,
  11187.                         UNSIGNED_LONGWORD,
  11188.                         UNSIGNED_LONGWORD),
  11189.             Mechanism       => (Value,
  11190.                         Reference,
  11191.                         Reference));
  11192.  
  11193. ----------------------------------------------------------------    
  11194.  
  11195.     procedure Enable_Control(
  11196.     Status   :    out INTEGER;
  11197.     Mask     : in     UNSIGNED_LONGWORD;
  11198.     Old_Mask :    out UNSIGNED_LONGWORD
  11199.     );
  11200.  
  11201.     pragma Interface(VAXRTL, Enable_Control);
  11202.     pragma Import_Valued_Procedure(
  11203.             Internal        => Enable_Control,
  11204.             External        => "Lib$Enable_Ctrl",
  11205.             Parameter_Types => (INTEGER,
  11206.                         UNSIGNED_LONGWORD,
  11207.                         UNSIGNED_LONGWORD),
  11208.             Mechanism       => (Value,
  11209.                         Reference,
  11210.                         Reference));
  11211.                                                         pragma page;
  11212. --------------------- Visible Subprograms ----------------------    
  11213.  
  11214.     procedure Set_Error is
  11215.  
  11216.     begin
  11217.  
  11218.     if Error_Switch = 0 then
  11219.         TIO.SET_OUTPUT(File => Error_File_Type);
  11220.     end if;
  11221.     Error_Switch := Error_Switch + 1;
  11222.  
  11223.     end Set_Error;
  11224.  
  11225. ----------------------------------------------------------------    
  11226.  
  11227.     procedure Reset_Error is
  11228.  
  11229.     begin
  11230.  
  11231.     if Error_Switch < 1 then
  11232.         return;
  11233.     end if;
  11234.     Error_Switch := Error_Switch - 1;
  11235.     if Error_Switch = 0 then
  11236.         TIO.SET_OUTPUT(File => TIO.STANDARD_OUTPUT);
  11237.     end if;
  11238.  
  11239.     end Reset_Error;
  11240.  
  11241. ----------------------------------------------------------------    
  11242.  
  11243.     procedure Put_Error(
  11244.     Message : in STRING
  11245.     ) is
  11246.  
  11247.     begin
  11248.  
  11249.     TIO.PUT_LINE(Error_File_Type, "Error : " & Message);
  11250.  
  11251.     end Put_Error;
  11252.  
  11253. ----------------------------------------------------------------    
  11254.  
  11255.     function Return_Code(
  11256.     Severity : in Severity_Code
  11257.     ) return integer is
  11258.  
  11259.     begin
  11260.  
  11261.     case Severity is
  11262.         when WARNING =>
  11263.         return STL.STS_K_WARNING;
  11264.         when SUCCESS =>
  11265.         return STL.STS_K_SUCCESS;
  11266.         when ERROR =>
  11267.         return STL.STS_K_ERROR;
  11268.         when INFORMATION =>
  11269.         return STL.STS_K_INFO;
  11270.         when SEVERE =>
  11271.         return STL.STS_K_SEVERE;
  11272.     end case;
  11273.  
  11274.     end Return_Code;
  11275.  
  11276. ----------------------------------------------------------------
  11277.  
  11278.     procedure Invoke(
  11279.     Process  : in     STRING;
  11280.     Severity :    out Severity_Code
  11281.     ) is
  11282.  
  11283.     Stat  : INTEGER;
  11284.     Found : BOOLEAN := FALSE;
  11285.  
  11286.     begin
  11287.  
  11288.     for i in Process'range loop
  11289.         if Process(i) /= ' ' and Process(i) /= ASCII.HT then
  11290.         Found := TRUE;
  11291.         exit;
  11292.         end if;
  11293.     end loop;
  11294.     if not Found then
  11295.         Severity := SUCCESS;
  11296.         return;
  11297.     end if;
  11298.     Spawn(Stat, Process);
  11299.     case Stat is
  11300.         when STL.STS_K_WARNING =>
  11301.         Severity := WARNING;
  11302.         when STL.STS_K_SUCCESS =>
  11303.         Severity := SUCCESS;
  11304.         when STL.STS_K_ERROR =>
  11305.         Severity := ERROR;
  11306.         when STL.STS_K_INFO =>
  11307.         Severity := INFORMATION;
  11308.         when STL.STS_K_SEVERE =>
  11309.         Severity := SEVERE;
  11310.         when others =>
  11311.         Severity := SEVERE;
  11312.     end case;
  11313.  
  11314.     end Invoke;
  11315.  
  11316. ----------------------------------------------------------------
  11317.  
  11318.     function Get_Item(
  11319.     Item : in Item_Type;
  11320.      Form : in Format := EDIT
  11321.     ) return STRING is
  11322.  
  11323.     Line      : STRING(1..Max_Arg_Length);
  11324.     Len       : INTEGER;
  11325.     Stat      : INTEGER;
  11326.     Inx1      : INTEGER;
  11327.     Inx2      : INTEGER;
  11328.     Dev_Class : INTEGER;
  11329.  
  11330.     begin
  11331.     case Item is
  11332.         when ARGUMENTS =>
  11333.         Get_Foreign(Line);
  11334.         if Form = EDIT then
  11335.             return SU.Strip(Line);
  11336.         else
  11337.             return Line;
  11338.         end if;
  11339.         when USER_NAME | ACCOUNT | PROGRAM_NAME | PROCESS_MODE |
  11340.          PROCESS_ID | TERMINAL_ADDRESS =>
  11341.         Get_JPI(Item_Code  => Item_Array(Item_Type'pos(Item)),
  11342.             Out_String => Line,
  11343.             Out_Len    => SHORT_INTEGER(Len),
  11344.             Status     => Stat);
  11345.         if Item = PROGRAM_NAME then
  11346.             if Form = EDIT then
  11347.             Inx1 := 0;
  11348.             Inx2 := 0;
  11349.             for i in 1 .. Len loop
  11350.                 if Line(i) = ']' then
  11351.                 Inx1 := i + 1;
  11352.                 for j in Inx1 .. Len loop
  11353.                     if Line(j) = '.' then
  11354.                     Inx2 := j - 1;
  11355.                     exit;
  11356.                     end if;
  11357.                 end loop;
  11358.                 exit;
  11359.                 end if;
  11360.             end loop;
  11361.             return Line(Inx1..Inx2);
  11362.             else
  11363.             return Line(1..Len);
  11364.             end if;
  11365.         else
  11366.             while Len > 0 and then Line(Len) = ' ' loop
  11367.             Len := Len - 1;
  11368.             end loop;
  11369.             return Line(1..Len);
  11370.         end if;
  11371.         when DEVICE_TYPE =>
  11372.         return Terminal_Type'image(Get_Terminal_Type);
  11373.         when others =>
  11374.         return "";
  11375.     end case;    
  11376.  
  11377.     end Get_Item;
  11378.  
  11379. ----------------------------------------------------------------
  11380.  
  11381.     function Read_No_Echo(
  11382.     Address : in STRING := Get_Item(TERMINAL_ADDRESS)
  11383.     ) return STRING is
  11384.  
  11385.     Line               : STRING(1 .. 255);
  11386.     Len                : INTEGER;
  11387.     Keyboard_File_Type : TIO.FILE_TYPE;
  11388.     TT                 : SP.String_Type;
  11389.  
  11390.     begin
  11391.  
  11392.     SP.Mark;
  11393.     if Address = "" then
  11394.         TT := SP.Create("TT:");
  11395.     else
  11396.         TT := SP.Create(Address);
  11397.     end if;
  11398.  
  11399.     begin
  11400.         TIO.OPEN(File => Keyboard_File_Type,
  11401.              Mode => TIO.IN_FILE, 
  11402.              Name => SP.Value(TT),
  11403.              Form => "CONNECT;TT_READ_NOECHO YES");
  11404.     exception
  11405.         when TIO.STATUS_ERROR =>
  11406.         null;
  11407.         when others =>
  11408.         SP.Release;
  11409.         raise;
  11410.     end;
  11411.     SP.Release;
  11412.     TIO.GET_LINE(Keyboard_File_Type, Line, Len);
  11413.     TIO.NEW_LINE(1);
  11414.     return Line(1 .. Len);
  11415.  
  11416.     end Read_No_Echo;
  11417.  
  11418. ----------------------------------------------------------------
  11419.  
  11420.     function Protection(
  11421.     System : in Protection_Specification :=
  11422.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES);
  11423.     Owner  : in Protection_Specification :=
  11424.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES);
  11425.     Group  : in Protection_Specification :=
  11426.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES);
  11427.     World  : in Protection_Specification :=
  11428.         (Read=>YES, Write=>YES, Execute=>YES, Delete=>YES)
  11429.     ) return STRING is
  11430.  
  11431.     Str : SP.String_Type;
  11432.  
  11433.     begin
  11434.  
  11435.     SP.Mark;
  11436.     Str := SP.Create("");
  11437.     Str := SP."&"(Str, Get_Protection_String("SYSTEM", System));     
  11438.     Str := SP."&"(Str, Get_Protection_String("OWNER", Owner));
  11439.     Str := SP."&"(Str, Get_Protection_String("GROUP", Group));
  11440.     Str := SP."&"(Str, Get_Protection_String("WORLD", World));
  11441.     if SP.Length(Str) /= 0 then
  11442.         Str := SP."&"("FILE;PROTECTION (",
  11443.               SP.Substr(Str, 1, SP.Length(Str) - 1));
  11444.         Str := SP."&"(Str, ")");
  11445.     end if;
  11446.     declare
  11447.         Protection_String : STRING (1 .. SP.Length(Str));
  11448.     begin
  11449.         Protection_String := SP.Value(Str);
  11450.         SP.Release;
  11451.         return Protection_String;
  11452.     end;
  11453.  
  11454.     end Protection;
  11455.  
  11456. ----------------------------------------------------------------    
  11457.  
  11458.     procedure Get_Time(
  11459.     Value : out Time_Value
  11460.     ) is
  11461.  
  11462.     Clock_Value : CAL.Time;
  11463.     Year        : CAL.Year_Number;
  11464.     Month       : CAL.Month_Number;
  11465.     Day         : CAL.Day_Number;
  11466.     Duration    : CAL.Day_Duration;
  11467.  
  11468.     begin
  11469.  
  11470.     Clock_Value := CAL.Clock;
  11471.     CAL.Split(Clock_Value, Year, Month, Day, Duration);
  11472.     Value.year  := INTEGER(Year);
  11473.     Value.month := INTEGER(Month);
  11474.     Value.day   := INTEGER(Day);
  11475.     Value.time  := INTEGER(Duration);
  11476.  
  11477.     end Get_Time;
  11478.  
  11479. ----------------------------------------------------------------    
  11480.  
  11481.     function "="(
  11482.     Left  : in Time_Value;
  11483.     Right : in Time_Value
  11484.     ) return BOOLEAN is
  11485.  
  11486.     begin
  11487.  
  11488.     return Compare(Left, Right) = 0;
  11489.  
  11490.     end "=";
  11491.  
  11492. ----------------------------------------------------------------    
  11493.  
  11494.     function "<"(
  11495.     Left  : in Time_Value;
  11496.     Right : in Time_Value
  11497.     ) return BOOLEAN is
  11498.  
  11499.     begin
  11500.  
  11501.     return Compare(Left, Right) < 0;
  11502.  
  11503.     end "<";
  11504.  
  11505. ----------------------------------------------------------------    
  11506.  
  11507.     function ">"(
  11508.     Left  : in Time_Value;
  11509.     Right : in Time_Value
  11510.     ) return BOOLEAN is
  11511.  
  11512.     begin
  11513.  
  11514.     return Compare(Left, Right) > 0;
  11515.  
  11516.     end ">";
  11517.  
  11518. ----------------------------------------------------------------    
  11519.  
  11520.     function "<="(
  11521.     Left  : in Time_Value;
  11522.     Right : in Time_Value
  11523.     ) return BOOLEAN is
  11524.  
  11525.     begin
  11526.  
  11527.     return Compare(Left, Right) <= 0;
  11528.  
  11529.     end "<=";
  11530.  
  11531. ----------------------------------------------------------------    
  11532.  
  11533.     function ">="(
  11534.     Left  : in Time_Value;
  11535.     Right : in Time_Value
  11536.     ) return BOOLEAN is
  11537.  
  11538.     begin
  11539.  
  11540.     return Compare(Left, Right) >= 0;
  11541.  
  11542.     end ">=";
  11543.  
  11544. ----------------------------------------------------------------    
  11545.  
  11546.     function Date(
  11547.     Value : in Time_Value
  11548.     ) return STRING is
  11549.  
  11550.     begin
  11551.  
  11552.     Check_Time_Value(Value);
  11553.     return     SU.Image(Value.month, 2, '0')
  11554.            & '/'
  11555.            & SU.Image(Value.day, 2, '0')
  11556.            & '/'
  11557.            & SU.Image((Value.year mod 100), 2, '0');
  11558.  
  11559.     end Date;
  11560.  
  11561. ----------------------------------------------------------------    
  11562.  
  11563.     function Calendar_Date(
  11564.     Value : in Time_Value
  11565.     ) return STRING is
  11566.  
  11567.     Index : INTEGER;
  11568.  
  11569.     begin
  11570.  
  11571.     Check_Time_Value(Value);
  11572.     Index := Value.month;
  11573.     return    Month_Name(Index_Array(Index) .. Index_Array(Index + 1) - 1)
  11574.         & INTEGER'image(Value.day)
  11575.         & ','
  11576.         & INTEGER'image(Value.year);
  11577.  
  11578.     end Calendar_Date;
  11579.  
  11580. ----------------------------------------------------------------    
  11581.  
  11582.     function Time(
  11583.     Value : in Time_Value
  11584.     ) return STRING is
  11585.  
  11586.     begin
  11587.  
  11588.     Check_Time_Value(Value);
  11589.     return     SU.Image(Value.time / (60 * 60), 2, '0')
  11590.            & ':'
  11591.            & SU.Image((Value.time mod (60 * 60)) / 60, 2, '0')
  11592.            & ':'
  11593.            & SU.Image(Value.time mod 60, 2, '0');
  11594.  
  11595.     end Time;
  11596.  
  11597. ----------------------------------------------------------------    
  11598.  
  11599.     function Get_Terminal_Type
  11600.     return Terminal_Type is
  11601.  
  11602.     Line      : STRING(1..Max_Arg_Length);
  11603.     Len       : INTEGER;
  11604.     Stat      : INTEGER;
  11605.     Dev_Class : INTEGER;
  11606.  
  11607.     begin
  11608.  
  11609.     if Get_Item(TERMINAL_ADDRESS) = "" then
  11610.         raise Terminal_Not_Attached;
  11611.     end if;
  11612.     Get_DVI(Item_Code  => STL.DVI_DEVCLASS,
  11613.         Dev_Name   => Get_Item(TERMINAL_ADDRESS),
  11614.         Out_Value  => Len,
  11615.         Out_String => Line,
  11616.         Out_Len    => SHORT_INTEGER(Len),
  11617.         Status     => Stat);
  11618.     begin
  11619.         Dev_Class := INTEGER'value(Line(1 .. Len));
  11620.     exception
  11621.         when CONSTRAINT_ERROR =>
  11622.         raise Unknown_Terminal_Type;
  11623.     end;
  11624.     if Dev_Class = STL.DC_TERM or 
  11625.        Dev_Class = STL.DC_WORKSTATION then
  11626.         Get_DVI(Item_Code  => Item_Array(Item_Type'pos(DEVICE_TYPE)),
  11627.             Dev_Name   => Get_Item(TERMINAL_ADDRESS),
  11628.             Out_Value  => Len,
  11629.             Out_String => Line,
  11630.             Out_Len    => SHORT_INTEGER(Len),
  11631.             Status     => Stat);
  11632.         begin
  11633.         if Dev_Class = STL.DC_TERM then
  11634.             for i in Terminal_Type'first .. 
  11635.                  Terminal_Type'val(Terminal_Type'pos(WORKSTATION) - 1) 
  11636.             loop
  11637.             if INTEGER'value(Line(1 .. Len)) = Terminal_Array(i) then
  11638.                 return i;
  11639.             end if;
  11640.             end loop;
  11641.         else
  11642.             for i in Terminal_Type'val(Terminal_Type'pos(WORKSTATION) + 1) .. 
  11643.                  Terminal_Type'last
  11644.             loop
  11645.             if INTEGER'value(Line(1 .. Len)) = Terminal_Array(i) then
  11646.                 return i;
  11647.             end if;
  11648.             end loop;
  11649.         end if;
  11650.         exception
  11651.         when CONSTRAINT_ERROR =>
  11652.             raise Unknown_Terminal_Type;
  11653.         end;
  11654.     end if;
  11655.     raise Unknown_Terminal_Type;
  11656.  
  11657.     end Get_Terminal_Type;
  11658.  
  11659. ----------------------------------------------------------------    
  11660.  
  11661.     procedure Enable_Interrupt_Trap is
  11662.  
  11663.     begin
  11664.  
  11665.     case State is
  11666.  
  11667.         when ENABLED =>
  11668.         return;
  11669.  
  11670.         when DISABLED =>
  11671.  
  11672.         Disable_Control(Status   => Status,
  11673.                 Mask     => Control_Y,
  11674.                 Old_Mask => Save_Mask);
  11675.         if not CD.Success(CD.Cond_Value_Type(Status)) then
  11676.             Signal(CD.Cond_Value_Type(Status));
  11677.         end if;
  11678.  
  11679.         if INTEGER(Save_Mask and Control_Y) = 0 then
  11680.             Enable_Control(Status   => Status,
  11681.                    Mask     => Save_Mask,
  11682.                     Old_Mask => Mask);
  11683.             if not CD.Success(CD.Cond_Value_Type(Status)) then
  11684.             Signal(CD.Cond_Value_Type(Status));
  11685.             end if;
  11686.             return;
  11687.         end if;
  11688.  
  11689.         when IGNORED =>
  11690.  
  11691.         STL.Cancel(
  11692.             Status => Condition,
  11693.             Chan   => TT_Channel);
  11694.         if not CD.Success(Condition) then 
  11695.             Signal(Condition);
  11696.         end if;
  11697.  
  11698.         STL.Dassgn(
  11699.             Status => Condition,
  11700.             Chan   => TT_Channel);
  11701.         if not CD.Success(Condition) then 
  11702.             Signal(Condition);
  11703.         end if;
  11704.  
  11705.     end case;
  11706.  
  11707.     STL.Assign(
  11708.         Status => Condition,
  11709.         Devnam => TT_Name, 
  11710.         Chan   => TT_Channel);
  11711.     if not CD.Success(Condition) then 
  11712.         Enable_Control(Status   => Status,
  11713.                Mask     => Save_Mask,
  11714.                Old_Mask => Mask);
  11715.         if not CD.Success(CD.Cond_Value_Type(Status)) then
  11716.         Signal(CD.Cond_Value_Type(Status));
  11717.         end if;
  11718.     end if;
  11719.  
  11720.     STL.QIOW(
  11721.         Status  => Condition,
  11722.         Chan    => TT_Channel, 
  11723.         FUNC    => STL.IO_SETMODE
  11724.             or STL.IO_M_CtrlCAst
  11725.             or STL.IO_M_CtrlYAst,
  11726.         IOSB    => IOSB, 
  11727.         P1      => TO_UNSIGNED_LONGWORD(Control_Character_Handler'Address));
  11728.     if not CD.Success(Condition) then 
  11729.         STL.Dassgn(Status => Condition,
  11730.                Chan   => TT_Channel);
  11731.         Enable_Control(Status   => Status,
  11732.                Mask     => Save_Mask,
  11733.                Old_Mask => Mask);
  11734.         Signal(Condition);
  11735.     end if;
  11736.  
  11737.     State := ENABLED;
  11738.  
  11739.     end Enable_Interrupt_Trap;
  11740.  
  11741. ----------------------------------------------------------------    
  11742.  
  11743.     procedure Disable_Interrupt_Trap is
  11744.  
  11745.     begin
  11746.  
  11747.     case State is
  11748.  
  11749.         when DISABLED =>
  11750.         return;
  11751.  
  11752.         when others =>
  11753.  
  11754.         STL.Cancel(
  11755.             Status => Condition,
  11756.             Chan   => TT_Channel);
  11757.         if not CD.Success(Condition) then 
  11758.             Signal(Condition);
  11759.         end if;
  11760.  
  11761.         STL.Dassgn(
  11762.             Status => Condition,
  11763.             Chan   => TT_Channel);
  11764.         if not CD.Success(Condition) then 
  11765.             Signal(Condition);
  11766.         end if;
  11767.  
  11768.         Enable_Control(Status   => Status,
  11769.                    Mask     => Save_Mask,
  11770.                    Old_Mask => Mask);
  11771.         if not CD.Success(CD.Cond_Value_Type(Status)) then
  11772.             Signal(CD.Cond_Value_Type(Status));
  11773.         end if;
  11774.  
  11775.         State := DISABLED;
  11776.  
  11777.     end case;
  11778.  
  11779.     end Disable_Interrupt_Trap;
  11780.  
  11781. ----------------------------------------------------------------    
  11782.  
  11783.     procedure Ignore_Interrupts is 
  11784.  
  11785.     begin
  11786.  
  11787.     case State is
  11788.  
  11789.         when IGNORED =>
  11790.         return;
  11791.  
  11792.         when DISABLED =>
  11793.  
  11794.         Disable_Control(Status   => Status,
  11795.                 Mask     => Control_Y,
  11796.                 Old_Mask => Save_Mask);
  11797.         if not CD.Success(CD.Cond_Value_Type(Status)) then
  11798.             Signal(CD.Cond_Value_Type(Status));
  11799.         end if;
  11800.  
  11801.         if INTEGER(Save_Mask and Control_Y) = 0 then
  11802.             Enable_Control(Status   => Status,
  11803.                    Mask     => Save_Mask,
  11804.                     Old_Mask => Mask);
  11805.             if not CD.Success(CD.Cond_Value_Type(Status)) then
  11806.             Signal(CD.Cond_Value_Type(Status));
  11807.             end if;
  11808.             return;
  11809.         end if;
  11810.  
  11811.         when ENABLED =>
  11812.  
  11813.         STL.Cancel(
  11814.             Status => Condition,
  11815.             Chan   => TT_Channel);
  11816.         if not CD.Success(Condition) then 
  11817.             Signal(Condition);
  11818.         end if;
  11819.  
  11820.         STL.Dassgn(
  11821.             Status => Condition,
  11822.             Chan   => TT_Channel);
  11823.         if not CD.Success(Condition) then 
  11824.             Signal(Condition);
  11825.         end if;
  11826.  
  11827.     end case;
  11828.  
  11829.     STL.Assign(Status => Condition,
  11830.            Devnam => TT_Name, 
  11831.            Chan   => TT_Channel);
  11832.     if not CD.Success(Condition) then 
  11833.         Signal(Condition);
  11834.     end if;
  11835.  
  11836.     STL.QIOW(
  11837.         Status  => Condition,
  11838.         Chan    => TT_Channel, 
  11839.         FUNC    => STL.IO_SETMODE
  11840.             or STL.IO_M_CtrlCAst
  11841.             or STL.IO_M_CtrlYAst,
  11842.         IOSB    => IOSB, 
  11843.         P1      => TO_UNSIGNED_LONGWORD(Control_Character_Ignore'Address));
  11844.     if not CD.Success(Condition) then 
  11845.         Signal(Condition);
  11846.     end if;
  11847.     State := IGNORED;
  11848.     Ignored_State := FALSE;
  11849.  
  11850.     end Ignore_Interrupts;
  11851.  
  11852. ----------------------------------------------------------------    
  11853.  
  11854.     function Interrupts_Ignored
  11855.     return BOOLEAN is
  11856.  
  11857.     begin
  11858.  
  11859.     return Get_Interrupt_State = IGNORED and Ignored_State;
  11860.  
  11861.     end Interrupts_Ignored;
  11862.  
  11863. ----------------------------------------------------------------    
  11864.  
  11865.     procedure Set_Interrupt_State(
  11866.     State : in Interrupt_State
  11867.     ) is
  11868.  
  11869.     begin
  11870.  
  11871.     if State = Get_Interrupt_State then
  11872.         return;
  11873.     end if;
  11874.     case State is
  11875.         when ENABLED =>
  11876.         Enable_Interrupt_Trap;
  11877.         when DISABLED =>
  11878.         Disable_Interrupt_Trap;
  11879.         when IGNORED =>
  11880.         Ignore_Interrupts;
  11881.     end case;
  11882.  
  11883.     end Set_Interrupt_State;
  11884.  
  11885. ----------------------------------------------------------------    
  11886.  
  11887.     function Get_Interrupt_State
  11888.     return Interrupt_State is
  11889.  
  11890.     begin
  11891.  
  11892.     return State;
  11893.  
  11894.     end Get_Interrupt_State;
  11895.  
  11896. ----------------------------------------------------------------    
  11897.  
  11898. begin
  11899.  
  11900.     State := DISABLED;
  11901.     Ignored_State := FALSE;
  11902.     Error_Switch := 0;
  11903.     TIO.OPEN(File => Error_File_Type,
  11904.          Mode => TIO.OUT_FILE,
  11905.          Name => "SYS$ERROR",
  11906.          Form => "CONNECT;END_OF_FILE YES");
  11907. exception
  11908.     when TIO.NAME_ERROR =>
  11909.     TIO.CREATE(File => Error_File_Type,
  11910.            Mode => TIO.OUT_FILE,
  11911.            Name => "SYS$ERROR",
  11912.            Form => "CONNECT;END_OF_FILE YES");
  11913.     when TIO.STATUS_ERROR =>
  11914.     null;
  11915.  
  11916. end Host_Lib;
  11917.                                                         pragma page;
  11918. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11919. --HOSTDEP.SPC
  11920. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11921.  
  11922. package Host_Dependencies is
  11923. --| Simple data types and constants involving the Host Machine.
  11924.     
  11925.                     -- Types and Objects --
  11926.  
  11927.     MaxColumn : constant := 250;
  11928.     subtype Source_Column is Natural range 0..MaxColumn;
  11929.     MaxLine : constant := 100000; -- This is completely arbitrary
  11930.     subtype Source_Line is Natural range 0..MaxLine;
  11931.  
  11932.                         -- Operations --
  11933.  
  11934.     function FindTabColumn (       --| returns source column a tab is in
  11935.         InColumn : Source_Column   --| source column before tab
  11936.         ) return Source_Column;
  11937.  
  11938.     --| Effects
  11939.  
  11940.     --| This subprogram implements the tab positioning strategy
  11941.     --| of the Host system.
  11942.  
  11943. end Host_Dependencies;
  11944.  
  11945.  
  11946. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11947. --ERRMSG.SPC
  11948. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11949.  
  11950. ----------------------------------------------------------------------
  11951.  
  11952. with Host_Dependencies;           -- host dependent constants
  11953.  
  11954. package Lexical_Error_Message is  --| handles lexical error messages
  11955.  
  11956. --| Overview
  11957. --|
  11958. --| Contains text, identifiers of text, and output subprograms
  11959. --| for package Lex.
  11960. --|
  11961.  
  11962.     package HD renames Host_Dependencies;
  11963.  
  11964.     --------------------------------------------------------------
  11965.     -- Declarations Global to Package Lexical_Error_Message
  11966.     ------------------------------------------------------------------
  11967.  
  11968.     type Message_Type is (
  11969.         Base_Out_Of_Legal_Range_Use_16,
  11970.         Based_Literal_Delimiter_Mismatch,
  11971.         Character_Can_Not_Start_Token,
  11972.         Character_Is_Non_ASCII,
  11973.         Character_Is_Non_Graphic,
  11974.         Consecutive_Underlines,
  11975.         Digit_Invalid_For_Base,
  11976.         Digit_Needed_After_Radix_Point,
  11977.         Digit_Needed_Before_Radix_Point,
  11978.         Exponent_Missing_Integer_Field,
  11979.         Illegal_Use_Of_Single_Quote,
  11980.         Integer_Literal_Conversion_Exception_Use_1,
  11981.         Leading_Underline,
  11982.         Missing_Second_Based_Literal_Delimiter,
  11983.         Negative_Exponent_Illegal_In_Integer,
  11984.         No_Ending_String_Delimiter,
  11985.         No_Integer_In_Based_Number,
  11986.         Only_Graphic_Characters_In_Strings,
  11987.         Real_Literal_Conversion_Exception_Use_1,
  11988.         Source_Line_Maximum_Exceeded,
  11989.         Source_Line_Too_Long,
  11990.         Space_Must_Separate_Num_And_Ids,
  11991.         Terminal_Underline,
  11992.         Too_Many_Radix_Points);
  11993.  
  11994.     --------------------------------------------------------------
  11995.     -- Subprogram Bodies Global to Package Lexical_Error_Message
  11996.     --------------------------------------------------------------
  11997.  
  11998.     procedure Output_Message(             --| output lexical error message
  11999.         In_Line   : in HD.Source_Line;    --| line number of error.
  12000.         In_Column : in HD.Source_Column;  --| column number of error.
  12001.         In_Message_Id : in Message_Type); --| which message to output.
  12002.  
  12003.     --| Effects
  12004.     --|
  12005.     --| Output error message for lexer.
  12006.     --|
  12007.  
  12008.     ------------------------------------------------------------------
  12009.  
  12010.     procedure Output_Message(             --| output lexical error message
  12011.         In_Line   : in HD.Source_Line;    --| line number of error.
  12012.         In_Column : in HD.Source_Column;  --| column number of error.
  12013.         In_Insertion_Text : in string;    --| text to insert.
  12014.         In_Message_Id : in Message_Type); --| which message to output.
  12015.  
  12016.     --| Effects
  12017.     --|
  12018.     --| Output error message with inserted text.  The text is appended
  12019.     --| to the message if there are no insertion flags.
  12020.  
  12021.     ------------------------------------------------------------------
  12022.  
  12023. end Lexical_Error_Message;
  12024.  
  12025. ----------------------------------------------------------------------
  12026.  
  12027.  
  12028. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12029. --ERRMSG.BDY
  12030. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12031.  
  12032.  
  12033. ------------------------------------------------------------------
  12034.  
  12035. with TEXT_IO;
  12036.  
  12037. package body Lexical_Error_Message is
  12038.  
  12039. ------------------------------------------------------------------
  12040. -- Declarations Local to Package Lexical_Error_Message
  12041. ------------------------------------------------------------------
  12042.  
  12043.     Insertion_Flag : character := '@';
  12044.  
  12045.     subtype Message_Text_Range is positive range 1..64;
  12046.  
  12047.     Message_Text : constant array (Message_Type) of
  12048.         string (Message_Text_Range) := (
  12049.     -- 1234567890123456789012345678901234567890123456789012345678901234
  12050.     -- Base_Out_Of_Legal_Range_Use_16   =>
  12051.       "This base " &
  12052.            Insertion_Flag  -- insert a String
  12053.            & " is not in the range 2 to 16. Assuming base 16.      ",
  12054.     -- Based_Literal_Delimiter_Mismatch =>
  12055.       "Based_literal delimiters must be the same.                      ",
  12056.     -- Character_Can_Not_Start_Token    =>
  12057.       "This character " &
  12058.             Insertion_Flag  -- insert a character
  12059.             & " can not start a token.                         ",
  12060.     -- Character_Is_Non_ASCII  =>
  12061.       "This value x@VALUE@x is not an ASCII character.                 ",
  12062.         --|? should display the value, but this message is unlikely.
  12063.         --|? see Lex.bdy
  12064.     -- Character_Is_Non_Graphic=>
  12065.       "This character with decimal value" &
  12066.                       Insertion_Flag
  12067.                                           -- insert the decimal value
  12068.                       & " is not a graphic_character.  ",
  12069.     -- Consecutive_Underlines  =>
  12070.       "Consecutive underlines are not allowed.                         ",
  12071.     -- Digit_Invalid_For_Base  =>
  12072.       "This digit " &
  12073.            Insertion_Flag  -- insert a Character
  12074.         & " is out of range for the base specified.            ",
  12075.     -- Digit_Needed_After_Radix_Point   =>
  12076.       "At least one digit must appear after a radix point              ",
  12077.     -- Digit_Needed_Before_Radix_Point  =>
  12078.       "At least one digit must appear before a radix point             ",
  12079.     -- Exponent_Missing_Integer_Field   =>
  12080.       "The exponent is missing its integer field.                      ",
  12081.     -- Illegal_Use_Of_Single_Quote  =>
  12082.       "Single quote is not used for an attribute or character literal. ",
  12083.     -- Integer_Literal_Conversion_Exception_Using_1 =>
  12084.       "Error while evaluating a integer_literal. Using a value of '1'. ",
  12085.     -- Leading_Underline    =>
  12086.       "Initial underlines are not allowed.                             ",
  12087.     -- Missing_Second_Based_Literal_Delimiter   =>
  12088.       "Second based_literal delimiter is missing.                      ",
  12089.     -- Negative_Exponent_Illegal_In_Integer =>
  12090.       "A negative exponent is illegal in an integer literal.           ",
  12091.     -- No_Ending_String_Delimiter   =>
  12092.       "String is improperly terminated by the end of the line.         ",
  12093.     -- No_Integer_In_Based_Number   =>
  12094.       "A based number must have a value.                               ",
  12095.     -- Only_Graphic_Characters_In_Strings   =>
  12096.       "This non-graphic character with decimal value" &
  12097.                             Insertion_Flag
  12098.                                                -- insert the decimal value
  12099.                           & " found in string. ",
  12100.     -- Real_Literal_Conversion_Exception_Using_1    =>
  12101.       "Error while evaluating a real_literal. Using a value of '1.0'.  ",
  12102.     -- Source_Line_Maximum_Exceeded =>
  12103.       "Maximum allowable source line number of " &
  12104.                            Insertion_Flag
  12105.                                                -- insert an Integer'IMAGE
  12106.                                              & " exceeded.             ",
  12107.     -- Source_Line_Too_Long =>
  12108.       "Source line number " &
  12109.                 Insertion_Flag  -- insert an Integer'IMAGE
  12110.             & " is too long.                               ",
  12111.     -- Space_Must_Separate_Num_And_Ids      =>
  12112.       "A space must separate numeric_literals and identifiers.         ",
  12113.     -- Terminal_Underline   =>
  12114.       "Terminal underlines are not allowed.                            ",
  12115.     -- Too_Many_Radix_Points        =>
  12116.       "A real_literal may have only one radix point.                   ");
  12117.  
  12118.     ------------------------------------------------------------------
  12119.     -- Subprogram Bodies Global to Package Lexical_Error_Message
  12120.     ------------------------------------------------------------------
  12121.  
  12122.     procedure Output_Message(
  12123.     In_Line       : in HD.Source_Line;
  12124.     In_Column     : in HD.Source_Column;
  12125.     In_Message_Id : in Message_Type) is
  12126.  
  12127.     begin
  12128.  
  12129.         -- output error message including line and column number
  12130.     TEXT_IO.NEW_LINE(TEXT_IO.STANDARD_OUTPUT);
  12131.     TEXT_IO.PUT_LINE(
  12132.             FILE => TEXT_IO.STANDARD_OUTPUT,
  12133.         ITEM =>
  12134.          "Lexical Error: Line: "
  12135.         & HD.Source_Line'IMAGE  (In_Line)
  12136.         & " Column: "
  12137.         & HD.Source_Column'IMAGE(In_Column)
  12138.         & " - "
  12139.         & Message_Text(In_Message_Id));
  12140.  
  12141.     end Output_Message;
  12142.  
  12143.     ------------------------------------------------------------------
  12144.  
  12145.     procedure Output_Message(
  12146.     In_Line       : in HD.Source_Line;
  12147.     In_Column     : in HD.Source_Column;
  12148.     In_Insertion_Text : in string; --| text to insert.
  12149.     In_Message_Id : in Message_Type) is
  12150.  
  12151.         --------------------------------------------------------------
  12152.         -- Declarations for SubProgram Output_Message
  12153.         --------------------------------------------------------------
  12154.  
  12155.         Insertion_Index : positive :=
  12156.             (Message_Text_Range'Last + 1);
  12157.         --| if insertion flag is not found,
  12158.         --| then we append the In_Message_Text to the message
  12159.  
  12160.     ------------------------------------------------------------------
  12161.  
  12162.     begin
  12163.  
  12164.     --| Algorithm
  12165.     --|
  12166.     --| Find the insertion point.
  12167.     --| if the Message_Text doesn't have an Insertion_Flag,
  12168.     --| then set the Insertion_Index to the end of the message.
  12169.  
  12170.     for i in Message_Text_Range loop
  12171.         if (Insertion_Flag = Message_Text(In_Message_Id)(i) ) then
  12172.             Insertion_Index := i;
  12173.             exit;
  12174.         end if;
  12175.     end loop;
  12176.  
  12177.     -- output error message with test, line and column number
  12178.     TEXT_IO.NEW_LINE(TEXT_IO.STANDARD_OUTPUT);
  12179.     TEXT_IO.PUT_LINE(
  12180.             FILE => TEXT_IO.STANDARD_OUTPUT,
  12181.         ITEM =>
  12182.           "Lexical Error: Line: "
  12183.         & HD.Source_Line'IMAGE  (In_Line)
  12184.         & " Column: "
  12185.         & HD.Source_Column'IMAGE(In_Column)
  12186.         & " - "
  12187.         & Message_Text(In_Message_Id)(1..(Insertion_Index-1))
  12188.         & In_Insertion_Text
  12189.         & Message_Text(In_Message_Id)
  12190.                     ((Insertion_Index+1)..Message_Text_Range'Last));
  12191.  
  12192.     end Output_Message;
  12193.  
  12194.     ------------------------------------------------------------------
  12195.  
  12196. end Lexical_Error_Message;
  12197.  
  12198. ----------------------------------------------------------------------
  12199.  
  12200.  
  12201. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12202. --HOSTDEP.BDY
  12203. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12204.  
  12205. package body Host_Dependencies is
  12206. --| Simple data types and constants involving the host machine
  12207.  
  12208.                             -- Operations --
  12209.  
  12210.     function FindTabColumn (          -- see subprogram specification
  12211.         InColumn : Source_Column
  12212.         ) return Source_Column is
  12213.  
  12214.     --| Effects
  12215.     --| Tabs are positioned every eight columns starting at column 1.
  12216.  
  12217.     Tab_Width : constant := 8; --| number of columns a tab takes up.
  12218.  
  12219.     begin
  12220.         return (InColumn + ( Tab_Width - ( InColumn mod Tab_Width) ) );
  12221.     end FindTabColumn;
  12222.  
  12223. end Host_Dependencies;
  12224.  
  12225.  
  12226. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12227. --ORDSET.SPC
  12228. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12229. with BinaryTrees;
  12230.  
  12231. generic
  12232.       type ItemType is private;
  12233.         --| Information being contained a the member of the set.
  12234.     
  12235.       with function "<" (X, Y :in    ItemType) return boolean;
  12236.  
  12237. package OrderedSets is
  12238.  
  12239. --| Overview
  12240. --| This abstractions is a counted ordered set.  Associated with each member
  12241. --| of the set is a count of the number of times it appears in the set.  In
  12242. --| addition, there is an ordering associated with the members.  This allows
  12243. --| fast insertion, and makes it possible to iterate over the set in order.
  12244. --|-
  12245. --| Operations:
  12246. --|
  12247. --| Cardinality        Return number of members in a set.
  12248. --| Create        Creates an empty set.
  12249. --| Destroy        Destroys a set and returns the space it occupies.
  12250. --| GetCount        Returns the number of times some member appears in
  12251. --|            a set.
  12252. --| Insert        Insert a member into a set.
  12253. --| MakeSetIter        Return a SetIter which will begin an iteration.
  12254. --| More        Test for more elements during iteration
  12255. --| Next        Return the next element during iteration and 
  12256. --|            bump the iterator.
  12257.  
  12258.  
  12259.                   -- Types --
  12260.  
  12261. type Set is private;  --| This is the type exported to represent 
  12262.                       --| the ordered set.
  12263.  
  12264. type SetIter is private;  --| This is the type exported whose 
  12265.                           --| purpose is to walk over a set.
  12266.  
  12267.  
  12268. ------------------------------------------------------------------------------
  12269.  
  12270. function Cardinality(    --| Return the number of members in the set.
  12271.     S:in Set        --| The set whose members are being counted.
  12272.     ) return natural;
  12273.  
  12274.  
  12275. function Create   --| Return the empty set.
  12276.     return Set;
  12277.  
  12278.  
  12279. procedure Destroy(    --| Destroy a set and return its space.
  12280.     S:in out Set    --| Set being destroyed.
  12281.     );
  12282.  
  12283. function GetCount(    --| Return the count of member given by an iterator
  12284.     I:in SetIter
  12285.     ) return natural;
  12286.  
  12287.  
  12288. procedure Insert(    --| Insert a member M into set S.
  12289.     M:in ItemType;    --| Member being inserted.
  12290.     S :in out Set    --| Set being inserted into.
  12291.     );
  12292.  
  12293. function MakeSetIter(    --| Return an iterator over the set S
  12294.     S:in Set        --| Set being iterate over.
  12295.     ) return SetIter;
  12296.  
  12297. function More(        --| Return True iff iterator I is not empty
  12298.     I:in SetIter    --| The iterator.
  12299.     ) return boolean;
  12300.  
  12301. procedure Next(
  12302. --| Return the current member in the iteration and increment the iterator.
  12303.     I:in out SetIter;    --| The iterator.
  12304.     M: out ItemType    --| The current member being returned.
  12305.     );
  12306.  
  12307. -----------------------------------------------------------------------------
  12308.  
  12309. private 
  12310.  
  12311.    type Member is 
  12312.        record 
  12313.          Info: ItemType;
  12314.          Count: natural;
  12315.        end record;
  12316.  
  12317.    function "<" (
  12318.     X: in Member;
  12319.     Y: in Member
  12320.     ) return boolean;
  12321.  
  12322.    package TreePkg is new BinaryTrees(ItemType => Member, "<" => "<");
  12323.  
  12324.    type Set is
  12325.        record 
  12326.          SetRep: TreePkg.Tree;
  12327.        end record;
  12328.  
  12329.    type SetIter is
  12330.        record
  12331.          Place: TreePkg.TreeIter;
  12332.          Count: natural;
  12333.        end record;
  12334.  
  12335. end OrderedSets;
  12336. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12337. --ORDSET.BDY
  12338. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12339. package body OrderedSets is
  12340. -------------------------------------------------------------------------------
  12341. --                Local Subprograms
  12342. -------------------------------------------------------------------------------
  12343.  
  12344. -------------------------------------------------------------------------------
  12345.  
  12346. function "<" (     --| Implements "<" for the type member.
  12347.          X :in   Member;
  12348.          Y :in   Member 
  12349. ) return boolean is
  12350.  
  12351. begin
  12352.      return X.Info < Y.Info;
  12353. end;
  12354.  
  12355. -------------------------------------------------------------------------------
  12356.  
  12357.  
  12358. -------------------------------------------------------------------------------
  12359. --               Visible Subprograms
  12360. -------------------------------------------------------------------------------
  12361.  
  12362.  
  12363. -------------------------------------------------------------------------------
  12364.  
  12365. function Cardinality ( 
  12366.               S :in Set  --| The set whose size is being computed.
  12367. ) return natural is
  12368.  
  12369.     T        :TreePkg.TreeIter;
  12370.     M        :Member;
  12371.     count    :natural := 0;
  12372. begin
  12373.     T := TreePkg.MakeTreeIter (S.SetRep);
  12374.     while TreePkg.More (T) loop
  12375.         TreePkg.Next (T, M);
  12376.         count := count + 1;
  12377.     end loop;
  12378.     return count;
  12379. end Cardinality;            
  12380.  
  12381. -------------------------------------------------------------------------------
  12382.  
  12383. function Create
  12384.  
  12385. return Set is
  12386.     S :Set;
  12387. begin
  12388.     S.SetRep := TreePkg.Create;
  12389.     return S;
  12390. end Create;
  12391.  
  12392. ------------------------------------------------------------------------------
  12393.  
  12394. procedure Destroy ( 
  12395.          S :in out Set
  12396. ) is
  12397.  
  12398. begin
  12399.     TreePkg.DestroyTree (S.SetRep);
  12400. end Destroy;
  12401.  
  12402. -----------------------------------------------------------------------------
  12403.  
  12404. function GetCount (
  12405.          I :in    SetIter
  12406. ) return natural is
  12407.  
  12408. begin
  12409.      return I.Count;
  12410. end;
  12411.  
  12412. -----------------------------------------------------------------------------
  12413. procedure Insert(
  12414.           M :in     ItemType;
  12415.           S :in out Set
  12416. ) is
  12417.     Subtree       :TreePkg.Tree;
  12418.     Exists        :boolean;
  12419.     MemberToEnter :Member := ( Info => M, count => 1);
  12420. begin
  12421.     --| If NewMember doesn't exist in SetRep it is added.  If it does exist
  12422.     --| Exists comes back true and then M's count is updated.  Since the
  12423.     --| first argument of TreePkg.Insert is in out, after Insert 
  12424.     --| MemberToEnter has the value stored in the tree.  Thus if we
  12425.     --| need to update the count we can simple bump the count in MemberToEnter.
  12426.  
  12427.     TreePkg.InsertNode (MemberToEnter, S.SetRep, SubTree, Exists);    
  12428.     if Exists then 
  12429.         MemberToEnter.Count := MemberToEnter.Count + 1;
  12430.         TreePkg.Deposit (MemberToEnter, SubTree);
  12431.     end if;        
  12432. end Insert;
  12433.  
  12434. ------------------------------------------------------------------------------
  12435.  
  12436. function MakeSetIter (   
  12437.          S :in Set
  12438. )        return SetIter is
  12439.  
  12440.     I :SetIter;
  12441. begin
  12442.     I.Place := TreePkg.MakeTreeIter (S.SetRep);
  12443.     I.Count := 0;
  12444.     return I;
  12445. end;
  12446.  
  12447.  ------------------------------------------------------------------------------
  12448.  
  12449. function More ( 
  12450.           I :in     SetIter
  12451. )         return boolean is
  12452.  
  12453. begin
  12454.     return TreePkg.More (I.Place);
  12455. end;
  12456.     
  12457. ------------------------------------------------------------------------------
  12458.  
  12459. procedure Next (
  12460.          I :in out SetIter;
  12461.          M :   out ItemType
  12462. ) is
  12463.     TempMember :Member;
  12464. begin
  12465.     TreePkg.Next (I.Place, TempMember);
  12466.     M := TempMember.Info;
  12467.     I.Count := TempMember.Count;
  12468. end;
  12469.  
  12470. ------------------------------------------------------------------------------
  12471.  
  12472. end OrderedSets;
  12473. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12474. --PGFILE.SPC
  12475. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12476. with Text_IO;
  12477. with String_Pkg;
  12478.  
  12479. package Paginated_Output is
  12480.  
  12481. --| Create paginated text files with user defined heading, footing, and page length.
  12482.                                                     pragma Page;
  12483. --| Overview:
  12484.  
  12485. --| The Paginated_Output package is used to create paginated output files.
  12486. --| When such a file is created, the page length, page header and footer length
  12487. --| are specified. Several operations are provided for setting/replacing the
  12488. --| header or the footer text which will appear on each output page. An escape
  12489. --| sequence ~X(Ann) may be used to insert texts in the header/footer texts.
  12490. --| The escape character X may be:
  12491. --|-
  12492. --|     F    the current external file name
  12493. --|     P    the current page number
  12494. --|     D    the current date (eg. 03/15/85)
  12495. --|     C    the current calendar date (eg. March 15, 1985)
  12496. --|     T    the current time (eg. 04:53:32)
  12497. --|+
  12498. --| The optional alignment character A may be:
  12499. --|-
  12500. --|    L    left align the text
  12501. --|    R    right allign the text
  12502. --|    C    center the text
  12503. --|+
  12504. --| nn following the alignment character specifies the number of spaces the
  12505. --| text will displace in the header/footer texts.
  12506. --|
  12507. --| Case is not significant after the tilde (~).  If the tilde is followed by
  12508. --| any other character, only the second character is printed unless the line
  12509. --| ends with a tilde in which case the line will be terminated one character
  12510. --| before the tilde.
  12511. --| 
  12512. --| The header is printed just before the first line of a page is output, and
  12513. --| the footer is printed just after the last line.  Thus, if a paginated file
  12514. --| is opened and closed without any calls to print a line in between, the
  12515. --| output is a null file.
  12516. --|
  12517. --| This package knows nothing about (and places no limits on) the length or
  12518. --| contents of each line sent to the output file.  In particular, if the line
  12519. --| contains ASCII control codes for new line, form feed, and/or vertical tab
  12520. --| the output file will not be properly paginated.  Normal usage is to call
  12521. --| Create_Paginated_File, call Set_Header/Set_Footer, call Put_Line repeatedly
  12522. --| to output a sequence of lines of text, and finally call
  12523. --| Close_Paginated_File to complete the last page and close the file.
  12524.  
  12525. --| N/A: Effects, Requires, Modifies, Raises
  12526.                                                     pragma Page;
  12527.             -- Exceptions --
  12528.  
  12529. Files_Already_Linked        --| Raised if an attempt is made to
  12530.           : exception;    --| link two linked paginated files 
  12531. File_Already_Open : exception;    --| Raised if create is attempted
  12532.                 --| for an already existing file.
  12533. File_Error        : exception;    --| Raised if unable to open a file
  12534.                 --| other than File_Already_Open
  12535. File_Not_Open     : exception;    --| Raised if close is attempted
  12536.                 --| for an unopened file.
  12537. Invalid_Count     : exception;    --| Raised if a requested count 
  12538.                 --| can not be serviced.
  12539. Invalid_File      : exception;    --| Raised if output is attempted
  12540.                 --| with an invalid file handle.
  12541. Output_Error      : exception;    --| Raised if error is encountered
  12542.                 --| during an output operation.
  12543. Page_Layout_Error : exception;    --| Raised if page specification
  12544.                 --| is invalid.
  12545. Page_Overflow     : exception;    --| Raised if specified reserve
  12546.                 --| value exceeds the page size.
  12547. Text_Overflow     : exception;    --| Raised if header/footer text
  12548.                 --| overflows area.
  12549.                                                     pragma Page;
  12550.               -- Packages --
  12551.  
  12552.     package TIO renames Text_IO;
  12553.  
  12554.     package SP  renames String_Pkg;
  12555.  
  12556.                -- Types --
  12557.  
  12558. subtype Date_String is STRING (1 .. 8);
  12559.                 --| Date string
  12560. subtype Time_String is STRING (1 .. 8);
  12561.                 --| Time string
  12562. type Variable_String_Array is    --| Array of variable length strings
  12563.     array (POSITIVE range <>) of SP.String_Type;
  12564.  
  12565. type Paginated_File_Handle is    --| Handle to be passed around in a
  12566.     limited private;        --| program that uses paginated output.
  12567.  
  12568. type Paginated_Output_Mode is (STD, CUR);
  12569.                 --| Paginated output mode
  12570.                                                     pragma Page;
  12571.             -- Operations --
  12572.  
  12573. procedure Create_Paginated_File(--| Create a paginated output file
  12574.                 --| and return the file handle.
  12575.     File_Name   : in     STRING                := "";
  12576.                 --| The name of the file to be created.
  12577.     File_Handle : in out Paginated_File_Handle;
  12578.                 --| Handle to be used for subsequent
  12579.                 --| operations
  12580.     Page_Size   : in     NATURAL               := 66;
  12581.                 --| The number of lines per page
  12582.     Header_Size : in     NATURAL               := 6;
  12583.                 --| The number of header text lines
  12584.     Footer_Size : in     NATURAL               := 6;
  12585.                 --| The number of footer text lines
  12586.     Output_Mode : in     Paginated_Output_Mode := STD
  12587.                 --| Output mode
  12588.     ); 
  12589.  
  12590. --| Raises:
  12591. --| File_Already_Open, File_Error, Page_Layout_Error
  12592.  
  12593. --| Requires:
  12594. --| File_Name is an valid external name of the file to be created (If
  12595. --| it is omitted, the current output file is selected).  Page_Size,
  12596. --| Header_Size, and Footer_Size are optional values (if omitted 66,
  12597. --| 6, and 6 are set, respectively) to be used for the page layout
  12598. --| of the file to be created.  Page_Size specifies the total number
  12599. --| of lines per page (including the areas for header and footer).
  12600. --| Header_Size and Footer_Size specify the number of lines to be
  12601. --| reserved for the header and footer areas, respectively.
  12602.  
  12603. --| Effects:
  12604. --| Creates a new paginated file with Page_Size number of lines
  12605. --| per page and Header_Size and Footer_Size number of lines
  12606. --| reserved for header and footer, respectively.  Access to the
  12607. --| paginated file control structure Paginated_File_Handle is
  12608. --| returned for use in subsequent operations.
  12609.  
  12610. --| Errors:
  12611. --| If any of the page layout values are negative, the exception
  12612. --| Page_Layout_Error is raised.  Also if the total number of lines
  12613. --| in the header and footer plus one exceeds Page_Size, the same
  12614. --| exception is raised.  This guarantees that at least one line of
  12615. --| text can appear on each output page.
  12616. --| If the output file with the specified File_Name is already open
  12617. --| File_Already_Open exception is raised.
  12618. --| If the file cannot be opened for any other reason, the exception
  12619. --| File_Error is raise.
  12620.  
  12621. --| N/A: Modifies
  12622.                                                     pragma Page;
  12623. procedure Set_Standard_Paginated_File(
  12624.                 --| Set the standard paginated output file
  12625.                 --| characteristics. 
  12626.     File_Name   : in STRING;    --| The name of the file to be set.
  12627.     Page_Size   : in NATURAL;    --| The number of lines per page
  12628.     Header_Size : in NATURAL;    --| The number of header text lines
  12629.     Footer_Size : in NATURAL    --| The number of footer text lines
  12630.     ); 
  12631.  
  12632. --| Raises:
  12633. --| File_Already_Open, File_Error, Page_Layout_Error
  12634.  
  12635. --| Requires:
  12636. --| File_Name is an valid external name of the file to be created
  12637. --| Page_Size, Header_Size, and Footer_Size are used for the page layout
  12638. --| of the file.
  12639.  
  12640. --| Effects:
  12641. --| Sets the standard paginated file to the given file name and sets the 
  12642. --| page layout as specified. 
  12643.  
  12644. --| Errors:
  12645. --| If any of the page layout values are negative, the exception
  12646. --| Page_Layout_Error is raised.  Also if the total number of lines
  12647. --| in the header and footer plus one exceeds Page_Size, the same
  12648. --| exception is raised.  This guarantees that at least one line of
  12649. --| text can appear on each output page.
  12650. --| If the output file with the specified File_Name is already open
  12651. --| File_Already_Open exception is raised.
  12652. --| If the file cannot be opened for any other reason, the exception
  12653. --| File_Error is raise.
  12654.  
  12655. --| N/A: Modifies
  12656.                                                     pragma page;
  12657. procedure Duplicate_Paginated_File(
  12658.                 --| Duplicate an already existing
  12659.                 --| paginated file and return the
  12660.                 --| file handle.
  12661.     Old_Handle : in     Paginated_File_Handle;
  12662.                 --| Existing paginated file handle
  12663.     New_Handle : in out Paginated_File_Handle
  12664.                 --| Handle of the new paginated file
  12665.     ); 
  12666.  
  12667. --| Requires:
  12668. --| Old_Handle for the existing paginated file to be duplicated.
  12669. --| The new handle (duplocated from Old_Handle) to be used to refer
  12670. --| to the same paginated file.
  12671.  
  12672. --| Effects:
  12673. --| Handle for the aginated file refered to be Old_Handle will be
  12674. --| duplicated in New_Handle.
  12675.  
  12676. --| N/A: Raises, Modifies, Errors
  12677.                                                     pragma Page;
  12678. procedure Set_Page_Layout(    --| Set the page layout for the 
  12679.                 --| paginated file.
  12680.     Page_Size   : in NATURAL;    --| The number of lines per page
  12681.     Header_Size : in NATURAL;    --| The number of header text lines
  12682.     Footer_Size : in NATURAL    --| The number of footer text lines
  12683.     );
  12684.  
  12685. --| Raises:
  12686. --| Page_Layout_Error
  12687.  
  12688. --| Requires:
  12689. --| Page_Size specifies the total number of lines per page (including the
  12690. --| area for header & footer).
  12691. --| Header_Size and Footer_Size specifies the number of lines to be
  12692. --| reserved for the header and footer area, respectively.
  12693.  
  12694. --| Effects:
  12695. --| A paginated file is set with Page_Size number of lines per
  12696. --| page and Header_Size and Footer_Size number of lines
  12697. --| reserved for header and footer, respectively.
  12698. --| A page eject is performed if not at the top of the page before
  12699. --| the new page layout values are set.
  12700.  
  12701. --| Errors:
  12702. --| If any of the page layout values are negative, the exception
  12703. --| Page_Layout_Error is raised.  Also if the total number of lines
  12704. --| in the header and footer plus one exceeds Page_Size, the exception
  12705. --| Page_Layout_Error is raised.
  12706.  
  12707. --| N/A: Modifies
  12708.  
  12709.  
  12710. procedure Set_Page_Layout(    --| Set the page layout for the 
  12711.                 --| paginated file.
  12712.     File_Handle : in Paginated_File_Handle;
  12713.                 --| The paginated file to be set 
  12714.                 --| with the given page layout
  12715.     Page_Size   : in NATURAL;    --| The number of lines per page
  12716.     Header_Size : in NATURAL;    --| The number of header text lines
  12717.     Footer_Size : in NATURAL    --| The number of footer text lines
  12718.     );
  12719.  
  12720. --| Raises:
  12721. --| Page_Layout_Error
  12722.  
  12723. --| Requires:
  12724. --| File_Handle is the access to the paginated file control structure
  12725. --| returned by Create_Paginated_File.  Page_Size specifies the total
  12726. --| number of lines per page (including the area for header & footer).
  12727. --| Header_Size and Footer_Size specifies the number of lines to be
  12728. --| reserved for the header and footer area, respectively.
  12729.  
  12730. --| Effects:
  12731. --| A paginated file is set with Page_Size number of lines per
  12732. --| page and Header_Size and Footer_Size number of lines
  12733. --| reserved for header and footer, respectively.
  12734. --| A page eject is performed if not at the top of the page before
  12735. --| the new page layout values are set.
  12736.  
  12737. --| Errors:
  12738. --| If any of the page layout values are negative, the exception
  12739. --| Page_Layout_Error is raised.  Also if the total number of lines
  12740. --| in the header and footer plus one exceeds Page_Size, the exception
  12741. --| Page_Layout_Error is raised.
  12742.  
  12743. --| N/A: Modifies
  12744.                                                     pragma Page;
  12745. procedure Link_Paginated_File(    --| Link paginated files into a chain
  12746.     File_Handle1 : in Paginated_File_Handle;
  12747.                 --| Handle to be linked
  12748.     File_Handle2 : in Paginated_File_Handle
  12749.                 --| Handle to be linked
  12750.     );
  12751.  
  12752. --| Raises:
  12753. --| Files_Already_Linked
  12754.  
  12755. --| Requires:
  12756. --| File_Handle1 and File_Handle2, access to the paginated file control
  12757. --| structures.
  12758.  
  12759. --| Effects:
  12760. --| File_Handle1 and File_Handle2 in a chain so in the given order such that
  12761. --| subsequent operations to File_Handle1 are reflected in both files. 
  12762. --| Any operations to File_Handle2 are NOT performed for File_Handle1.
  12763.  
  12764. --| Errors:
  12765. --| If either of the files have been linked, raises Files_Already_Linked.
  12766.  
  12767. --| N/A: Modifies
  12768.  
  12769.  
  12770. procedure Unlink_Paginated_File(
  12771.     File_Handle : in Paginated_File_Handle
  12772.     );
  12773.  
  12774. --| Requires:
  12775. --| File_Handle which accesses a paginated file control structure.
  12776.  
  12777. --| Effects:
  12778. --| Takes File_Handle out of a previously linked chain.
  12779.  
  12780. --| N/A: Raises, Modifies, Errors
  12781.                                                     pragma Page;
  12782. procedure Set_File_Name(    --| Set arbitrary file name for ~f substitute
  12783.     File_Handle : in Paginated_File_Handle;
  12784.                 --| The paginated file handle
  12785.     File_Name   : in STRING    --| The name of the file to be set.
  12786.     ); 
  12787.  
  12788. --| Raises:
  12789. --| Invalid_File
  12790.  
  12791. --| Requires:
  12792. --| File_Handle is a file handle to a paginated file
  12793. --| File_Name is any name of the file to be saved for ~f substitution
  12794.  
  12795. --| Effects:
  12796. --| Sets the name of the ~f substitution file to File_Name
  12797.  
  12798. --| Errors:
  12799. --| If the file handel is invalid Invalid_File is raise.
  12800.  
  12801. --| N/A: Modifies
  12802.  
  12803.  
  12804. procedure Reset_File_Name(    --| Reset file name to default
  12805.     File_Handle : in Paginated_File_Handle
  12806.     );
  12807.  
  12808.  
  12809. procedure Set_File_Name(    --| Set arbitrary file name for ~f substitute
  12810.     File_Name   : in STRING    --| The name of the file to be set.
  12811.     ); 
  12812.  
  12813. --| Raises:
  12814. --| Invalid_File
  12815.  
  12816. --| Requires:
  12817. --| File_Name is any name of the file to be saved for ~f substitution
  12818. --| for paginated standard output
  12819.  
  12820. --| Effects:
  12821. --| Sets the name of the ~f substitution file to File_Name
  12822.  
  12823. --| N/A: Modifies
  12824.  
  12825.  
  12826. procedure Reset_File_Name;    --| Reset file name to default
  12827.                                                     pragma Page;
  12828. procedure Set_Date(        --| Set arbitrary string for ~d date substitute
  12829.     File_Handle : in Paginated_File_Handle;
  12830.                 --| The paginated file handle
  12831.     Date        : in Date_String--| The date string
  12832.     ); 
  12833.  
  12834. --| Raises:
  12835. --| Invalid_File
  12836.  
  12837. --| Requires:
  12838. --| File_Handle is a file handle to a paginated file
  12839. --| Date is any string to be saved for ~d substitution
  12840.  
  12841. --| Effects:
  12842. --| Sets the string of the ~d substitution to date
  12843.  
  12844. --| Errors:
  12845. --| If the file handel is invalid Invalid_File is raise.
  12846.  
  12847. --| N/A: Modifies
  12848.  
  12849.  
  12850. procedure Reset_Date(        --| Reset date to current date
  12851.     File_Handle : in Paginated_File_Handle
  12852.     );
  12853.  
  12854.  
  12855. procedure Set_Date(        --| Set arbitrary string for ~d date substitute
  12856.     Date : in Date_String    --| The date string
  12857.     ); 
  12858.  
  12859. --| Requires:
  12860. --| Date is any string to be saved for ~d substitution
  12861.  
  12862. --| Effects:
  12863. --| Sets the string of the ~d substitution to date
  12864.  
  12865. --| N/A: Raises, Errors, Modifies
  12866.  
  12867.  
  12868. procedure Reset_Date;        --| Reset date to current date
  12869.                                                     pragma Page;
  12870. procedure Set_Calendar(        --| Set arbitrary string for ~c date substitute
  12871.     File_Handle : in Paginated_File_Handle;
  12872.                 --| The paginated file handle
  12873.     Calendar        : in STRING    --| The date string
  12874.     ); 
  12875.  
  12876. --| Raises:
  12877. --| Invalid_File
  12878.  
  12879. --| Requires:
  12880. --| File_Handle is a file handle to a paginated file
  12881. --| Date is any string to be saved for ~c substitution
  12882.  
  12883. --| Effects:
  12884. --| Sets the string of the ~c substitution to date
  12885.  
  12886. --| Errors:
  12887. --| If the file handel is invalid Invalid_File is raise.
  12888.  
  12889. --| N/A: Modifies
  12890.  
  12891.  
  12892. procedure Reset_Calendar(    --| Reset date to current calendar date
  12893.     File_Handle : in Paginated_File_Handle
  12894.     );
  12895.  
  12896.  
  12897. procedure Set_Calendar(        --| Set arbitrary string for ~c date substitute
  12898.     Calendar : in STRING    --| The date string
  12899.     ); 
  12900.  
  12901. --| Requires:
  12902. --| Date is any string to be saved for ~c substitution
  12903.  
  12904. --| Effects:
  12905. --| Sets the string of the ~c substitution to date
  12906.  
  12907. --| N/A: Raises, Errors, Modifies
  12908.  
  12909.  
  12910. procedure Reset_Calendar;    --| Reset date to current calendar date
  12911.                                                     pragma Page;
  12912. procedure Set_Time(        --| Set arbitrary string for ~t time substitute
  12913.     File_Handle : in Paginated_File_Handle;
  12914.                 --| The paginated file handle
  12915.     Time        : in Time_String--| The time string
  12916.     ); 
  12917.  
  12918. --| Raises:
  12919. --| Invalid_File
  12920.  
  12921. --| Requires:
  12922. --| File_Handle is a file handle to a paginated file
  12923. --| Time is any string to be saved for ~t substitution
  12924.  
  12925. --| Effects:
  12926. --| Sets the string of the ~t substitution to time
  12927.  
  12928. --| Errors:
  12929. --| If the file handel is invalid Invalid_File is raise.
  12930.  
  12931. --| N/A: Modifies
  12932.  
  12933.  
  12934. procedure Reset_Time(        --| Reset time to current time
  12935.     File_Handle : in Paginated_File_Handle
  12936.     );
  12937.  
  12938.  
  12939. procedure Set_Time(        --| Set arbitrary string for ~t time substitute
  12940.     Time : in Time_String    --| The time string
  12941.     ); 
  12942.  
  12943. --| Requires:
  12944. --| Time is any string to be saved for ~t substitution
  12945.  
  12946. --| Effects:
  12947. --| Sets the string of the ~t substitution to time
  12948.  
  12949. --| N/A: Raises, Errors, Modifies
  12950.  
  12951.  
  12952. procedure Reset_Time;        --| Reset time to current time
  12953.                                                     pragma Page;
  12954. procedure Set_Page(        --| Set arbitrary string for ~p page substitute
  12955.     File_Handle : in Paginated_File_Handle;
  12956.                 --| The paginated file handle
  12957.     Page        : in POSITIVE    --| The page number
  12958.     ); 
  12959.  
  12960. --| Raises:
  12961. --| Invalid_File
  12962.  
  12963. --| Requires:
  12964. --| File_Handle is a file handle to a paginated file
  12965. --| page is any string to be saved for ~p substitution
  12966.  
  12967. --| Effects:
  12968. --| Sets the page number for ~p substitution
  12969.  
  12970. --| Errors:
  12971. --| If the file handel is invalid Invalid_File is raise.
  12972.  
  12973. --| N/A: Modifies
  12974.  
  12975.  
  12976. procedure Reset_Page(        --| Reset page to 1
  12977.     File_Handle : in Paginated_File_Handle
  12978.     );
  12979.  
  12980.  
  12981. procedure Set_Page(        --| Set arbitrary string for ~p page substitute
  12982.     Page : in POSITIVE        --| The page number
  12983.     ); 
  12984.  
  12985. --| Requires:
  12986. --| page is any string to be saved for ~p substitution
  12987.  
  12988. --| Effects:
  12989. --| Sets the page number for ~p substitution
  12990.  
  12991. --| N/A: Raises, Errors, Modifies
  12992.  
  12993.  
  12994. procedure Reset_Page;        --| Rest page to 1
  12995.                                                     pragma Page;
  12996. procedure Set_Header(
  12997.     Header_Text : in Variable_String_Array
  12998.     );
  12999.  
  13000.  
  13001. procedure Set_Header(        --| Set the header text on a paginated
  13002.                 --| output file.
  13003.     File_Handle : in Paginated_File_Handle;
  13004.                 --| Paginated file to be set 
  13005.                 --| with the header text
  13006.     Header_Text : in Variable_String_Array
  13007.                 --| Sequence of header lines
  13008.     );
  13009.  
  13010. --| Raises:
  13011. --| Invalid_File, Text_Overflow
  13012.  
  13013. --| Requires:
  13014. --| File_Handle is the access to the paginated file control structure
  13015. --| returned by Create_Paginated_File.  Header_Text is the array
  13016. --| of text to be used for the page header.
  13017.  
  13018. --| Effects:
  13019. --| The header text of File_Handle is set to Header_Text.  Note that
  13020. --| the replaced header text will not be printed until the next
  13021. --| page of the output.
  13022.  
  13023. --| Errors:
  13024. --| If File_Handle is not a valid access to a paginated file control
  13025. --| structure exception Invalid_File is raised.
  13026. --| Specification of a header text array which implies a greater
  13027. --| number of lines than reserved for by Create_Paginated_File or
  13028. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  13029.  
  13030. --| N/A: Modifies
  13031.  
  13032.  
  13033. procedure Set_Header(
  13034.     Header_Line : in POSITIVE;
  13035.     Header_Text : in STRING
  13036.     );
  13037.  
  13038. procedure Set_Header(        --| Replace a line of header text on a
  13039.                 --| paginated output file.
  13040.     File_Handle : in Paginated_File_Handle;
  13041.                 --| Paginated file to be set 
  13042.                 --| with the header text
  13043.     Header_Line : in POSITIVE;    --| Line number of header to be replaced
  13044.     Header_Text : in STRING    --| Header line to replace
  13045.     );
  13046.  
  13047. --| Raises:
  13048. --| Invalid_File, Text_Overflow
  13049.  
  13050. --| Requires:
  13051. --| File_Handle is the access to the paginated file control structure
  13052. --| returned by Create_Paginated_File.  Header_Text is the text
  13053. --| to replace the existing header line at Header_Line.
  13054.  
  13055. --| Effects:
  13056. --| The header text of File_Handle at Header_Line is set to Header_Text.
  13057. --| Note that the replaced header text will not be printed until
  13058. --| the next page of the output.
  13059.  
  13060. --| Errors:
  13061. --| If File_Handle is not a valid access to a paginated file control
  13062. --| structure exception Invalid_File is raised.
  13063. --| Specification of Header_Line greater than the number of header
  13064. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13065. --| results in Text_Overflow exception to be raised.
  13066.  
  13067. --| N/A: Modifies
  13068.  
  13069.  
  13070. procedure Set_Header(
  13071.     Header_Line : in POSITIVE;
  13072.     Header_Text : in SP.String_Type
  13073.     );
  13074.  
  13075.  
  13076. procedure Set_Header(        --| Replace a line of header text on a
  13077.                 --| paginated output file.
  13078.     File_Handle : in Paginated_File_Handle;
  13079.                 --| Paginated file to be set 
  13080.                 --| with the header text
  13081.     Header_Line : in POSITIVE;    --| Line number of header to be replaced
  13082.     Header_Text : in SP.String_Type
  13083.                 --| Header line to replace
  13084.     );
  13085.  
  13086. --| Raises:
  13087. --| Invalid_File, Text_Overflow
  13088.  
  13089. --| Requires:
  13090. --| File_Handle is the access to the paginated file control structure
  13091. --| returned by Create_Paginated_File.  Header_Text is the text
  13092. --| to replace the existing header line at Header_Line.
  13093.  
  13094. --| Effects:
  13095. --| The header text of File_Handle at Header_Line is set to Header_Text.
  13096. --| Note that the replaced header text will not be printed until
  13097. --| the next page of the output.
  13098.  
  13099. --| Errors:
  13100. --| If File_Handle is not a valid access to a paginated file control
  13101. --| structure exception Invalid_File is raised.
  13102. --| Specification of Header_Line greater than the number of header
  13103. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13104. --| results in Text_Overflow exception to be raised.
  13105.  
  13106. --| N/A: Modifies
  13107.                                                     pragma Page;
  13108. procedure Set_Odd_Header(
  13109.     Header_Text : in Variable_String_Array
  13110.     );
  13111.  
  13112.  
  13113. procedure Set_Odd_Header(    --| Set the header text for the odd
  13114.                 --| pages of a paginated output file.
  13115.     File_Handle : in Paginated_File_Handle;
  13116.                 --| Paginated file to be set 
  13117.                 --| with the header text
  13118.     Header_Text : in Variable_String_Array
  13119.                 --| Sequence of header lines
  13120.     );
  13121.  
  13122. --| Raises:
  13123. --| Invalid_File, Text_Overflow
  13124.  
  13125. --| Requires:
  13126. --| File_Handle is the access to the paginated file control structure
  13127. --| returned by Create_Paginated_File.  Header_Text is the array
  13128. --| of text to be used for the odd page header.
  13129.  
  13130. --| Effects:
  13131. --| The header text for odd pages of File_Handle is set to Header_Text.
  13132. --| Note that the replaced header text will not be printed until
  13133. --| the next odd page of the output.
  13134.  
  13135. --| Errors:
  13136. --| If File_Handle is not a valid access to a paginated file control
  13137. --| structure exception Invalid_File is raised.
  13138. --| Specification of a header text array which implies a greater
  13139. --| number of lines than reserved for by Create_Paginated_File or
  13140. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  13141.  
  13142. --| N/A: Modifies
  13143.  
  13144.  
  13145. procedure Set_Odd_Header(
  13146.     Header_Line : in POSITIVE;
  13147.     Header_Text : in STRING
  13148.     );
  13149.  
  13150. procedure Set_Odd_Header(    --| Replace a line of header text on
  13151.                 --| the odd pages of a paginated
  13152.                 --| output file.
  13153.     File_Handle : in Paginated_File_Handle;
  13154.                 --| Paginated file to be set 
  13155.                 --| with the header text
  13156.     Header_Line : in POSITIVE;    --| Line number of header to be replaced
  13157.     Header_Text : in STRING    --| Header line to replace
  13158.     );
  13159.  
  13160. --| Raises:
  13161. --| Invalid_File, Text_Overflow
  13162.  
  13163. --| Requires:
  13164. --| File_Handle is the access to the paginated file control structure
  13165. --| returned by Create_Paginated_File.  Header_Text is the text
  13166. --| to replace the existing odd page header line at Header_Line.
  13167.  
  13168. --| Effects:
  13169. --| The odd page header text of File_Handle at Header_Line is set
  13170. --| to Header_Text.  Note that the replaced header text will not be
  13171. --| printed until the next odd page of the output.
  13172.  
  13173. --| Errors:
  13174. --| If File_Handle is not a valid access to a paginated file control
  13175. --| structure exception Invalid_File is raised.
  13176. --| Specification of Header_Line greater than the number of header
  13177. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13178. --| results in Text_Overflow exception to be raised.
  13179.  
  13180. --| N/A: Modifies
  13181.  
  13182.  
  13183. procedure Set_Odd_Header(
  13184.     Header_Line : in POSITIVE;
  13185.     Header_Text : in SP.String_Type
  13186.     );
  13187.  
  13188.  
  13189. procedure Set_Odd_Header(    --| Replace a line of header text on
  13190.                 --| the odd pages of a paginated
  13191.                 --| output file.
  13192.     File_Handle : in Paginated_File_Handle;
  13193.                 --| Paginated file to be set 
  13194.                 --| with the header text
  13195.     Header_Line : in POSITIVE;    --| Line number of header to be replaced
  13196.     Header_Text : in SP.String_Type
  13197.                 --| Header line to replace
  13198.     );
  13199.  
  13200. --| Raises:
  13201. --| Invalid_File, Text_Overflow
  13202.  
  13203. --| Requires:
  13204. --| File_Handle is the access to the paginated file control structure
  13205. --| returned by Create_Paginated_File.  Header_Text is the text
  13206. --| to replace the existing odd page header line at Header_Line.
  13207.  
  13208. --| Effects:
  13209. --| The odd page header text of File_Handle at Header_Line is set
  13210. --| to Header_Text.  Note that the replaced header text will not be
  13211. --| printed until the next odd page of the output.
  13212.  
  13213. --| Errors:
  13214. --| If File_Handle is not a valid access to a paginated file control
  13215. --| structure exception Invalid_File is raised.
  13216. --| Specification of Header_Line greater than the number of header
  13217. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13218. --| results in Text_Overflow exception to be raised.
  13219.  
  13220. --| N/A: Modifies
  13221.                                                     pragma Page;
  13222. procedure Set_Even_Header(
  13223.     Header_Text : in Variable_String_Array
  13224.     );
  13225.  
  13226.  
  13227. procedure Set_Even_Header(    --| Set the header text for the even
  13228.                 --| pages of a paginated output file.
  13229.     File_Handle : in Paginated_File_Handle;
  13230.                 --| Paginated file to be set 
  13231.                 --| with the header text
  13232.     Header_Text : in Variable_String_Array
  13233.                 --| Sequence of header lines
  13234.     );
  13235.  
  13236. --| Raises:
  13237. --| Invalid_File, Text_Overflow
  13238.  
  13239. --| Requires:
  13240. --| File_Handle is the access to the paginated file control structure
  13241. --| returned by Create_Paginated_File.  Header_Text is the array
  13242. --| of text to be used for the even page header.
  13243.  
  13244. --| Effects:
  13245. --| The header text for even pages of File_Handle is set to Header_Text.
  13246. --| Note that the replaced header text will not be printed until
  13247. --| the next even page of the output.
  13248.  
  13249. --| Errors:
  13250. --| If File_Handle is not a valid access to a paginated file control
  13251. --| structure exception Invalid_File is raised.
  13252. --| Specification of a header text array which implies a greater
  13253. --| number of lines than reserved for by Create_Paginated_File or
  13254. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  13255.  
  13256. --| N/A: Modifies
  13257.  
  13258.  
  13259. procedure Set_Even_Header(
  13260.     Header_Line : in POSITIVE;
  13261.     Header_Text : in STRING
  13262.     );
  13263.  
  13264.  
  13265. procedure Set_Even_Header(    --| Replace a line of header text on
  13266.                 --| the even pages of a paginated
  13267.                 --| output file.
  13268.     File_Handle : in Paginated_File_Handle;
  13269.                 --| Paginated file to be set 
  13270.                 --| with the header text
  13271.     Header_Line : in POSITIVE;    --| Line number of header to be replaced
  13272.     Header_Text : in STRING    --| Header line to replace
  13273.     );
  13274.  
  13275. --| Raises:
  13276. --| Invalid_File, Text_Overflow
  13277.  
  13278. --| Requires:
  13279. --| File_Handle is the access to the paginated file control structure
  13280. --| returned by Create_Paginated_File.  Header_Text is the text
  13281. --| to replace the existing even page header line at Header_Line.
  13282.  
  13283. --| Effects:
  13284. --| The even page header text of File_Handle at Header_Line is set
  13285. --| to Header_Text.  Note that the replaced header text will not be
  13286. --| printed until the next even page of the output.
  13287.  
  13288. --| Errors:
  13289. --| If File_Handle is not a valid access to a paginated file control
  13290. --| structure exception Invalid_File is raised.
  13291. --| Specification of Header_Line greater than the number of header
  13292. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13293. --| results in Text_Overflow exception to be raised.
  13294.  
  13295. --| N/A: Modifies
  13296.  
  13297.  
  13298. procedure Set_Even_Header(
  13299.     Header_Line : in POSITIVE;
  13300.     Header_Text : in SP.String_Type
  13301.     );
  13302.  
  13303.  
  13304. procedure Set_Even_Header(    --| Replace a line of header text on
  13305.                 --| the even pages of a paginated
  13306.                 --| output file.
  13307.     File_Handle : in Paginated_File_Handle;
  13308.                 --| Paginated file to be set 
  13309.                 --| with the header text
  13310.     Header_Line : in POSITIVE;    --| Line number of header to be replaced
  13311.     Header_Text : in SP.String_Type
  13312.                 --| Header line to replace
  13313.     );
  13314.  
  13315. --| Raises:
  13316. --| Invalid_File, Text_Overflow
  13317.  
  13318. --| Requires:
  13319. --| File_Handle is the access to the paginated file control structure
  13320. --| returned by Create_Paginated_File.  Header_Text is the text
  13321. --| to replace the existing even page header line at Header_Line.
  13322.  
  13323. --| Effects:
  13324. --| The even page header text of File_Handle at Header_Line is set
  13325. --| to Header_Text.  Note that the replaced header text will not be
  13326. --| printed until the next even page of the output.
  13327.  
  13328. --| Errors:
  13329. --| If File_Handle is not a valid access to a paginated file control
  13330. --| structure exception Invalid_File is raised.
  13331. --| Specification of Header_Line greater than the number of header
  13332. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13333. --| results in Text_Overflow exception to be raised.
  13334.  
  13335. --| N/A: Modifies
  13336.                                                     pragma Page;
  13337. procedure Set_Footer(
  13338.     Footer_Text : in Variable_String_Array
  13339.     );
  13340.  
  13341.  
  13342. procedure Set_Footer(        --| Set the footer text on a paginated
  13343.                 --| output file.
  13344.     File_Handle : in Paginated_File_Handle;
  13345.                 --| Paginated file to be set 
  13346.                 --| with the footer text
  13347.     Footer_Text : in Variable_String_Array
  13348.                 --| Sequence of lines for the footer
  13349.     );
  13350.  
  13351. --| Raises:
  13352. --| Invalid_File, Text_Overflow
  13353.  
  13354. --| Requires:
  13355. --| File_Handle is the access to the paginated file control structure
  13356. --| returned by Create_Paginated_File.  Footer_Text is the array
  13357. --| of text to be used for the page footer.
  13358.  
  13359. --| Effects:
  13360. --| The footer text of File_Handle is set to Footer_Text.  Note that
  13361. --| the replaced footer text will not be printed until the next
  13362. --| page of the output.
  13363.  
  13364. --| Errors:
  13365. --| If File_Handle is not a valid access to a paginated file control
  13366. --| structure exception Invalid_File is raised.
  13367. --| Specification of a footer text array which implies a greater
  13368. --| number of lines than reserved for by Create_Paginated_File or
  13369. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  13370.  
  13371. --| N/A: Modifies
  13372.  
  13373.  
  13374. procedure Set_Footer(
  13375.     Footer_Line : in POSITIVE;
  13376.     Footer_Text : in STRING
  13377.     );
  13378.  
  13379.  
  13380. procedure Set_Footer(        --| Replace a line of header text on a
  13381.                 --| paginated output file.
  13382.     File_Handle : in Paginated_File_Handle;
  13383.                 --| Paginated file to be set 
  13384.                 --| with the footer text
  13385.     Footer_Line : in POSITIVE;    --| Line number of footer to be replaced
  13386.     Footer_Text : in STRING    --| Footer line to replace
  13387.     );
  13388.  
  13389. --| Raises:
  13390. --| Invalid_File, Text_Overflow
  13391.  
  13392. --| Requires:
  13393. --| File_Handle is the access to the paginated file control structure
  13394. --| returned by Create_Paginated_File.  Footer_Text is the text
  13395. --| to replace the existing footer line at Footer_Line.
  13396.  
  13397. --| Effects:
  13398. --| The footer text of File_Handle at Footer_Line is set to Header_Text.
  13399. --| Note that the replaced footer text will not be printed until
  13400. --| the next page of the output.
  13401.  
  13402. --| Errors:
  13403. --| If File_Handle is not a valid access to a paginated file control
  13404. --| structure exception Invalid_File is raised.
  13405. --| Specification of Footer_Line greater than the number of footer
  13406. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13407. --| results in Text_Overflow exception to be raised.
  13408.  
  13409. --| N/A: Modifies
  13410.  
  13411.  
  13412. procedure Set_Footer(
  13413.     Footer_Line : in POSITIVE;
  13414.     Footer_Text : in SP.String_Type
  13415.     );
  13416.  
  13417. procedure Set_Footer(        --| Replace a line of footer text on a
  13418.                 --| paginated output file.
  13419.     File_Handle : in Paginated_File_Handle;
  13420.                 --| Paginated file to be set 
  13421.                 --| with the footer text
  13422.     Footer_Line : in POSITIVE;    --| Line number of footer to be replaced
  13423.     Footer_Text : in SP.String_Type
  13424.                 --| Footer line to replace
  13425.     );
  13426.  
  13427. --| Raises:
  13428. --| Invalid_File, Text_Overflow
  13429.  
  13430. --| Requires:
  13431. --| File_Handle is the access to the paginated file control structure
  13432. --| returned by Create_Paginated_File.  Footer_Text is the text
  13433. --| to replace the existing footer line at Footer_Line.
  13434.  
  13435. --| Effects:
  13436. --| The footer text of File_Handle at Footer_Line is set to Header_Text.
  13437. --| Note that the replaced footer text will not be printed until
  13438. --| the next page of the output.
  13439.  
  13440. --| Errors:
  13441. --| If File_Handle is not a valid access to a paginated file control
  13442. --| structure exception Invalid_File is raised.
  13443. --| Specification of Footer_Line greater than the number of footer
  13444. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13445. --| results in Text_Overflow exception to be raised.
  13446.  
  13447. --| N/A: Modifies
  13448.                                                     pragma Page;
  13449. procedure Set_Odd_Footer(
  13450.     Footer_Text : in Variable_String_Array
  13451.     );
  13452.  
  13453.  
  13454. procedure Set_Odd_Footer(    --| Set the footer text for the odd
  13455.                 --| pages of a paginated output file.
  13456.     File_Handle : in Paginated_File_Handle;
  13457.                 --| Paginated file to be set 
  13458.                 --| with the footer text
  13459.     Footer_Text : in Variable_String_Array
  13460.                 --| Sequence of lines for the footer
  13461.     );
  13462.  
  13463. --| Raises:
  13464. --| Invalid_File, Text_Overflow
  13465.  
  13466. --| Requires:
  13467. --| File_Handle is the access to the paginated file control structure
  13468. --| returned by Create_Paginated_File.  Footer_Text is the array
  13469. --| of text to be used for the odd page footer.
  13470.  
  13471. --| Effects:
  13472. --| The footer text for odd pages of File_Handle is set to Footer_Text.
  13473. --| Note that the replaced footer text will not be printed until
  13474. --| the next odd page of the output.
  13475.  
  13476. --| Errors:
  13477. --| If File_Handle is not a valid access to a paginated file control
  13478. --| structure exception Invalid_File is raised.
  13479. --| Specification of a footer text array which implies a greater
  13480. --| number of lines than reserved for by Create_Paginated_File or
  13481. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  13482.  
  13483. --| N/A: Modifies
  13484.  
  13485.  
  13486. procedure Set_Odd_Footer(
  13487.     Footer_Line : in POSITIVE;
  13488.     Footer_Text : in STRING
  13489.     );
  13490.  
  13491.  
  13492. procedure Set_Odd_Footer(    --| Replace a line of footer text on
  13493.                 --| the odd pages of a paginated
  13494.                 --| output file.
  13495.     File_Handle : in Paginated_File_Handle;
  13496.                 --| Paginated file to be set 
  13497.                 --| with the footer text
  13498.     Footer_Line : in POSITIVE;    --| Line number of footer to be replaced
  13499.     Footer_Text : in STRING    --| Footer line to replace
  13500.     );
  13501.  
  13502. --| Raises:
  13503. --| Invalid_File, Text_Overflow
  13504.  
  13505. --| Requires:
  13506. --| File_Handle is the access to the paginated file control structure
  13507. --| returned by Create_Paginated_File.  Footer_Text is the text
  13508. --| to replace the existing odd page footer line at Footer_Line.
  13509.  
  13510. --| Effects:
  13511. --| The odd page footer text of File_Handle at Footer_Line is set
  13512. --| to Footer_Text.  Note that the replaced footer text will not be
  13513. --| printed until the next odd page of the output.
  13514.  
  13515. --| Errors:
  13516. --| If File_Handle is not a valid access to a paginated file control
  13517. --| structure exception Invalid_File is raised.
  13518. --| Specification of Footer_Line greater than the number of footer
  13519. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13520. --| results in Text_Overflow exception to be raised.
  13521.  
  13522. --| N/A: Modifies
  13523.  
  13524.  
  13525. procedure Set_Odd_Footer(
  13526.     Footer_Line : in POSITIVE;
  13527.     Footer_Text : in SP.String_Type
  13528.     );
  13529.  
  13530.  
  13531. procedure Set_Odd_Footer(    --| Replace a line of footer text on
  13532.                 --| the odd pages of a paginated
  13533.                 --| output file.
  13534.     File_Handle : in Paginated_File_Handle;
  13535.                 --| Paginated file to be set 
  13536.                 --| with the footer text
  13537.     Footer_Line : in POSITIVE;    --| Line number of footer to be replaced
  13538.     Footer_Text : in SP.String_Type
  13539.                 --| Footer line to replace
  13540.     );
  13541.  
  13542. --| Raises:
  13543. --| Invalid_File, Text_Overflow
  13544.  
  13545. --| Requires:
  13546. --| File_Handle is the access to the paginated file control structure
  13547. --| returned by Create_Paginated_File.  Footer_Text is the text
  13548. --| to replace the existing odd page footer line at Footer_Line.
  13549.  
  13550. --| Effects:
  13551. --| The odd page footer text of File_Handle at Footer_Line is set
  13552. --| to Footer_Text.  Note that the replaced footer text will not be
  13553. --| printed until the next odd page of the output.
  13554.  
  13555. --| Errors:
  13556. --| If File_Handle is not a valid access to a paginated file control
  13557. --| structure exception Invalid_File is raised.
  13558. --| Specification of Footer_Line greater than the number of footer
  13559. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13560. --| results in Text_Overflow exception to be raised.
  13561.  
  13562. --| N/A: Modifies
  13563.                                                     pragma Page;
  13564. procedure Set_Even_Footer(
  13565.     Footer_Text : in Variable_String_Array
  13566.     );
  13567.  
  13568.  
  13569. procedure Set_Even_Footer(    --| Set the footer text for the even
  13570.                 --| pages of a paginated output file.
  13571.     File_Handle : in Paginated_File_Handle;
  13572.                 --| Paginated file to be set 
  13573.                 --| with the footer text
  13574.     Footer_Text : in Variable_String_Array
  13575.                 --| Sequence of lines for the footer
  13576.     );
  13577.  
  13578. --| Raises:
  13579. --| Invalid_File, Text_Overflow
  13580.  
  13581. --| Requires:
  13582. --| File_Handle is the access to the paginated file control structure
  13583. --| returned by Create_Paginated_File.  Footer_Text is the array
  13584. --| of text to be used for the even page footer.
  13585.  
  13586. --| Effects:
  13587. --| The footer text for even pages of File_Handle is set to Footer_Text.
  13588. --| Note that the replaced footer text will not be printed until
  13589. --| the next even page of the output.
  13590.  
  13591. --| Errors:
  13592. --| If File_Handle is not a valid access to a paginated file control
  13593. --| structure exception Invalid_File is raised.
  13594. --| Specification of a footer text array which implies a greater
  13595. --| number of lines than reserved for by Create_Paginated_File or
  13596. --| Set_Page_Layout results in Text_Overflow exception to be raised.
  13597.  
  13598. --| N/A: Modifies
  13599.  
  13600.  
  13601. procedure Set_Even_Footer(
  13602.     Footer_Line : in POSITIVE;
  13603.     Footer_Text : in STRING
  13604.     );
  13605.  
  13606.  
  13607. procedure Set_Even_Footer(    --| Replace a line of footer text on
  13608.                 --| the even pages of a paginated
  13609.                 --| output file.
  13610.     File_Handle : in Paginated_File_Handle;
  13611.                 --| Paginated file to be set 
  13612.                 --| with the footer text
  13613.     Footer_Line : in POSITIVE;    --| Line number of footer to be replaced
  13614.     Footer_Text : in STRING    --| Footer line to replace
  13615.     );
  13616.  
  13617. --| Raises:
  13618. --| Invalid_File, Text_Overflow
  13619.  
  13620. --| Requires:
  13621. --| File_Handle is the access to the paginated file control structure
  13622. --| returned by Create_Paginated_File.  Footer_Text is the text
  13623. --| to replace the existing even page footer line at Footer_Line.
  13624.  
  13625. --| Effects:
  13626. --| The even page footer text of File_Handle at Footer_Line is set
  13627. --| to Footer_Text.  Note that the replaced footer text will not be
  13628. --| printed until the next even page of the output.
  13629.  
  13630. --| Errors:
  13631. --| If File_Handle is not a valid access to a paginated file control
  13632. --| structure exception Invalid_File is raised.
  13633. --| Specification of Footer_Line greater than the number of footer
  13634. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13635. --| results in Text_Overflow exception to be raised.
  13636.  
  13637. --| N/A: Modifies
  13638.  
  13639.  
  13640. procedure Set_Even_Footer(
  13641.     Footer_Line : in POSITIVE;
  13642.     Footer_Text : in SP.String_Type
  13643.     );
  13644.  
  13645.  
  13646. procedure Set_Even_Footer(    --| Replace a line of footer text on
  13647.                 --| the even pages of a paginated
  13648.                 --| output file.
  13649.     File_Handle : in Paginated_File_Handle;
  13650.                 --| Paginated file to be set 
  13651.                 --| with the footer text
  13652.     Footer_Line : in POSITIVE;    --| Line number of footer to be replaced
  13653.     Footer_Text : in SP.String_Type
  13654.                 --| Footer line to replace
  13655.     );
  13656.  
  13657. --| Raises:
  13658. --| Invalid_File, Text_Overflow
  13659.  
  13660. --| Requires:
  13661. --| File_Handle is the access to the paginated file control structure
  13662. --| returned by Create_Paginated_File.  Footer_Text is the text
  13663. --| to replace the existing even page footer line at Footer_Line.
  13664.  
  13665. --| Effects:
  13666. --| The even page footer text of File_Handle at Footer_Line is set
  13667. --| to Footer_Text.  Note that the replaced footer text will not be
  13668. --| printed until the next even page of the output.
  13669.  
  13670. --| Errors:
  13671. --| If File_Handle is not a valid access to a paginated file control
  13672. --| structure exception Invalid_File is raised.
  13673. --| Specification of Footer_Line greater than the number of footer
  13674. --| lines reserved by Create_Paginated_File or Set_Page_Layout
  13675. --| results in Text_Overflow exception to be raised.
  13676.  
  13677. --| N/A: Modifies
  13678.                                                     pragma Page;
  13679. procedure Clear_Header;    
  13680.  
  13681.  
  13682. procedure Clear_Header(        --| Set the header text on a paginated
  13683.                 --| output file to null lines
  13684.     File_Handle : in Paginated_File_Handle
  13685.                 --| Paginated file to be set 
  13686.                 --| with the header text
  13687.     );
  13688.  
  13689. --| Raises:
  13690. --| Invalid_File
  13691.  
  13692. --| Requires:
  13693. --| File_Handle is the access to the paginated file control structure
  13694. --| returned by Create_Paginated_File.
  13695.  
  13696. --| Effects:
  13697. --| The header text of File_Handle is cleared to null lines.
  13698. --| The replaced null header will not be printed until the next
  13699. --| page of the output.
  13700.  
  13701. --| Errors:
  13702. --| If File_Handle is not a valid access to a paginated file control
  13703. --| structure exception Invalid_File is raised.
  13704.  
  13705. --| N/A: Modifies
  13706.                                                     pragma Page;
  13707. procedure Clear_Odd_Header;
  13708.  
  13709.  
  13710. procedure Clear_Odd_Header(    --| Set the header text for the odd
  13711.                 --| pages to null lines
  13712.     File_Handle : in Paginated_File_Handle
  13713.                 --| Paginated file to be set 
  13714.                 --| with the header text
  13715.     );
  13716.  
  13717. --| Raises:
  13718. --| Invalid_File, Text_Overflow
  13719.  
  13720. --| Requires:
  13721. --| File_Handle is the access to the paginated file control structure
  13722. --| returned by Create_Paginated_File.
  13723.  
  13724. --| Effects:
  13725. --| The header text for odd pages of File_Handle is cleared to null.
  13726. --| Note that the replaced null header text will not be printed until
  13727. --| the next odd page of the output.
  13728.  
  13729. --| Errors:
  13730. --| If File_Handle is not a valid access to a paginated file control
  13731. --| structure exception Invalid_File is raised.
  13732.  
  13733. --| N/A: Modifies
  13734.                                                     pragma Page;
  13735. procedure Clear_Even_Header;
  13736.  
  13737.  
  13738. procedure Clear_Even_Header(    --| Set the header text for the even
  13739.                 --| pages to null lines
  13740.     File_Handle : in Paginated_File_Handle
  13741.                 --| Paginated file to be set 
  13742.                 --| with the header text
  13743.     );
  13744.  
  13745. --| Raises:
  13746. --| Invalid_File, Text_Overflow
  13747.  
  13748. --| Requires:
  13749. --| File_Handle is the access to the paginated file control structure
  13750. --| returned by Create_Paginated_File.
  13751.  
  13752. --| Effects:
  13753. --| The header text for even pages of File_Handle is cleared to null.
  13754. --| Note that the replaced null header text will not be printed until
  13755. --| the next even page of the output.
  13756.  
  13757. --| Errors:
  13758. --| If File_Handle is not a valid access to a paginated file control
  13759. --| structure exception Invalid_File is raised.
  13760.  
  13761. --| N/A: Modifies
  13762.                                                     pragma Page;
  13763. procedure Clear_Footer;
  13764.  
  13765.  
  13766. procedure Clear_Footer(        --| Set the footer text on a paginated
  13767.                 --| output file to null lines
  13768.     File_Handle : in Paginated_File_Handle
  13769.                 --| Paginated file to be set 
  13770.                 --| with the footer text
  13771.     );
  13772.  
  13773. --| Raises:
  13774. --| Invalid_File
  13775.  
  13776. --| Requires:
  13777. --| File_Handle is the access to the paginated file control structure
  13778. --| returned by Create_Paginated_File.
  13779.  
  13780. --| Effects:
  13781. --| The footer text of File_Handle is cleared to null lines.
  13782. --| The replaced null footer will not be printed until the next
  13783. --| page of the output.
  13784.  
  13785. --| Errors:
  13786. --| If File_Handle is not a valid access to a paginated file control
  13787. --| structure exception Invalid_File is raised.
  13788.  
  13789. --| N/A: Modifies
  13790.                                                     pragma Page;
  13791. procedure Clear_Odd_Footer;
  13792.  
  13793.  
  13794. procedure Clear_Odd_Footer(    --| Set the footer text for the odd
  13795.                 --| pages to null lines
  13796.     File_Handle : in Paginated_File_Handle
  13797.                 --| Paginated file to be set 
  13798.                 --| with the footer text
  13799.     );
  13800.  
  13801. --| Raises:
  13802. --| Invalid_File, Text_Overflow
  13803.  
  13804. --| Requires:
  13805. --| File_Handle is the access to the paginated file control structure
  13806. --| returned by Create_Paginated_File.
  13807.  
  13808. --| Effects:
  13809. --| The footer text for odd pages of File_Handle is cleared to null.
  13810. --| Note that the replaced null footer text will not be printed until
  13811. --| the next odd page of the output.
  13812.  
  13813. --| Errors:
  13814. --| If File_Handle is not a valid access to a paginated file control
  13815. --| structure exception Invalid_File is raised.
  13816.  
  13817. --| N/A: Modifies
  13818.                                                     pragma Page;
  13819. procedure Clear_Even_Footer;
  13820.  
  13821.  
  13822. procedure Clear_Even_Footer(    --| Set the footer text for the even
  13823.                 --| pages to null lines
  13824.     File_Handle : in Paginated_File_Handle
  13825.                 --| Paginated file to be set 
  13826.                 --| with the footer text
  13827.     );
  13828.  
  13829. --| Raises:
  13830. --| Invalid_File, Text_Overflow
  13831.  
  13832. --| Requires:
  13833. --| File_Handle is the access to the paginated file control structure
  13834. --| returned by Create_Paginated_File.
  13835.  
  13836. --| Effects:
  13837. --| The footer text for even pages of File_Handle is cleared to null.
  13838. --| Note that the replaced null footer text will not be printed until
  13839. --| the next even page of the output.
  13840.  
  13841. --| Errors:
  13842. --| If File_Handle is not a valid access to a paginated file control
  13843. --| structure exception Invalid_File is raised.
  13844.  
  13845. --| N/A: Modifies
  13846.                                                     pragma Page;
  13847. procedure Close_Paginated_File;
  13848.  
  13849.  
  13850. procedure Close_Paginated_File(    --| Complete the last page and close
  13851.                 --| the paginated file.
  13852.     File_Handle : in out Paginated_File_Handle
  13853.                 --| The paginated file to be closed
  13854.     );
  13855.  
  13856. --| Raises:
  13857. --| Invalid_File, File_Not_Open
  13858.  
  13859. --| Requires:
  13860. --| File_Handle is the access to the paginated file control structure
  13861. --| returned by Create_Paginated_File.
  13862.  
  13863. --| Effects:
  13864. --| Completes the last page of output and closes the output file.
  13865.  
  13866. --| Errors:
  13867. --| If File_Handle is not a valid Paginated_File_Handle, the exception
  13868. --| Invalid_File is raised.  If an error occurs in closing the file,
  13869. --| File_Not_Open is raised.
  13870.  
  13871. --| N/A: Modifies
  13872.                                                     pragma Page;
  13873. procedure Put(
  13874.     Text        : in Variable_String_Array
  13875.     );
  13876.  
  13877.  
  13878. procedure Put(            --| Output a line on a paginated file
  13879.     File_Handle : in Paginated_File_Handle;
  13880.                 --| The paginated file to
  13881.                 --| output the text
  13882.     Text        : in Variable_String_Array
  13883.                 --| The text to be output.
  13884.     );
  13885.  
  13886. --| Raises:
  13887. --| Invalid_File, Output_Error
  13888.  
  13889. --| Requires:
  13890. --| File_Handle is the access to the paginated file control structure
  13891. --| returned by Create_Paginated_File.  Text is a string of 
  13892. --| characters to be written to the paginated output file.
  13893.  
  13894. --| Effects:
  13895. --| Outputs Text of text to File_Handle.  If Text is the first string of the
  13896. --| first line to be printed on a page, the page header is printed before
  13897. --| printing the text.  
  13898.  
  13899. --| Errors:
  13900. --| If File_Handle is not a valid, open Paginated_File_Handle,
  13901. --| the exception Invalid_File is raised.  If an error
  13902. --| occurs during output, Output_Error is raised.
  13903.  
  13904. --| N/A: Modifies
  13905.  
  13906.  
  13907. procedure Put(
  13908.     Text        : in SP.String_Type
  13909.     );
  13910.  
  13911.  
  13912. procedure Put(            --| Output a line on a paginated file
  13913.     File_Handle : in Paginated_File_Handle;
  13914.                 --| The paginated file to
  13915.                 --| output the text
  13916.     Text        : in SP.String_Type
  13917.                 --| The text to be output.
  13918.     );
  13919.  
  13920. --| Raises:
  13921. --| Invalid_File, Output_Error
  13922.  
  13923. --| Requires:
  13924. --| File_Handle is the access to the paginated file control structure
  13925. --| returned by Create_Paginated_File.  Text is a string of 
  13926. --| characters to be written to the paginated output file.
  13927.  
  13928. --| Effects:
  13929. --| Outputs Text of text to File_Handle.  If Text is the first string of the
  13930. --| first line to be printed on a page, the page header is printed before
  13931. --| printing the text.
  13932.  
  13933. --| Errors:
  13934. --| If File_Handle is not a valid, open Paginated_File_Handle,
  13935. --| the exception Invalid_File is raised.  If an error
  13936. --| occurs during output, Output_Error is raised.
  13937.  
  13938. --| N/A: Modifies
  13939.  
  13940.  
  13941. procedure Put(
  13942.     Text        : in STRING
  13943.     );
  13944.  
  13945.  
  13946. procedure Put(            --| Output a line on a paginated file
  13947.     File_Handle : in Paginated_File_Handle;
  13948.                 --| The paginated file to
  13949.                 --| output the text
  13950.     Text        : in STRING    --| The text to be output.
  13951.     );
  13952.  
  13953. --| Raises:
  13954. --| Invalid_File, Output_Error
  13955.  
  13956. --| Requires:
  13957. --| File_Handle is the access to the paginated file control structure
  13958. --| returned by Create_Paginated_File.  Text is a string of 
  13959. --| characters to be written to the paginated output file.
  13960.  
  13961. --| Effects:
  13962. --| Outputs Text of text to File_Handle.  If Text is the first string of the
  13963. --| first line to be printed on a page, the page header is printed before
  13964. --| printing the string.  
  13965.  
  13966. --| Errors:
  13967. --| If File_Handle is not a valid, open Paginated_File_Handle,
  13968. --| the exception Invalid_File is raised.  If an error
  13969. --| occurs during output, Output_Error is raised.
  13970.  
  13971. --| N/A: Modifies
  13972.  
  13973.  
  13974. procedure Put(
  13975.     Text        : in CHARACTER
  13976.     );
  13977.  
  13978.  
  13979. procedure Put(            --| Output a line on a paginated file
  13980.     File_Handle : in Paginated_File_Handle;
  13981.                 --| The paginated file to
  13982.                 --| output the text
  13983.     Text        : in CHARACTER    --| The text to be output.
  13984.     );
  13985.  
  13986. --| Raises:
  13987. --| Invalid_File, Output_Error
  13988.  
  13989. --| Requires:
  13990. --| File_Handle is the access to the paginated file control structure
  13991. --| returned by Create_Paginated_File.  Text is a the characters to be
  13992. --| written to the paginated output file.
  13993.  
  13994. --| Effects:
  13995. --| Outputs Text of text to File_Handle.  If Text is the first character of the
  13996. --| first line to be printed on a page, the page header is printed before
  13997. --| printing the string.  
  13998.  
  13999. --| Errors:
  14000. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14001. --| the exception Invalid_File is raised.  If an error
  14002. --| occurs during output, Output_Error is raised.
  14003.  
  14004. --| N/A: Modifies
  14005.                                                     pragma Page;
  14006. procedure Space(
  14007.     Count       : in NATURAL
  14008.     );
  14009.  
  14010.  
  14011. procedure Space(        --| Output a specified number of spaces
  14012.     File_Handle : in Paginated_File_Handle;
  14013.                 --| The paginated file to output the line
  14014.     Count       : in NATURAL    --| Number of spaces
  14015.     );
  14016.  
  14017. --| Raises:
  14018. --| Invalid_File, Output_Error
  14019.  
  14020. --| Requires:
  14021. --| File_Handle is the access to the paginated file control structure
  14022. --| returned by Create_Paginated_File.  Count is the number of horizontal
  14023. --| spaces to be output.
  14024.  
  14025. --| Effects:
  14026. --| Output Count number of blanks to File_Handle.
  14027.  
  14028. --| Errors:
  14029. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14030. --| the exception Invalid_File is raised.  If an error
  14031. --| occurs during output, Output_Error is raised.
  14032.  
  14033. --| N/A: Modifies
  14034.                                                     pragma Page;
  14035. procedure Put_Line(
  14036.     Text_Line   : in Variable_String_Array
  14037.     );
  14038.  
  14039.  
  14040. procedure Put_Line(        --| Output a line on a paginated file
  14041.     File_Handle : in Paginated_File_Handle;
  14042.                 --| The paginated file to output the line
  14043.     Text_Line   : in Variable_String_Array
  14044.                 --| The line to be output.
  14045.     );
  14046.  
  14047. --| Raises:
  14048. --| Invalid_File, Output_Error
  14049.  
  14050. --| Requires:
  14051. --| File_Handle is the access to the paginated file control structure
  14052. --| returned by Create_Paginated_File.  Text_Line is a string of 
  14053. --| characters to be written to the paginated output file.
  14054.  
  14055. --| Effects:
  14056. --| Outputs Text_Line of text to File_Handle.  If Text_Line is the
  14057. --| first line to be printed on a page, the page header is printed
  14058. --| before the line.  If it is the last line on a page, the page
  14059. --| footer followed by a page terminator is written immediately
  14060. --| after the line is written.
  14061.  
  14062. --| Errors:
  14063. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14064. --| the exception Invalid_File is raised.  If an error
  14065. --| occurs during output, Output_Error is raised.
  14066.  
  14067. --| N/A: Modifies
  14068.  
  14069.  
  14070. procedure Put_Line(
  14071.     Text_Line   : in SP.String_Type
  14072.     );
  14073.  
  14074.  
  14075. procedure Put_Line(        --| Output a line on a paginated file
  14076.     File_Handle : in Paginated_File_Handle;
  14077.                 --| The paginated file to
  14078.                 --| output the line
  14079.     Text_Line   : in SP.String_Type
  14080.                 --| The line to be output.
  14081.     );
  14082.  
  14083. --| Raises:
  14084. --| Invalid_File, Output_Error
  14085.  
  14086. --| Requires:
  14087. --| File_Handle is the access to the paginated file control structure
  14088. --| returned by Create_Paginated_File.  Text_Line is a string of 
  14089. --| characters to be written to the paginated output file.
  14090.  
  14091. --| Effects:
  14092. --| Outputs Text_Line of text to File_Handle.  If Text_Line is the
  14093. --| first line to be printed on a page, the page header is printed
  14094. --| before the line.  If it is the last line on a page, the page
  14095. --| footer followed by a page terminator is written immediately
  14096. --| after the line is written.
  14097.  
  14098. --| Errors:
  14099. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14100. --| the exception Invalid_File is raised.  If an error
  14101. --| occurs during output, Output_Error is raised.
  14102.  
  14103. --| N/A: Modifies
  14104.  
  14105.  
  14106. procedure Put_Line(
  14107.     Text_Line   : in STRING
  14108.     );
  14109.  
  14110.  
  14111. procedure Put_Line(        --| Output a line on a paginated file
  14112.     File_Handle : in Paginated_File_Handle;
  14113.                 --| The paginated file to
  14114.                 --| output the line
  14115.     Text_Line   : in STRING    --| The line to be output.
  14116.     );
  14117.  
  14118. --| Raises:
  14119. --| Invalid_File, Output_Error
  14120.  
  14121. --| Requires:
  14122. --| File_Handle is the access to the paginated file control structure
  14123. --| returned by Create_Paginated_File.  Text_Line is a string of 
  14124. --| characters to be written to the paginated output file.
  14125.  
  14126. --| Effects:
  14127. --| Outputs Text_Line of text to File_Handle.  If Text_Line is the
  14128. --| first line to be printed on a page, the page header is printed
  14129. --| before the line.  If it is the last line on a page, the page
  14130. --| footer followed by a page terminator is written immediately
  14131. --| after the line is written.
  14132.  
  14133. --| Errors:
  14134. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14135. --| the exception Invalid_File is raised.  If an error
  14136. --| occurs during output, Output_Error is raised.
  14137.  
  14138. --| N/A: Modifies
  14139.                                                     pragma Page;
  14140. procedure Space_Line(
  14141.     Count       : in NATURAL := 1
  14142.     );
  14143.  
  14144.  
  14145. procedure Space_Line(        --| Output one or more spaces on a
  14146.                 --| paginated file
  14147.     File_Handle : in Paginated_File_Handle;
  14148.                 --| The paginated file to 
  14149.                 --| output spaces
  14150.     Count       : in NATURAL := 1
  14151.                 --| The number of spaces.
  14152.     );
  14153.  
  14154. --| Raises:
  14155. --| Invalid_File, Output_Error, Invalid_Count
  14156.  
  14157. --| Requires:
  14158. --| File_Handle is the access to the paginated file control structure
  14159. --| returned by Create_Paginated_File.  Count is the number of
  14160. --| spaces to be output to File_Handle.  If Count is omitted, 1 is
  14161. --| assumed.
  14162.  
  14163. --| Effects:
  14164. --| Count number of line terminators are output to File_Handle.
  14165. --| If Count is greater than the number of lines remaining on
  14166. --| the page, the page footer, a page terminator, and the page header
  14167. --| are written before the remainder of the spaces are output.
  14168. --| If the specified Count is less than equal to 0, no operation
  14169. --| takes place.
  14170.  
  14171. --| Errors:
  14172. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14173. --| the exception Invalid_File is raised.  If the requested space
  14174. --| count is greater than a predetermined amount, Invalid_Count
  14175. --| is raised.  If an error occurs during output, Output_Error
  14176. --| is raised.
  14177.  
  14178. --| N/A: Modifies
  14179.                                                     pragma Page;
  14180. procedure Skip_Line(
  14181.     Count       : in NATURAL := 1
  14182.     );
  14183.  
  14184.  
  14185. procedure Skip_Line(        --| Output one or more spaces on a
  14186.                 --| paginated file
  14187.     File_Handle : in Paginated_File_Handle;
  14188.                 --| The paginated file to
  14189.                 --| output skips
  14190.     Count       : in NATURAL := 1
  14191.                 --| The number of spaces.
  14192.     );
  14193.  
  14194. --| Raises:
  14195. --| Invalid_File, Output_Error, Invalid_Count
  14196.  
  14197. --| Requires:
  14198. --| File_Handle is the access to the paginated file control structure
  14199. --| returned by Create_Paginated_File.  Count is the number of
  14200. --| spaces to be output to File_Handle.  If Count is omitted, 1 is
  14201. --| assumed.
  14202.  
  14203. --| Effects:
  14204. --| Count number of line terminators are output to File_Handle.
  14205. --| If Count is greater than the number of lines remaining on
  14206. --| the page, the page footer is printed, a page terminator is
  14207. --| output and the remainder of the skips are NOT output.
  14208. --| If the specified Count is less than equal to 0, no operation
  14209. --| takes place.
  14210.  
  14211. --| Errors:
  14212. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14213. --| the exception Invalid_File is raised.  If the requested skip
  14214. --| count is greater than a predetermined amount, Invalid_Count
  14215. --| is raised.  If an error occurs during output, Output_Error
  14216. --| is raised.
  14217.  
  14218. --| N/A: Modifies
  14219.                                                     pragma Page;
  14220. procedure Put_Page(
  14221.     Count       : in NATURAL := 1
  14222.     );
  14223.  
  14224.  
  14225. procedure Put_Page(        --| Output one or more page ejects
  14226.                 --| on a paginated file
  14227.     File_Handle : in Paginated_File_Handle;
  14228.                 --| The paginated file to
  14229.                 --| output page ejects
  14230.     Count       : in NATURAL := 1
  14231.                 --| The number of pages.
  14232.     );
  14233.  
  14234. --| Raises:
  14235. --| Invalid_File, Output_Error, Invalid_Count
  14236.  
  14237. --| Requires:
  14238. --| File_Handle is the access to the paginated file control structure
  14239. --| returned by Create_Paginated_File.  Count is the number of
  14240. --| pages to be output to File_Handle.  If Count is omitted, 1 is
  14241. --| assumed.
  14242.  
  14243. --| Effects:
  14244. --| Outputs Count number of page ejects. The page footer and the page
  14245. --| header are printed as appropriate.
  14246. --| If the specified Count is less than equal to 0, no operation
  14247. --| takes place.
  14248.  
  14249. --| Errors:
  14250. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14251. --| the exception Invalid_File is raised.  If the requested page
  14252. --| count is greater than a predetermined amount, Invalid_Count
  14253. --| is raised.  If an error occurs during output, Output_Error
  14254. --| is raised.
  14255.  
  14256. --| N/A: Modifies
  14257.                                                     pragma Page;
  14258. function Available_Lines
  14259.     return NATURAL;
  14260.  
  14261. function Available_Lines(    --| Query the number of lines that
  14262.                 --| are available on the current page
  14263.     File_Handle : in Paginated_File_Handle
  14264.                 --| The paginated file to be
  14265.                 --| queried for available lines
  14266.     ) return NATURAL;
  14267.  
  14268. --| Raises:
  14269. --| Invalid_File
  14270.  
  14271. --| Requires:
  14272. --| File_Handle is the access to the paginated file control structure
  14273. --| returned by Create_Paginated_File.
  14274.  
  14275. --| Effects:
  14276. --| Return the number of lines (excluding the header and the footer
  14277. --| spaces) remaining on the current output page.
  14278.  
  14279. --| Errors:
  14280. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14281. --| the exception Invalid_File is raised.
  14282.  
  14283. --| N/A: Modifies
  14284.                                                     pragma Page;
  14285. procedure Reserve_Lines(
  14286.     Count       : in NATURAL
  14287.     );
  14288.  
  14289.  
  14290. procedure Reserve_Lines(    --| Assure that there are at least
  14291.                 --| a specified number of contiguous
  14292.                 --| lines on a paginated file.
  14293.     File_Handle : in Paginated_File_Handle;
  14294.                 --| The paginated file to
  14295.                 --| reserve the lines
  14296.     Count       : in NATURAL    --| The number of lines needed
  14297.     );
  14298.  
  14299. --| Raises :
  14300. --| Invalid_File, Page_Overflow
  14301.  
  14302. --| Requires:
  14303. --| File_Handle is the access to the paginated file control structure
  14304. --| returned by Create_Paginated_File.  Count is the number of
  14305. --| contiguous lines needed on File_Handle.
  14306.  
  14307. --| Effects:
  14308. --| If Count is greater than the number of lines remaining on
  14309. --| the page, Put_Page is executed to assure that there are Count
  14310. --| number of contiguous lines.
  14311. --| Specifying value less than or equal to 0 for Count will result
  14312. --| in no operation
  14313.  
  14314. --| Errors:
  14315. --| If File_Handle is not a valid, open Paginated_File_Handle,
  14316. --| the exception Invalid_File is raised.  If Count is greater than
  14317. --| the maximum number of lines available on a page as set by
  14318. --| Set_Page_Layout, exception Page_Overflow is raised and Put_Page
  14319. --| is NOT executed.
  14320.                                                     pragma Page;
  14321. private
  14322.                                                     pragma List(off);
  14323.     type Variable_String_Array_Handle is
  14324.     access Variable_String_Array;
  14325.                 --| Handle to array of variable length
  14326.                 --| strings
  14327.  
  14328.     type Paginated_File_Structure;
  14329.                 --| Data structure to store state of
  14330.                 --| the output file.
  14331.  
  14332.     type Paginated_File_Handle is
  14333.     access Paginated_File_Structure;
  14334.                 --| Handle to be passed around in a
  14335.                 --| program that uses paginated_output.
  14336.  
  14337.     type Paginated_File_Structure is
  14338.                 --| a structure to store state of
  14339.     record            --| the output file.
  14340.         access_count     : NATURAL;
  14341.                 --| Number of accesses to this structure
  14342.         forward_link     : Paginated_File_Handle := null;
  14343.                 --| Access to next file structure
  14344.         reverse_link     : Paginated_File_Handle := null;
  14345.                 --| Access to previous file structure
  14346.         file_spec        : SP.String_Type;
  14347.                 --| External file name
  14348.         file_name        : SP.String_Type;
  14349.                 --| External file name for ~f substitute
  14350.         file_reference   : TIO.File_Type;
  14351.                 --| External file reference
  14352.         output_mode      : Paginated_Output_Mode := STD;
  14353.                 --| Output mode (STD or CUR)
  14354.         page_size        : NATURAL;
  14355.                 --| The number of lines per page
  14356.         maximum_line     : NATURAL;
  14357.                 --| The maximum number of text lines
  14358.         current_calendar : SP.String_Type;
  14359.                 --| Creation date (eg. March 15, 1985)
  14360.         current_date     : STRING (1 .. 8);
  14361.                 --| Creation date (eg. 03/15/85)
  14362.         current_time     : STRING (1 .. 8);
  14363.                 --| Creation time (eg. 15:24:07)
  14364.         current_page     : NATURAL := 0;
  14365.                 --| The number of lines per page
  14366.         current_line     : NATURAL := 0;
  14367.                 --| The number of lines used
  14368.         header_size      : NATURAL;
  14369.                 --| Number of lines of header text
  14370.         odd_page_header  : Variable_String_Array_Handle := null;
  14371.                 --| Access to odd page header text
  14372.         even_page_header : Variable_String_Array_Handle := null;
  14373.                 --| Access to even page header text
  14374.         footer_size      : NATURAL;
  14375.                 --| Number of lines of footer text
  14376.         odd_page_footer  : Variable_String_Array_Handle := null;
  14377.                 --| Access to odd page footer text
  14378.         even_page_footer : Variable_String_Array_Handle := null;
  14379.                 --| Access to even page footer text
  14380.     end record;
  14381.                                                     pragma List(on);
  14382. end  Paginated_Output;
  14383.                                                     pragma Page;
  14384. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14385. --PGFILE.BDY
  14386. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14387. with Calendar;
  14388. with Unchecked_Deallocation;
  14389. with String_Utilities;
  14390.  
  14391.  
  14392. package body Paginated_Output is
  14393.  
  14394.     package IIO is new TIO.Integer_IO(INTEGER);
  14395.     package CAL renames Calendar;
  14396.     package SU  renames String_Utilities;
  14397.     package SS  is new SU.Generic_String_Utilities(SP.String_Type,
  14398.                            SP.Make_Persistent,
  14399.                            SP.Value);
  14400.  
  14401.     type Odd_Even is (Odd, Even);        --| Odd/Even page indicator
  14402.  
  14403.     type Header_Footer is (Header,Footer);    --| Header/Footer selection
  14404.  
  14405.     type Kind_Of_Text is            --| Text selection switches
  14406.     record
  14407.         page: Odd_Even;
  14408.         text: Header_Footer;
  14409.     end record;
  14410.  
  14411.     type DCT is (DATE, CALENDAR_DATE, TIME);
  14412.  
  14413.     type Date_Calendar_Time is array (DCT) of BOOLEAN;
  14414.  
  14415.     Max_Filename_Size : constant POSITIVE := 60;
  14416.  
  14417.     Max_Calendar_Size : constant POSITIVE := 18;
  14418.  
  14419.     Max_Page_Size     : constant POSITIVE :=  3;
  14420.  
  14421.     Month_Name : constant Variable_String_Array(1 .. 12) :=
  14422.     ( 1 => SP.Create("January"),
  14423.       2 => SP.Create("February"), 
  14424.       3 => SP.Create("March"), 
  14425.       4 => SP.Create("April"), 
  14426.       5 => SP.Create("May"), 
  14427.       6 => SP.Create("June"), 
  14428.       7 => SP.Create("July"), 
  14429.       8 => SP.Create("August"), 
  14430.       9 => SP.Create("September"), 
  14431.      10 => SP.Create("October"), 
  14432.      11 => SP.Create("November"), 
  14433.      12 => SP.Create("December") );
  14434.  
  14435.     Paginated_Standard_Output : Paginated_File_Handle;
  14436.                                                                     pragma page;
  14437.     procedure Reset_Date_Calendar_Time(
  14438.     File_Handle : in Paginated_File_Handle;
  14439.     Reset       : in Date_Calendar_Time
  14440.     ) is
  14441.  
  14442. --|-Algorithm:
  14443. --| Get the current system date/time
  14444. --| Separate date/time into appropriate components
  14445. --| Calculate in terms of hours, minutes, and seconds
  14446. --| Set current date/time in the file structure
  14447. --| Set the current date in "English" (eg. January 1, 1985)
  14448. --|    in the file structure
  14449. --| Exit
  14450. --|+
  14451.  
  14452.     Clock_Value : CAL.Time;
  14453.     Year        : CAL.Year_Number;
  14454.     Month       : CAL.Month_Number;
  14455.     Day         : CAL.Day_Number;
  14456.     Duration    : CAL.Day_Duration;
  14457.  
  14458.     begin
  14459.  
  14460.     Clock_Value := CAL.Clock;
  14461.     CAL.Split(Clock_Value, Year, Month, Day, Duration);
  14462.  
  14463.     if Reset(Date) then
  14464.         File_Handle.current_date := SU.Image(INTEGER(Month), 2, '0') & "/"
  14465.                       & SU.Image(INTEGER(Day), 2, '0') & "/"
  14466.                       & SU.Image(INTEGER(Year mod 100), 2, '0');
  14467.     end if;
  14468.  
  14469.     if Reset(Time) then
  14470.         File_Handle.current_time := SU.Image(INTEGER(Duration) / (60 * 60), 2, '0') & ":"
  14471.                       & SU.Image((INTEGER(Duration) mod (60 * 60)) / 60, 2, '0') & ":"
  14472.                       & SU.Image(INTEGER(Duration) mod 60, 2, '0');
  14473.     end if;
  14474.  
  14475.     if Reset(Calendar_Date) then
  14476.         SP.Mark;
  14477.         if not SP.Equal(File_Handle.current_calendar, "") then
  14478.         SP.Flush(File_Handle.current_calendar);
  14479.         end if;
  14480.         File_Handle.current_calendar := SP.Make_Persistent( 
  14481.                         SP.Value(Month_Name(INTEGER(Month))) & 
  14482.                         INTEGER'image(Day) &
  14483.                         "," &
  14484.                         INTEGER'image(Year));
  14485.         SP.Release;
  14486.     end if;
  14487.  
  14488.     return;
  14489.  
  14490.     end Reset_Date_Calendar_Time;
  14491.                                                                     pragma page;
  14492.     procedure Check_Valid(
  14493.     File_Handle : in Paginated_File_Handle
  14494.     ) is
  14495.  
  14496. --|-Algorithm:
  14497. --| If handle is null or external file name is null
  14498. --|    then raise an error
  14499. --| Exit
  14500. --|+
  14501.  
  14502.     begin
  14503.  
  14504.     if File_Handle = null then
  14505.         raise Invalid_File;
  14506.     end if;
  14507.     return;
  14508.  
  14509.     end Check_Valid;
  14510.                                                                     pragma page;
  14511.     procedure Clear_Text(
  14512.     Text_Handle : in Variable_String_Array_Handle
  14513.     ) is
  14514.  
  14515. --|-Algorithm:
  14516. --| If valid access to text array
  14517. --|    then return text array storage to the heap (access set to null)
  14518. --| Exit
  14519. --|+
  14520.  
  14521.     begin
  14522.  
  14523.     if Text_Handle /= null then
  14524.         for i in Text_Handle'range loop
  14525.         SP.Flush(Text_Handle(i));
  14526.         end loop;
  14527.     end if;
  14528.     return;
  14529.  
  14530.     end Clear_Text;
  14531.  
  14532.  
  14533.     procedure Set_Text(
  14534.     File_Handle  : in Paginated_File_Handle;
  14535.     Text_String  : in Variable_String_Array;
  14536.     Text_Control : in Kind_Of_Text
  14537.     ) is
  14538.  
  14539. --|-Algorithm:
  14540. --| Validate paginated file structure (raise error if not valid)
  14541. --| If requested text array is too large
  14542. --|    then raise an error
  14543. --| Clear old text array
  14544. --| Set new text array with specified justification (top or bottom)
  14545. --| in the area as specified
  14546. --| Exit
  14547. --|+
  14548.  
  14549.     Text_Handle : Variable_String_Array_Handle;
  14550.     Text_Index  : INTEGER;
  14551.     Text_Size   : INTEGER;
  14552.     Handle      : Paginated_File_Handle;
  14553.  
  14554.     begin
  14555.     Check_Valid(File_Handle);
  14556.     Handle := File_Handle;
  14557.     loop
  14558.         exit when Handle = null;
  14559.         case Text_Control.text is
  14560.         when Header =>
  14561.             Text_Size := Handle.header_size;
  14562.             Text_Index := 1;
  14563.             case Text_Control.page is
  14564.             when Odd =>
  14565.                 Text_Handle := Handle.odd_page_header;
  14566.             when Even =>
  14567.                 Text_Handle := Handle.even_page_header;
  14568.             end case;
  14569.         when Footer =>
  14570.             Text_Size := Handle.footer_size;
  14571.             Text_Index := Text_Size - Text_String'last + 1;
  14572.             case Text_Control.page is
  14573.             when Odd =>
  14574.                 Text_Handle := Handle.odd_page_footer;
  14575.             when Even =>
  14576.                 Text_Handle := Handle.even_page_footer;
  14577.             end case;
  14578.         end case;
  14579.         if Text_Size < Text_String'last then
  14580.         raise Text_Overflow;
  14581.         end if;
  14582.         Clear_Text(Text_Handle);
  14583.         for i in Text_String'range loop
  14584.         Text_Handle(Text_Index) := SP.Make_Persistent(Text_String(i));
  14585.         Text_Index := Text_Index + 1;
  14586.         end loop;
  14587.         Handle := Handle.forward_link;
  14588.     end loop;
  14589.     return;
  14590.  
  14591.     end Set_Text;
  14592.                                                                     pragma page;
  14593.     procedure Substitute(
  14594.     In_String  : in     SP.String_Type;
  14595.     Index      : in out INTEGER;
  14596.     Sub_String : in     STRING;
  14597.     Out_String :    out SP.String_Type
  14598.     ) is
  14599.  
  14600.     Scanner : SU.Scanner;
  14601.     S_Str   : SP.String_Type;
  14602.     Found   : BOOLEAN;
  14603.     Num     : INTEGER;
  14604.     Letter  : CHARACTER;
  14605.     Inx     : INTEGER;
  14606.     
  14607.     begin
  14608.  
  14609.     Out_String := SP.Create(Sub_String);
  14610.     Scanner := SS.Make_Scanner(
  14611.             SP.Substr(In_String, Index, SP.Length(In_String) - Index + 1)
  14612.             );
  14613.     SS.Scan_Enclosed('(', ')', Scanner, Found, S_Str);
  14614.     SU.Destroy_Scanner(Scanner);
  14615.     if Found then
  14616.         Scanner := SS.Make_Scanner(S_Str);
  14617.         Inx := SP.Length(S_Str);
  14618.         SP.Flush(S_Str);
  14619.         if SU.More(Scanner) then
  14620.         SU.Next(Scanner, Letter);
  14621.         if SU.More(Scanner) then
  14622.             SU.Scan_Number(Scanner, Found, Num);
  14623.             if Found and then Num > 0 then
  14624.             if not SU.More(Scanner) then
  14625.                 if Letter = 'r' or Letter = 'R' or
  14626.                    Letter = 'l' or Letter = 'L' or
  14627.                    Letter = 'c' or Letter = 'C' then
  14628.                 case Letter is
  14629.                 when 'R' | 'r' =>
  14630.                     Out_String := SS.Right_Justify(Sub_String, Num);
  14631.                 when 'L' | 'l' =>
  14632.                     Out_String := SS.Left_Justify(Sub_String, Num);
  14633.                 when 'C' | 'c' =>
  14634.                     Out_String := SS.Center(Sub_String, Num);
  14635.                 when others    =>
  14636.                     null;
  14637.                 end case;
  14638.                 Index := Index + Inx + 2;
  14639.                 end if;
  14640.             end if;
  14641.             end if;
  14642.         end if;
  14643.         end if;
  14644.         SU.Destroy_Scanner(Scanner);
  14645.     end if;
  14646.  
  14647.     end Substitute;
  14648.                                                                     pragma page;
  14649.     function Tilde_Substitute(
  14650.     File_Handle : in Paginated_File_Handle;
  14651.     Input_Text : in SP.String_Type
  14652.     ) return STRING is
  14653.  
  14654. --|-Algorithm:
  14655. --| Set the length of the text in question
  14656. --| Clear the result string to null
  14657. --| Loop until all input characters are processed
  14658. --|    Fetch one character
  14659. --|    If the character is a tilde (~) 
  14660. --|       then bump input index and if past the end exit the loop
  14661. --|            Fetch the next character
  14662. --|            Based on this character substitute appropriately
  14663. --|        else add this to the output
  14664. --|     Bump input index and loop
  14665. --| Return the output (substituted) string
  14666. --| Exit
  14667. --|+
  14668.  
  14669.     Output_Text  : SP.String_Type;
  14670.     R_Str, S_Str : SP.String_Type;
  14671.     Letter       : CHARACTER;
  14672.     Index        : NATURAL;
  14673.  
  14674.     begin
  14675.  
  14676.     S_Str := Input_Text;
  14677.     loop
  14678.         Index := SP.Match_C(S_Str, '~');
  14679.         if Index = 0 then
  14680.         Output_Text := SP."&"(Output_Text, S_Str);
  14681.         exit;
  14682.         end if;
  14683.         if Index > 1 then
  14684.         Output_Text := SP."&"(Output_Text, SP.Substr(S_Str, 1, Index - 1));
  14685.         end if;
  14686.         if Index < SP.Length(S_Str) then
  14687.         Letter := SP.Fetch(S_Str, Index + 1);
  14688.         else
  14689.         exit;
  14690.         end if;
  14691.         Index := Index + 2;
  14692.         case Letter is
  14693.         when 'f' | 'F' =>
  14694.             Substitute(S_Str, Index, SP.Value(File_Handle.file_name), R_Str);
  14695.             Output_Text := SP."&"(Output_Text, R_Str);
  14696.         when 'c' | 'C' =>
  14697.             Substitute(S_Str, Index, SP.Value(File_Handle.current_calendar), R_Str);
  14698.             Output_Text := SP."&"(Output_Text, R_Str);
  14699.         when 'd' | 'D' =>
  14700.             Substitute(S_Str, Index, File_Handle.current_date, R_Str);
  14701.             Output_Text := SP."&"(Output_Text, R_Str);
  14702.         when 't' | 'T' =>
  14703.             Substitute(S_Str, Index, File_Handle.current_time, R_Str);
  14704.             Output_Text := SP."&"(Output_Text, R_Str);
  14705.         when 'p' | 'P' =>
  14706.             Substitute(S_Str, Index, STRING'(SU.Image(File_Handle.current_page, 0)), R_Str);
  14707.             Output_Text := SP."&"(Output_Text, R_Str);
  14708.         when others    =>
  14709.             Output_Text := SP."&"(Output_Text, ("" & Letter));
  14710.         end case;
  14711.         if Index > SP.Length(S_Str) then
  14712.         exit;
  14713.         end if;
  14714.         S_Str := SP.Substr(S_Str, Index, SP.Length(S_Str) - Index + 1);
  14715.     end loop;
  14716.         
  14717.     return SP.Value(Output_Text);
  14718.  
  14719.     end Tilde_Substitute;
  14720.                                                                     pragma page;
  14721.     procedure Put_Text(
  14722.     File_Handle  : in Paginated_File_Handle;
  14723.     Text_Control : in Kind_Of_Text
  14724.     ) is
  14725.  
  14726. --|-Algorithm:
  14727. --| If access to text array is null
  14728. --|    then write appropriate number of line terminators
  14729. --|         exit
  14730. --| Loop over the depth of the text array
  14731. --|    If text is null
  14732. --|       then write line terminator
  14733. --|       else resolve tilde substitution
  14734. --|            write a line of text followed by a line terminator
  14735. --| Exit
  14736. --|+
  14737.  
  14738.     Text_Handle : Variable_String_Array_Handle;
  14739.     Text_Size   : INTEGER;
  14740.  
  14741.     begin
  14742.     case Text_Control.text is
  14743.         when Header =>
  14744.         if File_Handle.header_size = 0 then
  14745.             return;
  14746.         end if;
  14747.         Text_Size := File_Handle.header_size;
  14748.         if File_Handle.current_page mod 2 = 0 then
  14749.             Text_Handle := File_Handle.even_page_header;
  14750.         else
  14751.             Text_Handle := File_Handle.odd_page_header;
  14752.         end if;
  14753.         when Footer =>
  14754.         if File_Handle.footer_size = 0 then
  14755.             return;
  14756.         end if;
  14757.         Text_Size := File_Handle.footer_size;
  14758.         if File_Handle.current_page mod 2 = 0 then
  14759.             Text_Handle := File_Handle.even_page_footer;
  14760.         else
  14761.             Text_Handle := File_Handle.odd_page_footer;
  14762.         end if;
  14763.     end case;
  14764.     if Text_Handle = null then
  14765.         if SP.Equal(File_Handle.file_spec, "") then
  14766.         if File_Handle.output_mode = STD then
  14767.             TIO.New_Line(TIO.Standard_Output,
  14768.                  TIO.POSITIVE_Count(Text_Size));
  14769.         else
  14770.             TIO.New_Line(TIO.Current_Output,
  14771.                  TIO.POSITIVE_Count(Text_Size));
  14772.         end if;
  14773.         else
  14774.         TIO.New_Line(File_Handle.file_reference,
  14775.                  TIO.POSITIVE_Count(Text_Size));
  14776.         end if;
  14777.         return;
  14778.     end if;
  14779.     for i in 1 .. Text_Size loop
  14780.         SP.Mark;
  14781.         if SP.Is_Empty(Text_Handle(i)) then
  14782.             if SP.Equal(File_Handle.file_spec, "") then
  14783.             if File_Handle.output_mode = STD then
  14784.             TIO.New_Line(TIO.Standard_Output, 1);
  14785.             else
  14786.             TIO.New_Line(TIO.Current_Output, 1);
  14787.             end if;
  14788.         else
  14789.             TIO.New_Line(File_Handle.file_reference, 1);
  14790.         end if;
  14791.         else
  14792.             if SP.Equal(File_Handle.file_spec, "") then
  14793.             if File_Handle.output_mode = STD then
  14794.             TIO.Put_Line(TIO.Standard_Output,
  14795.                      Tilde_Substitute(File_Handle, Text_Handle(i)));
  14796.             else
  14797.             TIO.Put_Line(TIO.Current_Output,
  14798.                      Tilde_Substitute(File_Handle, Text_Handle(i)));
  14799.             end if;
  14800.         else
  14801.             TIO.Put_Line(File_Handle.file_reference,
  14802.                  Tilde_Substitute(File_Handle, Text_Handle(i)));
  14803.         end if;
  14804.         end if;
  14805.         SP.Release;
  14806.     end loop;
  14807.     return;
  14808.  
  14809.     end Put_Text;
  14810.                                                                     pragma page;
  14811.     procedure Free_Structure is
  14812.     new Unchecked_Deallocation(Paginated_File_Structure, Paginated_File_Handle);
  14813.  
  14814.     procedure Abort_Paginated_Output(
  14815.     File_Handle : in out Paginated_File_Handle
  14816.     ) is
  14817.  
  14818. --|-Algorithm:
  14819. --| If given handle is null
  14820. --|    return
  14821. --| Return header/footer text array storage to the heap
  14822. --| Close file
  14823. --| Return file structure storage to the heap
  14824. --| Exit
  14825. --|+        
  14826.  
  14827.     begin
  14828.     if File_Handle = null then
  14829.         return;
  14830.     end if;
  14831.     Clear_Text(File_Handle.odd_page_header);
  14832.     Clear_Text(File_Handle.even_page_header);
  14833.     Clear_Text(File_Handle.odd_page_footer);
  14834.     Clear_Text(File_Handle.even_page_footer);
  14835.     SP.Flush(File_Handle.current_calendar);
  14836.     SP.Flush(File_Handle.file_name);
  14837.     if not SP.Equal(File_Handle.file_spec, "") then
  14838.         SP.Flush(File_Handle.file_spec);
  14839.         TIO.Close(File_Handle.file_reference);
  14840.     end if;
  14841.     Free_Structure(File_Handle);
  14842.     return;
  14843.  
  14844.     exception
  14845.  
  14846.     when TIO.Status_error =>
  14847.         Free_Structure(File_Handle);
  14848.  
  14849.     end Abort_Paginated_Output;
  14850.                                                                     pragma page;
  14851.     function Footer_Exist(
  14852.     File_Handle : in Paginated_File_Handle
  14853.     ) return BOOLEAN is
  14854.  
  14855.     Text_Handle : Variable_String_Array_Handle;
  14856.     Text_Size   : INTEGER;
  14857.  
  14858.     begin
  14859.  
  14860.     Text_Size := File_Handle.footer_size;
  14861.     if Text_Size <= 0 then
  14862.         return FALSE;
  14863.     end if;
  14864.     if File_Handle.current_page mod 2 = 0 then
  14865.         Text_Handle := File_Handle.even_page_footer;
  14866.     else
  14867.         Text_Handle := File_Handle.odd_page_footer;
  14868.     end if;
  14869.     if Text_Handle = null then
  14870.         return FALSE;
  14871.     end if;
  14872.     for i in 1 .. Text_Size loop
  14873.         SP.Mark;
  14874.         if not SP.Is_Empty(Text_Handle(i)) then
  14875.         return TRUE;
  14876.         end if;
  14877.         SP.Release;
  14878.     end loop;
  14879.     return FALSE;
  14880.  
  14881.     end Footer_Exist;
  14882.                                                                     pragma page;
  14883.     procedure Line_Feed(
  14884.     File_Handle : in Paginated_File_Handle;
  14885.     Count       : in INTEGER
  14886.     ) is
  14887.  
  14888. --|-Algorithm:
  14889. --| If at top of the page
  14890. --|    then write header 
  14891. --| If the request count is 0
  14892. --|    then return
  14893. --| If the request is greater than the remainder on the page
  14894. --|    then write remainder number of new lines
  14895. --|         decrement request by this amount
  14896. --|         write footer
  14897. --|         eject page and update page and line count
  14898. --|         if more space needed
  14899. --|            then recursively call self with count
  14900. --|    else write requested number of new lines
  14901. --|         update line count
  14902. --| Exit
  14903. --|+
  14904.  
  14905.     Skip_Count : INTEGER;
  14906.     Text_Kind  : Kind_Of_Text;
  14907.  
  14908.     begin
  14909.  
  14910.     if File_Handle.current_line = 0 and File_Handle.page_size /= 0 then
  14911.         File_Handle.current_line := 1;
  14912.         File_Handle.current_page := File_Handle.current_page + 1;
  14913.         if SP.Equal(File_Handle.file_spec, "") then
  14914.         if File_Handle.output_mode = STD then
  14915.             TIO.Put(TIO.Standard_Output, ASCII.FF);
  14916.         else
  14917.             TIO.Put(TIO.Current_Output, ASCII.FF);
  14918.         end if;
  14919.         else
  14920.         TIO.Put(File_Handle.file_reference, ASCII.FF);
  14921.         end if;
  14922.         Text_Kind.text := Header;
  14923.         Put_Text(File_Handle, Text_Kind);
  14924.     end if;
  14925.     if Count <= 0 then
  14926.         return;
  14927.     end if;
  14928.     Skip_Count := File_Handle.maximum_line - File_Handle.current_line + 1;
  14929.     if Count >= Skip_Count and File_Handle.page_size /= 0 then
  14930.         if Footer_Exist(File_Handle) then
  14931.         if SP.Equal(File_Handle.file_spec, "") then
  14932.             if File_Handle.output_mode = STD then
  14933.             TIO.New_Line(TIO.Standard_Output,
  14934.                      TIO.POSITIVE_Count(Skip_Count));
  14935.             else
  14936.             TIO.New_Line(TIO.Current_Output,
  14937.                      TIO.POSITIVE_Count(Skip_Count));
  14938.             end if;
  14939.         else
  14940.             TIO.New_Line(File_Handle.file_reference,
  14941.                  TIO.POSITIVE_Count(Skip_Count));
  14942.         end if;
  14943.         Text_Kind.text := footer;
  14944.         Put_Text(File_Handle, Text_Kind);
  14945.         else
  14946.         if SP.Equal(File_Handle.file_spec, "") then
  14947.             if File_Handle.output_mode = STD then
  14948.             TIO.New_Line(TIO.Standard_Output, 1);
  14949.             else
  14950.             TIO.New_Line(TIO.Current_Output, 1);
  14951.             end if;
  14952.         else
  14953.             TIO.New_Line(File_Handle.file_reference, 1);
  14954.         end if;
  14955.         end if;
  14956.         Skip_Count := Count - Skip_Count;
  14957.         File_Handle.current_line := 0;
  14958.         if Skip_Count /= 0 then
  14959.         Line_Feed(File_Handle, Skip_Count);
  14960.         end if;
  14961.     else
  14962.         if SP.Equal(File_Handle.file_spec, "") then
  14963.         if File_Handle.output_mode = STD then
  14964.             TIO.New_Line(TIO.Standard_Output,
  14965.                  TIO.POSITIVE_Count(Count));
  14966.         else
  14967.             TIO.New_Line(TIO.Current_Output,
  14968.                  TIO.POSITIVE_Count(Count));
  14969.         end if;
  14970.         else
  14971.         TIO.New_Line(File_Handle.file_reference,
  14972.                  TIO.POSITIVE_Count(Count));
  14973.         end if;
  14974.         if File_Handle.page_size /= 0 then
  14975.         File_Handle.current_line := File_Handle.current_line + Count;
  14976.         end if;
  14977.     end if;
  14978.     return;
  14979.  
  14980.     end Line_Feed;
  14981.                                                                     pragma page;
  14982.     procedure Page_Eject(
  14983.     File_Handle : in Paginated_File_Handle;
  14984.     Count       : in POSITIVE := 1
  14985.     ) is
  14986.  
  14987. --|-Algorithm:
  14988. --| Validate paginated file structure (raise error if not valid)
  14989. --| Raise Invalid_Count if page request is too large
  14990. --| Convert the number of pages to skip into number of lines  
  14991. --| Write out this number of new line control characters
  14992. --| while taking into account header, footer, and pagination.
  14993. --| Exit
  14994. --|+
  14995.  
  14996.     begin
  14997.  
  14998.     if File_Handle.page_size = 0 then
  14999.         Line_Feed(File_Handle, 1);
  15000.         return;
  15001.     end if;
  15002.     if Count > 99 then
  15003.         raise Invalid_Count;
  15004.     end if;
  15005.     if File_Handle.current_line = 0 then
  15006.         Line_Feed(File_Handle,
  15007.         (Count * File_Handle.maximum_line));
  15008.     else
  15009.         Line_Feed(File_Handle,
  15010.         (Count * File_Handle.maximum_line - File_Handle.current_line + 1));
  15011.     end if;
  15012.     return;
  15013.  
  15014.     end Page_Eject;
  15015.                                                                     pragma page;
  15016.     procedure Set_Text_Area(
  15017.     Text_Handle : in out Variable_String_Array_Handle;
  15018.     Area_Size   : in     INTEGER
  15019.     ) is
  15020.  
  15021.     Temp_Handle : Variable_String_Array_Handle;
  15022.  
  15023.     begin
  15024.  
  15025.     if Area_Size <= 0 then
  15026.         return;
  15027.     end if;
  15028.     if Text_Handle = null or else
  15029.        Text_Handle'last < Area_Size then
  15030.         Temp_Handle := Text_Handle;
  15031.         Text_Handle := new Variable_String_Array (1 .. Area_Size);
  15032.         if Temp_Handle /= null then
  15033.         for i in Temp_Handle'range loop
  15034.             Text_Handle(i) := SP.Make_Persistent(Temp_Handle(i));
  15035.         end loop;
  15036.         Clear_Text(Temp_Handle);
  15037.         end if;
  15038.       end if;
  15039.  
  15040.     end Set_Text_Area;
  15041.                                                                     pragma page;
  15042.     procedure Write(
  15043.     File_Handle : in Paginated_File_Handle;
  15044.     Text_Line   : in STRING;
  15045.     Feed        : in BOOLEAN
  15046.     ) is
  15047.  
  15048. --|-Algorithm:
  15049. --| Validate paginated file structure (raise error if not valid)
  15050. --| If at the top of the page
  15051. --|    then write out the header
  15052. --| Output the given line of text to the paginated file
  15053. --| Write out a new line control character
  15054. --| If at the bottom of the page
  15055. --|    then write out the footer and eject the page
  15056. --| Exit
  15057. --|+
  15058.  
  15059.     Handle : Paginated_File_Handle;
  15060.  
  15061.     begin
  15062.  
  15063.     Check_Valid(File_Handle);
  15064.     Handle := File_Handle;
  15065.     loop
  15066.         exit when Handle = null;
  15067.         Line_Feed(Handle, 0);
  15068.         if SP.Equal(Handle.file_spec, "") then
  15069.         if Handle.output_mode = STD then
  15070.             TIO.Put(TIO.Standard_Output, Text_Line);
  15071.         else
  15072.             TIO.Put(TIO.Current_Output, Text_Line);
  15073.         end if;
  15074.         else
  15075.         TIO.Put(Handle.file_reference, Text_Line);
  15076.         end if;
  15077.         if Feed then
  15078.         Line_Feed(Handle, 1);
  15079.         end if;
  15080.         Handle := Handle.forward_link;
  15081.     end loop;
  15082.     return;
  15083.  
  15084.     end Write;
  15085.                                                                     pragma page;
  15086.     procedure Create_Paginated_File(
  15087.     File_Name   : in STRING                     := "";
  15088.     File_Handle : in out Paginated_File_Handle;
  15089.     Page_Size   : in NATURAL                    := 66;
  15090.     Header_Size : in NATURAL                    := 6;
  15091.     Footer_Size : in NATURAL                    := 6;
  15092.     Output_mode : in Paginated_output_mode      := STD
  15093.     ) is
  15094.  
  15095. --|-Algorithm:
  15096. --| If an active (ie. non-null) handle is given
  15097. --|    then close that file first
  15098. --| Create a paginated file structure
  15099. --| If no file name is given
  15100. --|    then assume Standard output
  15101. --|    else create (open) an external file 
  15102. --| Fill the paginated file structure with external file information,
  15103. --| page layout information, and current date/time
  15104. --| Return access to the completed structure
  15105. --| Exit
  15106. --|+
  15107.  
  15108.     begin
  15109.  
  15110.     Close_Paginated_File(File_Handle);
  15111.     File_Handle := new Paginated_File_Structure;
  15112.     if File_Name /= "" then
  15113.         File_Handle.file_spec := SP.Make_Persistent(File_Name);
  15114.         TIO.Create(File => File_Handle.file_reference,
  15115.                Name => File_Name);
  15116.     end if;
  15117.     Reset_File_Name(File_Handle);
  15118.     Set_Page_Layout(File_Handle, Page_Size, Header_Size, Footer_Size);
  15119.     Reset_Date_Calendar_Time(File_Handle, (Date=>TRUE, Calendar_Date=>TRUE, Time=>TRUE));
  15120.     File_Handle.output_mode := output_mode;
  15121.     File_Handle.access_count := 1;
  15122.     return;
  15123.  
  15124.     exception
  15125.  
  15126.     when TIO.Status_error =>
  15127.         Abort_Paginated_Output(File_Handle);
  15128.         raise File_Already_Open;
  15129.     when TIO.Name_error | TIO.Use_error =>
  15130.         Abort_Paginated_Output(File_Handle);
  15131.         raise File_error;
  15132.     when Page_Layout_error =>
  15133.         Abort_Paginated_Output(File_Handle);
  15134.         raise Page_Layout_error;
  15135.  
  15136.     end Create_Paginated_File;
  15137.                                                                     pragma page;
  15138.     procedure Set_Standard_Paginated_File(
  15139.     File_Name   : in STRING;
  15140.     Page_Size   : in NATURAL;
  15141.     Header_Size : in NATURAL;
  15142.     Footer_Size : in NATURAL
  15143.     ) is
  15144.  
  15145.     begin
  15146.  
  15147.     Create_Paginated_File(File_Name,
  15148.                   Paginated_Standard_Output,
  15149.                   Page_Size,
  15150.                   Header_Size,
  15151.                   Footer_Size);
  15152.  
  15153.     end Set_Standard_Paginated_File;
  15154.                                                                     pragma page;
  15155.     procedure Duplicate_Paginated_File(
  15156.     Old_Handle : in Paginated_File_Handle;
  15157.     New_Handle : in out Paginated_File_Handle
  15158.     ) is
  15159.  
  15160. --|-Algorithm:
  15161. --| Close file refered to by the handle to which the existing handle
  15162. --| is to be copied (if such file exists)
  15163. --| Duplicate the handle
  15164. --| Exit
  15165. --|+
  15166.  
  15167.     begin
  15168.  
  15169.     Close_Paginated_File(New_Handle);
  15170.     Old_Handle.access_count := Old_Handle.access_count + 1;
  15171.     New_Handle := Old_Handle;
  15172.     return;
  15173.  
  15174.     end Duplicate_Paginated_File;
  15175.                                                                     pragma page;
  15176.     procedure Set_Page_Layout(
  15177.     Page_Size   : in NATURAL;
  15178.     Header_Size : in NATURAL;
  15179.     Footer_Size : in NATURAL
  15180.     ) is
  15181.  
  15182.     begin
  15183.  
  15184.     Set_Page_Layout(Paginated_Standard_Output,
  15185.             Page_Size,
  15186.             Header_Size,
  15187.             Footer_Size);
  15188.  
  15189.     end Set_Page_Layout;
  15190.  
  15191.  
  15192.     procedure Set_Page_Layout(
  15193.     File_Handle : in Paginated_File_Handle;
  15194.     Page_Size   : in NATURAL;
  15195.     Header_Size : in NATURAL;
  15196.     Footer_Size : in NATURAL
  15197.     ) is
  15198.  
  15199. --|-Algorithm:
  15200. --| Validate paginated file structure (raise error if not valid)
  15201. --| If page layout is contradictory
  15202. --|    then raise an error
  15203. --| If not at the top of the page
  15204. --|    then eject current page
  15205. --| Set page size, header size, footer size, and text area size
  15206. --| per page
  15207. --| Exit
  15208. --|+
  15209.  
  15210.     Temp_Handle : Variable_String_Array_Handle;
  15211.  
  15212.     begin
  15213.  
  15214.     Check_Valid(File_Handle);
  15215.     if Page_Size < 0 or Header_Size < 0 or Footer_Size < 0 or
  15216.        (Page_Size /= 0 and Page_Size <= Header_Size + Footer_Size) then
  15217.         raise Page_Layout_error;
  15218.         return;
  15219.     end if;
  15220.     if File_Handle.current_line /= 0 and File_Handle.page_size /= 0 then
  15221.         Page_Eject(File_Handle, 1);
  15222.     end if;
  15223.     File_Handle.page_size := Page_Size;
  15224.     if Page_Size = 0 then
  15225.         File_Handle.maximum_line := 0;
  15226.     else
  15227.         File_Handle.maximum_line := Page_Size - (Header_Size + Footer_Size);
  15228.     end if;
  15229.     File_Handle.header_size := Header_Size;
  15230.     Set_Text_Area(File_Handle.odd_page_header, File_Handle.header_size);
  15231.     Set_Text_Area(File_Handle.even_page_header, File_Handle.header_size);
  15232.     File_Handle.footer_size := Footer_Size;
  15233.     Set_Text_Area(File_Handle.odd_page_footer, File_Handle.footer_size);
  15234.     Set_Text_Area(File_Handle.even_page_footer, File_Handle.footer_size);
  15235.     return;
  15236.  
  15237.     end Set_Page_Layout;
  15238.                                                                     pragma page;
  15239.     procedure Link_Paginated_File(
  15240.     File_Handle1 : in Paginated_File_Handle;
  15241.     File_Handle2 : in Paginated_File_Handle
  15242.     ) is
  15243.  
  15244.     begin
  15245.  
  15246.     Check_Valid(File_Handle1);
  15247.     Check_Valid(File_Handle2);
  15248.     if File_Handle1.forward_link = null and
  15249.        File_Handle2.reverse_link = null then
  15250.         File_Handle1.forward_link := File_Handle2;
  15251.         File_Handle2.reverse_link := File_Handle1;
  15252.         return; 
  15253.     end if;
  15254.  
  15255.     raise Files_Already_Linked;
  15256.         
  15257.     end Link_Paginated_File;
  15258.  
  15259.  
  15260.     procedure Unlink_Paginated_File(
  15261.     File_Handle : in Paginated_File_Handle
  15262.     ) is
  15263.  
  15264.     begin
  15265.  
  15266.     Check_Valid(File_Handle);
  15267.     if File_Handle.reverse_link /= null then
  15268.         File_Handle.reverse_link.forward_link := File_Handle.forward_link;
  15269.         File_Handle.reverse_link := null;
  15270.     end if;
  15271.     if File_Handle.forward_link /= null then
  15272.         File_Handle.forward_link.reverse_link := File_Handle.reverse_link;
  15273.         File_Handle.forward_link := null;
  15274.     end if;
  15275.     return;    
  15276.  
  15277.     end Unlink_Paginated_File;
  15278.                                                                     pragma page;
  15279.     procedure Set_File_Name(
  15280.     File_Handle : in Paginated_File_Handle;
  15281.     File_Name   : in STRING
  15282.     ) is
  15283.  
  15284.     begin
  15285.  
  15286.     Check_Valid(File_Handle);
  15287.     File_Handle.file_name := SP.Make_Persistent(File_Name);
  15288.  
  15289.     end Set_File_Name;
  15290.  
  15291.  
  15292.     procedure Set_File_Name(
  15293.     File_Name   : in STRING
  15294.     ) is
  15295.  
  15296.     begin
  15297.  
  15298.     Set_File_Name(Paginated_Standard_Output, File_Name);
  15299.  
  15300.     end Set_File_Name;
  15301.  
  15302.  
  15303.     procedure Reset_File_Name(
  15304.     File_Handle : in Paginated_File_Handle
  15305.     ) is
  15306.  
  15307.     begin
  15308.  
  15309.     Check_Valid(File_Handle);
  15310.     if not SP.Equal(File_Handle.file_name, "") then    
  15311.         SP.Flush(File_Handle.file_name);
  15312.     end if;
  15313.     if SP.Equal(File_Handle.file_spec, "") then
  15314.         File_Handle.file_name := SP.Make_Persistent("STANDARD OUTPUT");
  15315.     else
  15316.         File_Handle.file_name := SP.Make_Persistent(File_Handle.file_spec);
  15317.     end if;
  15318.  
  15319.     end Reset_File_Name;
  15320.  
  15321.  
  15322.     procedure Reset_File_Name
  15323.     is
  15324.  
  15325.     begin
  15326.  
  15327.     Reset_File_Name(Paginated_Standard_Output);
  15328.  
  15329.     end Reset_File_Name;
  15330.                                                                     pragma page;
  15331.     procedure Set_Date(        
  15332.     File_Handle : in Paginated_File_Handle;
  15333.     Date : in Date_String        
  15334.     ) is
  15335.  
  15336.     S_Str : SP.String_Type;
  15337.  
  15338.     begin
  15339.  
  15340.     Check_Valid(File_Handle);
  15341.     File_Handle.current_date := Date;
  15342.  
  15343.     end Set_Date;
  15344.  
  15345.  
  15346.     procedure Set_Date(        
  15347.     Date : in Date_String        
  15348.     ) is
  15349.  
  15350.     begin
  15351.  
  15352.     Set_Date(Paginated_Standard_Output, Date);
  15353.  
  15354.     end Set_Date;
  15355.  
  15356.  
  15357.     procedure Reset_Date(        
  15358.     File_Handle : in Paginated_File_Handle
  15359.     ) is
  15360.  
  15361.     begin
  15362.  
  15363.     Check_Valid(File_Handle);
  15364.     Reset_Date_Calendar_Time(File_Handle, (Date=>TRUE, Calendar_Date=> FALSE, Time=>FALSE));
  15365.  
  15366.     end Reset_Date;
  15367.  
  15368.  
  15369.     procedure Reset_Date
  15370.     is
  15371.  
  15372.     begin
  15373.  
  15374.     Reset_Date(Paginated_Standard_Output);
  15375.  
  15376.     end Reset_Date;
  15377.                                                                     pragma page;
  15378.     procedure Set_Calendar(        
  15379.     File_Handle : in Paginated_File_Handle;
  15380.     Calendar : in STRING    
  15381.     ) is
  15382.  
  15383.     begin
  15384.  
  15385.     Check_Valid(File_Handle);
  15386.     File_Handle.current_Calendar := SP.Make_Persistent(Calendar);
  15387.  
  15388.     end Set_Calendar;
  15389.  
  15390.  
  15391.     procedure Set_Calendar(        
  15392.     Calendar : in STRING    
  15393.     ) is
  15394.  
  15395.     begin
  15396.  
  15397.     Set_Calendar(Paginated_Standard_Output, Calendar);
  15398.  
  15399.     end Set_Calendar;
  15400.  
  15401.  
  15402.     procedure Reset_Calendar(
  15403.     File_Handle : in Paginated_File_Handle
  15404.     ) is
  15405.  
  15406.     begin
  15407.  
  15408.     Check_Valid(File_Handle);
  15409.     Reset_Date_Calendar_Time(File_Handle, (Date=>FALSE, Calendar_Date=> TRUE, Time=>FALSE));
  15410.  
  15411.     end Reset_Calendar;
  15412.  
  15413.  
  15414.     procedure Reset_Calendar
  15415.     is
  15416.  
  15417.     begin
  15418.  
  15419.     Reset_Calendar(Paginated_Standard_Output);
  15420.  
  15421.     end Reset_Calendar;
  15422.                                                                     pragma page;
  15423.     procedure Set_Time(        
  15424.     File_Handle : in Paginated_File_Handle;
  15425.     Time        : in Time_String    
  15426.     ) is
  15427.  
  15428.     begin
  15429.  
  15430.     Check_Valid(File_Handle);
  15431.     File_Handle.current_time := Time;
  15432.  
  15433.     end Set_Time;
  15434.  
  15435.  
  15436.     procedure Set_Time(        
  15437.     Time : in Time_String    
  15438.     ) is
  15439.  
  15440.     begin
  15441.  
  15442.     Set_Time(Paginated_Standard_Output, Time);
  15443.  
  15444.     end Set_Time;
  15445.  
  15446.  
  15447.     procedure Reset_Time(        
  15448.     File_Handle : in Paginated_File_Handle
  15449.     ) is
  15450.  
  15451.     begin
  15452.  
  15453.     Check_Valid(File_Handle);
  15454.     Reset_Date_Calendar_Time(File_Handle, (Date=>FALSE, Calendar_Date=> FALSE, Time=>TRUE));
  15455.  
  15456.     end Reset_Time;
  15457.  
  15458.  
  15459.     procedure Reset_Time
  15460.     is
  15461.  
  15462.     begin
  15463.  
  15464.     Reset_Time(Paginated_Standard_Output);
  15465.  
  15466.     end Reset_Time;
  15467.                                                                     pragma page;
  15468.     procedure Set_Page(        
  15469.     File_Handle : in Paginated_File_Handle;
  15470.     Page        : in POSITIVE    
  15471.     ) is
  15472.  
  15473.     begin
  15474.  
  15475.     Check_Valid(File_Handle);
  15476.     File_Handle.current_page := Page - 1;
  15477.  
  15478.     end Set_Page;
  15479.  
  15480.  
  15481.     procedure Set_Page(        
  15482.     Page : in POSITIVE        
  15483.     ) is
  15484.  
  15485.     begin
  15486.  
  15487.     Set_Page(Paginated_Standard_Output, Page);
  15488.  
  15489.     end Set_Page;
  15490.  
  15491.  
  15492.     procedure Reset_Page(        
  15493.     File_Handle : in Paginated_File_Handle
  15494.     ) is
  15495.  
  15496.     begin
  15497.  
  15498.     Check_Valid(File_Handle);
  15499.     File_Handle.current_page := 0;
  15500.  
  15501.     end Reset_Page;
  15502.  
  15503.  
  15504.     procedure Reset_Page        
  15505.     is
  15506.  
  15507.     begin
  15508.  
  15509.     Reset_Page(Paginated_Standard_Output);
  15510.  
  15511.     end Reset_Page;
  15512.                                                                     pragma page;
  15513.     procedure Set_Header(
  15514.     Header_Text : in Variable_String_Array
  15515.     ) is
  15516.  
  15517.     begin
  15518.     Set_Header(Paginated_Standard_Output,
  15519.            Header_Text);
  15520.  
  15521.     end Set_Header;
  15522.  
  15523.  
  15524.     procedure Set_Header(
  15525.     File_Handle : in Paginated_File_Handle;
  15526.     Header_Text : in Variable_String_Array
  15527.     ) is
  15528.  
  15529. --|-Algorithm:
  15530. --| Set given header text as odd page header 
  15531. --| Set given header text as even page header 
  15532. --| Exit
  15533. --|+
  15534.  
  15535.     begin
  15536.  
  15537.     Set_Text(File_Handle, Header_Text, (Odd, Header));
  15538.     Set_Text(File_Handle, Header_Text, (Even, Header));
  15539.     return;
  15540.  
  15541.     end Set_Header;
  15542.  
  15543.  
  15544.     procedure Set_Header(
  15545.     Header_Line : in POSITIVE;
  15546.     Header_Text : in SP.String_Type
  15547.     ) is
  15548.  
  15549.     begin
  15550.  
  15551.     Set_Header(Paginated_Standard_Output,
  15552.            Header_Line,
  15553.            Header_Text);
  15554.  
  15555.     end Set_Header;
  15556.  
  15557.  
  15558.     procedure Set_Header(
  15559.     File_Handle : in Paginated_File_Handle;
  15560.     Header_Line : in POSITIVE;
  15561.     Header_Text : in SP.String_Type
  15562.     ) is
  15563.  
  15564. --|-Algorithm:
  15565. --| Set odd page header
  15566. --| Set even page header
  15567. --| Exit
  15568. --|+
  15569.  
  15570.     begin
  15571.  
  15572.     Set_Odd_Header(File_Handle, Header_Line, Header_Text);
  15573.     Set_Even_Header(File_Handle, Header_Line, Header_Text);
  15574.     return;
  15575.  
  15576.     end Set_Header;
  15577.  
  15578.  
  15579.     procedure Set_Header(
  15580.     Header_Line : in POSITIVE;
  15581.     Header_Text : in STRING
  15582.     ) is
  15583.  
  15584.     begin
  15585.  
  15586.     Set_Header(Paginated_Standard_Output,
  15587.            Header_Line,
  15588.            Header_Text);
  15589.  
  15590.     end Set_Header;
  15591.  
  15592.  
  15593.     procedure Set_Header(
  15594.     File_Handle : in Paginated_File_Handle;
  15595.     Header_Line : in POSITIVE;
  15596.     Header_Text : in STRING
  15597.     ) is
  15598.  
  15599. --|-Algorithm:
  15600. --| Create a variable string
  15601. --| Set odd page header
  15602. --| Set even page header
  15603. --| Exit
  15604. --|+
  15605.  
  15606.     Text : SP.String_Type;
  15607.  
  15608.     begin
  15609.  
  15610.     Text :=    SP.Make_Persistent(Header_Text);
  15611.     Set_Odd_Header(File_Handle, Header_Line, Text);
  15612.     Set_Even_Header(File_Handle, Header_Line, Text);
  15613.     SP.Flush(Text);
  15614.     return;
  15615.  
  15616.     end Set_Header;
  15617.                                                                     pragma page;
  15618.     procedure Set_Odd_Header(
  15619.     Header_Text : in Variable_String_Array
  15620.     ) is
  15621.  
  15622.     begin
  15623.  
  15624.     Set_Odd_Header(Paginated_Standard_Output,
  15625.                Header_Text);
  15626.  
  15627.     end Set_Odd_Header;
  15628.  
  15629.  
  15630.     procedure Set_Odd_Header(
  15631.     File_Handle : in Paginated_File_Handle;
  15632.     Header_Text : in Variable_String_Array
  15633.     ) is
  15634.  
  15635. --|-Algorithm:
  15636. --| Set given header text as odd page header 
  15637. --| Exit
  15638. --|+
  15639.  
  15640.     begin
  15641.  
  15642.     Set_Text(File_Handle, Header_Text, (Odd, Header));
  15643.     return;
  15644.  
  15645.     end Set_Odd_Header;
  15646.  
  15647.  
  15648.     procedure Set_Odd_Header(
  15649.     Header_Line : in POSITIVE;
  15650.     Header_Text : in SP.String_Type
  15651.     ) is
  15652.  
  15653.     begin
  15654.  
  15655.     Set_Odd_Header(Paginated_Standard_Output,
  15656.                Header_Line,
  15657.                Header_Text);
  15658.  
  15659.     end Set_Odd_Header;
  15660.  
  15661.  
  15662.     procedure Set_Odd_Header(
  15663.     File_Handle : in Paginated_File_Handle;
  15664.     Header_Line : in POSITIVE;
  15665.     Header_Text : in SP.String_Type
  15666.     ) is
  15667.  
  15668. --|-Algorithm:
  15669. --| Validate paginated file structure (raise error if not valid)
  15670. --| If requested header line number is out of range
  15671. --|     then raise an error
  15672. --| Set header text at requested line for odd pages
  15673. --| Exit
  15674. --|+
  15675.  
  15676.     begin
  15677.  
  15678.     Check_Valid(File_Handle);
  15679.     if Header_Line > File_Handle.header_size then
  15680.         raise Text_Overflow;
  15681.     end if;
  15682.     File_Handle.odd_page_header(Header_Line) := SP.Make_Persistent(Header_Text);
  15683.     return;
  15684.  
  15685.     end Set_Odd_Header;
  15686.  
  15687.  
  15688.     procedure Set_Odd_Header(
  15689.     Header_Line : in POSITIVE;
  15690.     Header_Text : in STRING
  15691.     ) is
  15692.  
  15693.     begin
  15694.  
  15695.     Set_Odd_Header(Paginated_Standard_Output,
  15696.                Header_Line,
  15697.                Header_Text);
  15698.  
  15699.     end Set_Odd_Header;
  15700.  
  15701.  
  15702.     procedure Set_Odd_Header(
  15703.     File_Handle : in Paginated_File_Handle;
  15704.     Header_Line : in POSITIVE;
  15705.     Header_Text : in STRING
  15706.     ) is
  15707.  
  15708. --|-Algorithm:
  15709. --| Create a variable string
  15710. --| Set odd page header
  15711. --| Exit
  15712. --|+
  15713.  
  15714.     Text : SP.String_Type;
  15715.  
  15716.     begin
  15717.  
  15718.     Text := SP.Make_Persistent(Header_Text);
  15719.     Set_Odd_Header(File_Handle, Header_Line, Text);
  15720.     SP.Flush(Text);
  15721.     return;
  15722.  
  15723.     end Set_Odd_Header;
  15724.                                                                     pragma page;
  15725.     procedure Set_Even_Header(
  15726.     Header_Text : in Variable_String_Array
  15727.     ) is
  15728.  
  15729.     begin
  15730.  
  15731.     Set_Even_Header(Paginated_Standard_Output,
  15732.             Header_Text);
  15733.  
  15734.     end Set_Even_Header;
  15735.  
  15736.  
  15737.     procedure Set_Even_Header(
  15738.     File_Handle : in Paginated_File_Handle;
  15739.     Header_Text : in Variable_String_Array
  15740.     ) is
  15741.  
  15742. --|-Algorithm:
  15743. --| Set given header text as even page header 
  15744. --| Exit
  15745. --|+
  15746.  
  15747.     begin
  15748.  
  15749.     Set_Text(File_Handle, Header_Text, (Even, Header));
  15750.     return;
  15751.  
  15752.     end Set_Even_Header;
  15753.  
  15754.  
  15755.     procedure Set_Even_Header(
  15756.     Header_Line : in POSITIVE;
  15757.     Header_Text : in SP.String_Type
  15758.     ) is
  15759.  
  15760.     begin
  15761.  
  15762.     Set_Even_Header(Paginated_Standard_Output,
  15763.             Header_Line,
  15764.             Header_Text);
  15765.  
  15766.     end Set_Even_Header;
  15767.  
  15768.  
  15769.     procedure Set_Even_Header(
  15770.     File_Handle : in Paginated_File_Handle;
  15771.     Header_Line : in POSITIVE;
  15772.     Header_Text : in SP.String_Type
  15773.     ) is
  15774.  
  15775. --|-Algorithm:
  15776. --| Validate paginated file structure (raise error if not valid)
  15777. --| If requested header line number is out of range
  15778. --|     then raise an error
  15779. --| Set header text at requested line for even pages
  15780. --| Exit
  15781. --|+
  15782.  
  15783.     begin
  15784.  
  15785.     Check_Valid(File_Handle);
  15786.     if Header_Line > File_Handle.header_size then
  15787.         raise Text_Overflow;
  15788.     end if;
  15789.     SP.Flush(File_Handle.even_page_header(Header_Line));
  15790.     File_Handle.even_page_header(Header_Line) := SP.Make_Persistent(Header_Text);
  15791.     return;
  15792.  
  15793.     end Set_Even_Header;
  15794.  
  15795.  
  15796.     procedure Set_Even_Header(
  15797.     Header_Line : in POSITIVE;
  15798.     Header_Text : in STRING
  15799.     ) is
  15800.  
  15801.     begin
  15802.  
  15803.     Set_Even_Header(Paginated_Standard_Output,
  15804.             Header_Line,
  15805.             Header_Text);
  15806.  
  15807.     end Set_Even_Header;
  15808.  
  15809.  
  15810.     procedure Set_Even_Header(
  15811.     File_Handle : in Paginated_File_Handle;
  15812.     Header_Line : in POSITIVE;
  15813.     Header_Text : in STRING
  15814.     ) is
  15815.  
  15816. --|-Algorithm:
  15817. --| Create a variable string
  15818. --| Set even page header
  15819. --| Exit
  15820. --|+
  15821.  
  15822.     Text : SP.String_Type;
  15823.  
  15824.     begin
  15825.  
  15826.     Text :=    SP.Make_Persistent(Header_Text);
  15827.     Set_Even_Header(File_Handle, Header_Line, Text);
  15828.     SP.Flush(Text);
  15829.     return;
  15830.  
  15831.     end Set_Even_Header;
  15832.                                                                     pragma page;
  15833.     procedure Set_Footer(
  15834.     Footer_Text : in Variable_String_Array
  15835.     ) is
  15836.  
  15837.     begin
  15838.  
  15839.     Set_Footer(Paginated_Standard_Output,
  15840.            Footer_Text);
  15841.  
  15842.     end Set_Footer;
  15843.  
  15844.  
  15845.     procedure Set_Footer(
  15846.     File_Handle : in Paginated_File_Handle;
  15847.     Footer_Text : in Variable_String_Array
  15848.     ) is
  15849.  
  15850. --|-Algorithm:
  15851. --| Set given footer text as odd page header 
  15852. --| Set given footer text as even page header 
  15853. --| Exit
  15854. --|+
  15855.  
  15856.     begin
  15857.  
  15858.     Set_Text(File_Handle, Footer_Text, (Odd, Footer));
  15859.     Set_Text(File_Handle, Footer_Text, (Even, Footer));
  15860.     return;
  15861.  
  15862.     end Set_Footer;
  15863.  
  15864.  
  15865.     procedure Set_Footer(
  15866.     Footer_Line : in POSITIVE;
  15867.     Footer_Text : in SP.String_Type
  15868.     ) is
  15869.  
  15870.     begin
  15871.  
  15872.     Set_Footer(Paginated_Standard_Output,
  15873.            Footer_Line,
  15874.            Footer_Text);
  15875.  
  15876.     end Set_Footer;
  15877.  
  15878.  
  15879.     procedure Set_Footer(
  15880.     File_Handle : in Paginated_File_Handle;
  15881.     Footer_Line : in POSITIVE;
  15882.     Footer_Text : in SP.String_Type
  15883.     ) is
  15884.  
  15885. --|-Algorithm:
  15886. --| Set odd page footer
  15887. --| Set even page footer
  15888. --| Exit
  15889. --|+
  15890.  
  15891.     begin
  15892.  
  15893.     Set_Odd_Footer(File_Handle, Footer_Line, Footer_Text);
  15894.     Set_Even_Footer(File_Handle, Footer_Line, Footer_Text);
  15895.     return;
  15896.  
  15897.     end Set_Footer;
  15898.  
  15899.  
  15900.     procedure Set_Footer(
  15901.     Footer_Line : in POSITIVE;
  15902.     Footer_Text : in STRING
  15903.     ) is
  15904.  
  15905.     begin
  15906.  
  15907.     Set_Footer(Paginated_Standard_Output,
  15908.            Footer_Line,
  15909.            Footer_Text);
  15910.  
  15911.     end Set_Footer;
  15912.  
  15913.  
  15914.     procedure Set_Footer(
  15915.     File_Handle : in Paginated_File_Handle;
  15916.     Footer_Line : in POSITIVE;
  15917.     Footer_Text : in STRING
  15918.     ) is
  15919.  
  15920. --|-Algorithm:
  15921. --| Create a variable string
  15922. --| Set odd page footer
  15923. --| Set even page footer
  15924. --| Exit
  15925. --|+
  15926.  
  15927.     Text : SP.String_Type;
  15928.  
  15929.     begin
  15930.  
  15931.     Text := SP.Make_Persistent(Footer_Text);
  15932.     Set_Odd_Footer(File_Handle, Footer_Line, Text);
  15933.     Set_Even_Footer(File_Handle, Footer_Line, Text);
  15934.     SP.Flush(Text);
  15935.     return;
  15936.  
  15937.     end Set_Footer;
  15938.                                                                     pragma page;
  15939.     procedure Set_Odd_Footer(
  15940.     Footer_Text : in Variable_String_Array
  15941.     ) is
  15942.  
  15943.     begin
  15944.  
  15945.     Set_Odd_Footer(Paginated_Standard_Output,
  15946.                Footer_Text);
  15947.  
  15948.     end Set_Odd_Footer;
  15949.  
  15950.  
  15951.     procedure Set_Odd_Footer(
  15952.     File_Handle : in Paginated_File_Handle;
  15953.     Footer_Text : in Variable_String_Array
  15954.     ) is
  15955.  
  15956. --|-Algorithm:
  15957. --| Set given footer text as odd page header 
  15958. --| Exit
  15959. --|+
  15960.  
  15961.     begin
  15962.  
  15963.     Set_Text(File_Handle, Footer_Text, (Odd, Footer));
  15964.     return;
  15965.  
  15966.     end Set_Odd_Footer;
  15967.  
  15968.  
  15969.     procedure Set_Odd_Footer(
  15970.     Footer_Line : in POSITIVE;
  15971.     Footer_Text : in SP.String_Type
  15972.     ) is
  15973.  
  15974.     begin
  15975.  
  15976.     Set_Odd_Footer(Paginated_Standard_Output,
  15977.                Footer_Line,
  15978.                Footer_Text);
  15979.  
  15980.     end Set_Odd_Footer;
  15981.  
  15982.  
  15983.     procedure Set_Odd_Footer(
  15984.     File_Handle : in Paginated_File_Handle;
  15985.     Footer_Line : in POSITIVE;
  15986.     Footer_Text : in SP.String_Type
  15987.     ) is
  15988.  
  15989. --|-Algorithm:
  15990. --| Validate paginated file structure (raise error if not valid)
  15991. --| If requested footer line number is out of range
  15992. --|     then raise an error
  15993. --| Set footer text at requested line for odd pages
  15994. --| Exit
  15995. --|+
  15996.  
  15997.     begin
  15998.  
  15999.     Check_Valid(File_Handle);
  16000.     if Footer_Line > File_Handle.footer_size then
  16001.         raise Text_Overflow;
  16002.     end if;
  16003.     SP.Flush(File_Handle.odd_page_footer(Footer_Line));
  16004.     File_Handle.odd_page_footer(Footer_Line) := SP.Make_Persistent(Footer_Text);
  16005.     return;
  16006.  
  16007.     end Set_Odd_Footer;
  16008.  
  16009.  
  16010.     procedure Set_Odd_Footer(
  16011.     Footer_Line : in POSITIVE;
  16012.     Footer_Text : in STRING
  16013.     ) is
  16014.  
  16015.     begin
  16016.  
  16017.     Set_Odd_Footer(Paginated_Standard_Output,
  16018.                Footer_Line,
  16019.                Footer_Text);
  16020.  
  16021.     end Set_Odd_Footer;
  16022.  
  16023.  
  16024.     procedure Set_Odd_Footer(
  16025.     File_Handle : in Paginated_File_Handle;
  16026.     Footer_Line : in POSITIVE;
  16027.     Footer_Text : in STRING
  16028.     ) is
  16029.  
  16030.     Text : SP.String_Type;
  16031.  
  16032.     begin
  16033.  
  16034.     Text := SP.Make_Persistent(Footer_Text);
  16035.     Set_Odd_Footer(File_Handle, Footer_Line, Text);
  16036.     SP.Flush(Text);
  16037.     return;
  16038.  
  16039.     end Set_Odd_Footer;
  16040.                                                                     pragma page;
  16041.     procedure Set_Even_Footer(
  16042.     Footer_Text : in Variable_String_Array
  16043.     ) is
  16044.  
  16045.     begin
  16046.  
  16047.     Set_Even_Footer(Paginated_Standard_Output,
  16048.             Footer_Text);
  16049.  
  16050.     end Set_Even_Footer;
  16051.  
  16052.  
  16053.     procedure Set_Even_Footer(
  16054.     File_Handle : in Paginated_File_Handle;
  16055.     Footer_Text : in Variable_String_Array
  16056.     ) is
  16057.  
  16058. --|-Algorithm:
  16059. --| Set given footer text as even page header 
  16060. --| Exit
  16061. --|+
  16062.  
  16063.     begin
  16064.  
  16065.     Set_Text(File_Handle, Footer_Text, (Even, Footer));
  16066.     return;
  16067.  
  16068.     end Set_Even_Footer;
  16069.  
  16070.  
  16071.     procedure Set_Even_Footer(
  16072.     Footer_Line : in POSITIVE;
  16073.     Footer_Text : in SP.String_Type
  16074.     ) is
  16075.  
  16076.     begin
  16077.  
  16078.     Set_Even_Footer(Paginated_Standard_Output,
  16079.             Footer_Line,
  16080.             Footer_Text);
  16081.  
  16082.     end Set_Even_Footer;
  16083.  
  16084.  
  16085.     procedure Set_Even_Footer(
  16086.     File_Handle : in Paginated_File_Handle;
  16087.     Footer_Line : in POSITIVE;
  16088.     Footer_Text : in SP.String_Type
  16089.     ) is
  16090.  
  16091. --|-Algorithm:
  16092. --| Validate paginated file structure (raise error if not valid)
  16093. --| If requested footer line number is out of range
  16094. --|     then raise an error
  16095. --| Set footer text at requested line for even pages
  16096. --| Exit
  16097. --|+
  16098.  
  16099.     begin
  16100.  
  16101.     Check_Valid(File_Handle);
  16102.     if Footer_Line > File_Handle.footer_size then
  16103.         raise Text_Overflow;
  16104.     end if;
  16105.     SP.Flush(File_Handle.even_page_footer(Footer_Line));
  16106.     File_Handle.even_page_footer(Footer_Line) := SP.Make_Persistent(Footer_Text);
  16107.     return;
  16108.  
  16109.     end Set_Even_Footer;
  16110.  
  16111.  
  16112.     procedure Set_Even_Footer(
  16113.     Footer_Line : in POSITIVE;
  16114.     Footer_Text : in STRING
  16115.     ) is
  16116.  
  16117.     begin
  16118.  
  16119.     Set_Even_Footer(Paginated_Standard_Output,
  16120.             Footer_Line,
  16121.             Footer_Text);
  16122.  
  16123.     end Set_Even_Footer;
  16124.  
  16125.  
  16126.     procedure Set_Even_Footer(
  16127.     File_Handle : in Paginated_File_Handle;
  16128.     Footer_Line : in POSITIVE;
  16129.     Footer_Text : in STRING
  16130.     ) is
  16131.  
  16132. --|-Algorithm:
  16133. --| Create a variable string
  16134. --| Set even page footer
  16135. --| Exit
  16136. --|+
  16137.     Text : SP.String_Type;
  16138.  
  16139.     begin
  16140.  
  16141.     Text := SP.Make_Persistent(Footer_Text);
  16142.     Set_Even_Footer(File_Handle, Footer_Line, Text);
  16143.     SP.Flush(Text);
  16144.     return;
  16145.  
  16146.     end Set_Even_Footer;
  16147.                                                                     pragma page;
  16148.     procedure Clear_Header    
  16149.     is
  16150.  
  16151.     begin
  16152.  
  16153.     Clear_Header(Paginated_Standard_Output);
  16154.  
  16155.     end Clear_Header;
  16156.  
  16157.  
  16158.     procedure Clear_Header(    
  16159.     File_Handle : in Paginated_File_Handle
  16160.     ) is
  16161.  
  16162. --|-Algorithm:
  16163. --| Clear odd page header
  16164. --| Clear even page header
  16165. --| Exit
  16166. --|+
  16167.  
  16168.     begin
  16169.  
  16170.     Clear_Odd_Header(File_Handle);
  16171.     Clear_Even_Header(File_Handle);
  16172.     return;
  16173.  
  16174.     end Clear_Header;
  16175.                                                                     pragma page;
  16176.     procedure Clear_Odd_Header
  16177.     is
  16178.  
  16179.     begin
  16180.  
  16181.     Clear_Odd_Header(Paginated_Standard_Output);
  16182.  
  16183.     end Clear_Odd_Header;
  16184.  
  16185.  
  16186.     procedure Clear_Odd_Header(
  16187.     File_Handle : in Paginated_File_Handle
  16188.     ) is
  16189.  
  16190. --|-Algorithm:
  16191. --| Validate paginated file structure (raise error if not valid)
  16192. --| Clear all text for odd page header lines
  16193. --| Exit
  16194. --|+
  16195.  
  16196.     begin
  16197.  
  16198.     Check_Valid(File_Handle);
  16199.     Clear_Text(File_Handle.odd_page_header);
  16200.     return;
  16201.  
  16202.     end Clear_Odd_Header;
  16203.                                                                     pragma page;
  16204.     procedure Clear_Even_Header
  16205.     is
  16206.  
  16207.     begin
  16208.  
  16209.     Clear_Even_Header(Paginated_Standard_Output);
  16210.  
  16211.     end Clear_Even_Header;
  16212.  
  16213.  
  16214.     procedure Clear_Even_Header(
  16215.     File_Handle : in Paginated_File_Handle
  16216.     ) is
  16217.  
  16218. --|-Algorithm:
  16219. --| Validate paginated file structure (raise error if not valid)
  16220. --| Clear all text for even page header lines
  16221. --| Exit
  16222. --|+
  16223.  
  16224.     begin
  16225.  
  16226.     Check_Valid(File_Handle);
  16227.     Clear_Text(File_Handle.even_page_header);
  16228.     return;
  16229.  
  16230.     end Clear_Even_Header;
  16231.                                                                     pragma page;
  16232.     procedure Clear_Footer
  16233.     is
  16234.  
  16235.     begin
  16236.  
  16237.     Clear_Footer(Paginated_Standard_Output);
  16238.  
  16239.     end Clear_Footer;
  16240.  
  16241.  
  16242.     procedure Clear_Footer(    
  16243.     File_Handle : in Paginated_File_Handle
  16244.     ) is
  16245.  
  16246. --|-Algorithm:
  16247. --| Clear odd page footer
  16248. --| Clear even page footer
  16249. --| Exit
  16250. --|+
  16251.  
  16252.     begin
  16253.  
  16254.     Clear_Odd_Footer(File_Handle);
  16255.     Clear_Even_Footer(File_Handle);
  16256.     return;
  16257.  
  16258.     end Clear_Footer;
  16259.                                                                     pragma page;
  16260.     procedure Clear_Odd_Footer
  16261.     is
  16262.  
  16263.     begin
  16264.  
  16265.     Clear_Odd_Footer(Paginated_Standard_Output);
  16266.  
  16267.     end Clear_Odd_Footer;
  16268.  
  16269.  
  16270.     procedure Clear_Odd_Footer(
  16271.     File_Handle : in Paginated_File_Handle
  16272.     ) is
  16273.  
  16274. --|-Algorithm:
  16275. --| Validate paginated file structure (raise error if not valid)
  16276. --| Clear all text for odd page footer lines
  16277. --| Exit
  16278. --|+
  16279.  
  16280.     begin
  16281.  
  16282.     Check_Valid(File_Handle);
  16283.     Clear_Text(File_Handle.odd_page_footer);
  16284.     return;
  16285.  
  16286.     end Clear_Odd_Footer;
  16287.                                                                     pragma page;
  16288.     procedure Clear_Even_Footer
  16289.     is
  16290.  
  16291.     begin
  16292.  
  16293.     Clear_Even_Footer(Paginated_Standard_Output);
  16294.  
  16295.     end Clear_Even_Footer;
  16296.  
  16297.  
  16298.     procedure Clear_Even_Footer(
  16299.     File_Handle : in Paginated_File_Handle
  16300.     ) is
  16301.  
  16302. --|-Algorithm:
  16303. --| Validate paginated file structure (raise error if not valid)
  16304. --| Clear all text for even footer lines
  16305. --| Exit
  16306. --|+
  16307.  
  16308.     begin
  16309.  
  16310.     Check_Valid(File_Handle);
  16311.     Clear_Text(File_Handle.even_page_footer);
  16312.     return;
  16313.  
  16314.     end Clear_Even_Footer;
  16315.                                                                     pragma page;
  16316.     procedure Close_Paginated_File
  16317.     is
  16318.  
  16319.     begin
  16320.  
  16321.     Close_Paginated_File(Paginated_Standard_Output);
  16322.     Create_Paginated_File("", Paginated_Standard_Output, 0, 0, 0);
  16323.     
  16324.     end Close_Paginated_File;
  16325.  
  16326.  
  16327.     procedure Close_Paginated_File(
  16328.     File_Handle : in out Paginated_File_Handle
  16329.     ) is
  16330.  
  16331. --|-Algorithm:
  16332. --| If no file (ie. handle is null)
  16333. --|    then return
  16334. --| Decrement access count to this file structure
  16335. --| If other accesses still exist for this structure
  16336. --|    then null this handle and return
  16337. --| If not at the top of the page
  16338. --|    then eject current page
  16339. --| Return all storage used for this file to the heap
  16340. --| Close the external file
  16341. --| Exit
  16342. --|+
  16343.  
  16344.     begin
  16345.  
  16346.     if File_Handle = null then
  16347.         return;
  16348.     end if;
  16349.     File_Handle.access_count := File_Handle.access_count - 1;
  16350.     if File_Handle.access_count > 0 then
  16351.         File_Handle := null;
  16352.         return;
  16353.     end if;
  16354.     Unlink_Paginated_File(File_Handle);
  16355.     if File_Handle.current_line /= 0 and File_Handle.page_size /= 0 then
  16356.         Page_Eject(File_Handle, 1);
  16357.     end if;
  16358.     Abort_Paginated_Output(File_Handle);
  16359.     return;
  16360.  
  16361.     end Close_Paginated_File;
  16362.                                                                     pragma page;
  16363.     procedure Put(
  16364.     Text        : in CHARACTER
  16365.     ) is
  16366.  
  16367.     begin
  16368.  
  16369.     Put(Paginated_Standard_Output,
  16370.         Text);
  16371.  
  16372.     end Put;
  16373.  
  16374.  
  16375.     procedure Put(
  16376.     File_Handle : in Paginated_File_Handle;
  16377.     Text        : in CHARACTER
  16378.     ) is
  16379.  
  16380.     begin
  16381.  
  16382.     Write(File_Handle, "" & Text, FALSE);
  16383.  
  16384.     end Put;
  16385.  
  16386.  
  16387.     procedure Put(
  16388.     Text        : in STRING
  16389.     ) is
  16390.  
  16391.     begin
  16392.  
  16393.     Write(Paginated_Standard_Output, Text, FALSE);
  16394.  
  16395.     end Put;
  16396.  
  16397.  
  16398.     procedure Put(
  16399.     File_Handle : in Paginated_File_Handle;
  16400.     Text        : in STRING
  16401.     ) is
  16402.  
  16403. --|-Algorithm:
  16404. --| Execute Write procedure with feed
  16405. --| Exit
  16406. --|+
  16407.  
  16408.     begin
  16409.  
  16410.     Write(File_Handle, Text, FALSE);
  16411.  
  16412.     end Put;
  16413.  
  16414.  
  16415.     procedure Put(
  16416.     Text        : in SP.String_Type
  16417.     ) is
  16418.  
  16419.     begin
  16420.  
  16421.     Put(Paginated_Standard_Output,
  16422.         SP.Value(Text));
  16423.  
  16424.     end Put;
  16425.  
  16426.  
  16427.     procedure Put(
  16428.     File_Handle : in Paginated_File_Handle;
  16429.     Text        : in SP.String_Type
  16430.     ) is
  16431.  
  16432. --|-Algorithm:
  16433. --| Create a fixed length string
  16434. --| Output the line
  16435. --| Exit
  16436. --|+
  16437.  
  16438.     begin
  16439.  
  16440.     Put(File_Handle, SP.Value(Text));
  16441.     return;
  16442.  
  16443.     end Put;
  16444.  
  16445.  
  16446.     procedure Put(
  16447.     Text        : in Variable_String_Array
  16448.     ) is
  16449.  
  16450.     begin
  16451.  
  16452.     for i in Text'range loop
  16453.         Put(Paginated_Standard_Output, SP.Value(Text(i)));
  16454.     end loop;
  16455.     return;
  16456.  
  16457.     end Put;
  16458.  
  16459.  
  16460.     procedure Put(
  16461.     File_Handle : in Paginated_File_Handle;
  16462.     Text        : in Variable_String_Array
  16463.     ) is
  16464.  
  16465. --|-Algorithm:
  16466. --| Loop for all elements of the variable string array
  16467. --|    Create a fixed length string
  16468. --|    Output the line
  16469. --| Exit
  16470. --|+
  16471.  
  16472.     begin
  16473.  
  16474.     for i in Text'range loop
  16475.         Put(File_Handle, SP.Value(Text(i)));
  16476.     end loop;
  16477.     return;
  16478.  
  16479.     end Put;
  16480.                                                                     pragma page;
  16481.     procedure Space(
  16482.     Count       : in NATURAL
  16483.     ) is
  16484.  
  16485.     begin
  16486.  
  16487.     Space(Paginated_Standard_Output,
  16488.           Count);
  16489.  
  16490.     end Space;
  16491.  
  16492.  
  16493.     procedure Space(
  16494.     File_Handle : in Paginated_File_Handle;
  16495.     Count       : in NATURAL
  16496.     ) is
  16497.  
  16498.     begin
  16499.  
  16500.     Check_Valid(File_Handle);
  16501.     if Count = 0 then
  16502.         return;
  16503.     end if;
  16504.     declare
  16505.         Space_String : STRING (1 .. Count) := (1 .. Count => ' ');
  16506.     begin
  16507.         Put(File_Handle, Space_String);
  16508.     end;
  16509.  
  16510.     end Space;
  16511.                                                                     pragma page;
  16512.     procedure Put_Line(
  16513.     Text_Line   : in STRING
  16514.     ) is
  16515.  
  16516.     begin
  16517.  
  16518.     Write(Paginated_Standard_Output, Text_Line, TRUE);
  16519.  
  16520.     end Put_Line;
  16521.  
  16522.  
  16523.     procedure Put_Line(
  16524.     File_Handle : in Paginated_File_Handle;
  16525.     Text_Line   : in STRING
  16526.     ) is
  16527.  
  16528. --|-Algorithm:
  16529. --| Execute Write procedure with feed
  16530. --| Exit
  16531. --|+
  16532.  
  16533.     begin
  16534.  
  16535.     Write(File_Handle, Text_Line, TRUE);
  16536.  
  16537.     end Put_Line;
  16538.  
  16539.  
  16540.     procedure Put_Line(
  16541.     Text_Line   : in SP.String_Type
  16542.     ) is
  16543.  
  16544.     begin
  16545.  
  16546.     Put_Line(Paginated_Standard_Output,
  16547.          SP.Value(Text_Line));
  16548.     return;
  16549.  
  16550.     end Put_Line;
  16551.  
  16552.  
  16553.     procedure Put_Line(
  16554.     File_Handle : in Paginated_File_Handle;
  16555.     Text_Line   : in SP.String_Type
  16556.     ) is
  16557.  
  16558. --|-Algorithm:
  16559. --| Create a fixed length string
  16560. --| Output the line
  16561. --| Exit
  16562. --|+
  16563.  
  16564.     begin
  16565.  
  16566.     Put_Line(File_Handle, SP.Value(Text_Line));
  16567.     return;
  16568.  
  16569.     end Put_Line;
  16570.  
  16571.  
  16572.     procedure Put_Line(
  16573.     Text_Line   : in Variable_String_Array
  16574.     ) is
  16575.  
  16576.     begin
  16577.  
  16578.     for i in Text_Line'range loop
  16579.         Put_Line(Paginated_Standard_Output,
  16580.              SP.Value(Text_Line(i)));
  16581.     end loop;
  16582.     return;
  16583.  
  16584.     end Put_Line;
  16585.  
  16586.  
  16587.     procedure Put_Line(
  16588.     File_Handle : in Paginated_File_Handle;
  16589.     Text_Line   : in Variable_String_Array
  16590.     ) is
  16591.  
  16592. --|-Algorithm:
  16593. --| Loop for all elements of the variable string array
  16594. --|    Create a fixed length string
  16595. --|    Output the line
  16596. --| Exit
  16597. --|+
  16598.  
  16599.     begin
  16600.  
  16601.     for i in Text_Line'range loop
  16602.         Put_Line(File_Handle, SP.Value(Text_Line(i)));
  16603.     end loop;
  16604.     return;
  16605.  
  16606.     end Put_Line;
  16607.                                                                     pragma page;
  16608.     procedure Space_Line(
  16609.     Count       : in NATURAL := 1
  16610.     ) is
  16611.  
  16612.     begin
  16613.  
  16614.     Space_Line(Paginated_Standard_Output,
  16615.            Count);
  16616.  
  16617.     end Space_Line;
  16618.  
  16619.  
  16620.     procedure Space_Line(
  16621.     File_Handle : in Paginated_File_Handle;
  16622.     Count       : in NATURAL := 1
  16623.     ) is
  16624.  
  16625. --|-Algorithm:
  16626. --| Validate paginated file structure (raise error if not valid)
  16627. --| Raise Invalid_Count if space request is too large
  16628. --| Write out the given number of new line control characters
  16629. --| while taking into account header, footer, and pagination.
  16630. --| Exit
  16631. --|+
  16632.  
  16633.     Handle : Paginated_File_Handle;
  16634.  
  16635.     begin
  16636.     
  16637.     Check_Valid(File_Handle);
  16638.     if Count = 0 then
  16639.         return;
  16640.     end if;
  16641.     Handle := File_Handle;
  16642.     loop
  16643.         exit when Handle = null;
  16644.         Line_Feed(Handle, Count);
  16645.         Handle := Handle.forward_link;
  16646.     end loop;
  16647.     return;
  16648.  
  16649.     end Space_Line;
  16650.                                                                     pragma page;
  16651.     procedure Skip_Line(
  16652.     Count       : in NATURAL := 1
  16653.     ) is
  16654.  
  16655.     begin
  16656.  
  16657.     Skip_Line(Paginated_Standard_Output,
  16658.           Count);
  16659.  
  16660.     end Skip_Line;
  16661.  
  16662.  
  16663.     procedure Skip_Line(
  16664.     File_Handle : in Paginated_File_Handle;
  16665.     Count       : in NATURAL := 1
  16666.     ) is
  16667.  
  16668. --|-Algorithm:
  16669. --| Validate paginated file structure (raise error if not valid)
  16670. --| Set the number of new line characters to be written as the
  16671. --| number specified or the number of lines remaining on the 
  16672. --| page which ever is smaller.
  16673. --| Write out this number of new line control characters
  16674. --| while taking into account header, footer, and pagination.
  16675. --| (If at the top of the page then Skip_Lines does nothing)
  16676. --| Exit
  16677. --|+
  16678.  
  16679.     Skip_Count : INTEGER;
  16680.     Handle     : Paginated_File_Handle;
  16681.  
  16682.     begin
  16683.     
  16684.     Check_Valid(File_Handle);
  16685.     if Count = 0 then
  16686.         return;
  16687.     end if;
  16688.     Handle := File_Handle;
  16689.     loop
  16690.         exit when Handle = null;
  16691.         if Handle.current_line /= 0 or Handle.page_size = 0 then
  16692.         Skip_Count := Handle.maximum_line - Handle.current_line + 1;
  16693.         if Skip_Count > Count or Handle.page_size = 0 then
  16694.             Skip_Count := Count;
  16695.         end if;
  16696.         Line_Feed(Handle, Skip_Count);
  16697.         end if;
  16698.         Handle := Handle.forward_link;
  16699.     end loop;
  16700.     return;
  16701.  
  16702.     end Skip_Line;
  16703.                                                                     pragma page;
  16704.     procedure Put_Page(
  16705.     Count       : in NATURAL := 1
  16706.     ) is
  16707.  
  16708.     begin
  16709.  
  16710.     Put_Page(Paginated_Standard_Output,
  16711.          Count);
  16712.  
  16713.     end Put_Page;
  16714.  
  16715.  
  16716.     procedure Put_Page(
  16717.     File_Handle : in Paginated_File_Handle;
  16718.     Count       : in NATURAL := 1
  16719.     ) is
  16720.  
  16721. --|-Algorithm:
  16722. --| Validate paginated file structure (raise error if not valid)
  16723. --| Raise Invalid_Count if page request is too large
  16724. --| Convert the number of pages to skip into number of lines  
  16725. --| Write out this number of new line control characters
  16726. --| while taking into account header, footer, and pagination.
  16727. --| Exit
  16728. --|+
  16729.  
  16730.     Handle : Paginated_File_Handle;
  16731.  
  16732.     begin
  16733.  
  16734.     Check_Valid(File_Handle);
  16735.     if Count = 0 then
  16736.         return;
  16737.     end if;
  16738.     Handle := File_Handle;
  16739.     loop
  16740.         exit when Handle = null;
  16741.         Page_Eject(Handle, Count);
  16742.         Handle := Handle.forward_link;
  16743.     end loop;
  16744.     return;
  16745.  
  16746.     end Put_Page;
  16747.                                                                     pragma page;
  16748.     function Available_Lines
  16749.     return NATURAL is
  16750.  
  16751.     begin
  16752.  
  16753.     return Available_Lines(Paginated_Standard_Output);
  16754.  
  16755.     end Available_Lines;
  16756.  
  16757.  
  16758.     function Available_Lines(
  16759.     File_Handle : in Paginated_File_Handle
  16760.     ) return NATURAL is
  16761.  
  16762. --|-Algorithm:
  16763. --| Validate paginated file structure (raise error if not valid)
  16764. --| Return the number of lines remaining on the page
  16765. --|+
  16766.  
  16767.     begin
  16768.  
  16769.     Check_Valid(File_Handle);
  16770.     if File_Handle.page_size = 0 then
  16771.         return 0;
  16772.     end if;
  16773.     if File_Handle.current_line = 0 then
  16774.         return File_Handle.maximum_line;
  16775.     else
  16776.         return File_Handle.maximum_line - File_Handle.current_line + 1;
  16777.     end if;
  16778.  
  16779.     end Available_Lines;
  16780.                                                                     pragma page;
  16781.     procedure Reserve_Lines(
  16782.     Count       : in NATURAL
  16783.     ) is
  16784.  
  16785.     begin
  16786.  
  16787.     Reserve_Lines(Paginated_Standard_Output,
  16788.               Count);
  16789.  
  16790.     end Reserve_Lines;
  16791.  
  16792.  
  16793.     procedure Reserve_Lines(
  16794.     File_Handle : in Paginated_File_Handle;
  16795.     Count       : in NATURAL
  16796.     ) is
  16797.  
  16798. --|-Algorithm:
  16799. --| Validate paginated file structure (raise error if not valid)
  16800. --| If the requested number of lines is greater than the page size
  16801. --|    then raise an error
  16802. --| If the requested is greater than the remaining space
  16803. --|    then eject page
  16804. --| Exit
  16805. --|+
  16806.  
  16807.     begin
  16808.  
  16809.     Check_Valid(File_Handle);
  16810.     if Count = 0 or File_Handle.page_size = 0 then
  16811.         return;
  16812.     end if;
  16813.     if Count > File_Handle.page_size then
  16814.         raise Page_Overflow;
  16815.     end if;
  16816.     if Count > Available_Lines(File_Handle) then
  16817.         Page_Eject(File_Handle, 1);
  16818.     end if;
  16819.     return;
  16820.  
  16821.     end Reserve_Lines;
  16822.                                                                     pragma page;
  16823. begin
  16824.  
  16825.     Create_Paginated_File("", Paginated_Standard_Output, 0, 0, 0);
  16826.  
  16827. end Paginated_Output;
  16828.                                                                     pragma page;
  16829. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16830. --SCANNERS.SPC
  16831. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16832. package scanners is    --| Scan tokens from strings
  16833.  
  16834. --| Overview
  16835. --| This package is used to break strings into tokens in a very simple
  16836. --| but efficient manner.  For maximum efficiency, the scanner type
  16837. --| is not private so that it can be used directly.  The following 
  16838. --| conventions are adopted to allow the Ada string handling primitives
  16839. --| to be used to maximum advantage:
  16840. --|-
  16841. --|  1. Strings are never copied.  The scanner type contains First and
  16842. --|     Last components so that slices may be used to obtain the desired
  16843. --|     tokens (substrings).
  16844. --| 
  16845. --|  2. The scanner type does not include a copy of the string being
  16846. --|     scanned, also to avoid copying strings.
  16847. --| 
  16848. --|  3. The Length component of a scanner is always set to the length of the
  16849. --|     item scanned.  If it is zero it means that no such item was found,
  16850. --|     either because it wasn't there or because the scanner is exhausted.
  16851. --|     The is_Empty operation may be used to determint if a scanner is
  16852. --|     exhausted (usually before attempting to scan something).
  16853. --| 
  16854. --|  4. All operations have well defined behavior for any consistent input.
  16855. --|     There are no exceptions declared in this package or raised directly
  16856. --|     by the operations in the package.
  16857. --|+
  16858.  
  16859.                   -- Types --
  16860.  
  16861. type scanner_type is 
  16862.   record
  16863.     Index: natural;    --| Index of next character to be scanned
  16864.     Max_Index: natural;    --| Index of last scannable character
  16865.     First: natural;    --| Index of first character of the result of a scan
  16866.     Last: Natural;    --| Index of last character of the result of a scan
  16867.     Length: Natural;    --| Length of the item scanned.
  16868.   end record;
  16869.  
  16870. ------------------------------------------------------------------------
  16871.  
  16872. procedure start_Scanner(        --| Initialize a scanner
  16873.     Scanner: in out Scanner_Type;    --| Scanner to be initialized
  16874.     S: in string;            --| String to be scanned
  16875.     Last: in natural            --| Last scannable character in S.
  16876.     );
  16877.  
  16878. --| Effects:  Initialize Scanner for scanning S.  S and Last are
  16879. --| typically obtained by calling text_io.Get_Line.  The first character
  16880. --| scanned will be S'First and the last character scanned will be Last,
  16881. --| which will generally be different from S'Last.
  16882.  
  16883. --| N/A: Requires, Modifies, Raises
  16884.  
  16885. ------------------------------------------------------------------------
  16886.  
  16887. function is_Empty(    --| Return False if Scanner can scan more characters
  16888.     Scanner: in Scanner_Type
  16889.     ) return boolean;
  16890. pragma inline(is_Empty);
  16891.  
  16892. --| Effects: Return True iff Scanner.Index > Scanner.Max_Index.
  16893. --| N/A: Requires, Modifies, Raises
  16894.  
  16895. ------------------------------------------------------------------------
  16896.  
  16897. function is_Alpha(    --| Check for alphabetic character
  16898.     Scanner: in scanner_Type;
  16899.     S: in string
  16900.     ) return boolean;
  16901. pragma inline(is_Alpha);
  16902.  
  16903. --| Effects: Return True iff S(Scanner.Index) is an alphabetic character.
  16904. --| Requires: Scanner must have been created on S using start start_Scanner
  16905. --| prior to calling this routine.
  16906.  
  16907. --| N/A: Modifies, Raises
  16908.  
  16909. ------------------------------------------------------------------------
  16910.  
  16911. function is_Digit(    --| Check for start of  unsigned number
  16912.     Scanner: in scanner_Type;
  16913.     S: in string
  16914.     ) return boolean;
  16915. pragma inline(is_Digit);
  16916.  
  16917. --| Effects: Return True iff S(Scanner.Index) is a decimal digit.
  16918. --| Requires: Scanner must have been created on S using start start_Scanner
  16919. --| prior to calling this routine.
  16920.  
  16921. --| N/A: Modifies, Raises
  16922.  
  16923. ------------------------------------------------------------------------
  16924.  
  16925. function is_Sign(    --| Check for '+' or '-'
  16926.     Scanner: in scanner_Type;
  16927.     S: in string
  16928.     ) return boolean;
  16929. pragma inline(is_Sign);
  16930.  
  16931. --| Effects: Return True iff S(Scanner.Index) is '+' or '-'
  16932. --| Requires: Scanner must have been created on S using start start_Scanner
  16933. --| prior to calling this routine.
  16934.  
  16935. --| N/A: Modifies, Raises
  16936.  
  16937. ------------------------------------------------------------------------
  16938.  
  16939. function is_Digit_or_Sign(    --| Check for start of optionally signed number
  16940.     Scanner: in scanner_Type;
  16941.     S: in string
  16942.     ) return boolean;
  16943. pragma inline(is_Digit_or_Sign);
  16944.  
  16945. --| Effects: Return True iff S(Scanner.Index) is '+', '-', or a decimal digit.
  16946. --| Requires: Scanner must have been created on S using start start_Scanner
  16947. --| prior to calling this routine.
  16948. --| N/A: Modifies, Raises
  16949.  
  16950. ------------------------------------------------------------------------
  16951.  
  16952. procedure skip_Blanks(    --| Skip leading blanks and tabs in S
  16953.     Scanner: in out Scanner_Type;    --| Scanner to be updated
  16954.     S: in string            --| String being scanned
  16955.     );
  16956.  
  16957. --| Effects: Increment Scanner.Index until S(Scanner.Index) is neither a
  16958. --| blank nor a tab character, or until it is greater than Scanner.Max_Index.
  16959.  
  16960. --| Requires: Scanner must have been created on S using start start_Scanner
  16961. --| prior to calling this routine.
  16962.  
  16963. --| N/A: Modifies, Raises
  16964.  
  16965. ------------------------------------------------------------------------
  16966.  
  16967. procedure trim_blanks(
  16968.     Scanner: in out Scanner_Type;
  16969.     S: in string
  16970.     );
  16971.  
  16972. --| Effects: Adjust Scanner.First and Scanner.Last such that 
  16973. --| S(Scanner.First..Scanner.Last) contains neither leading nor trailing
  16974. --| blanks or tabs.  Scanner.Length is adjusted accordingly.  This is
  16975. --| useful to remove blanks after a call to scan_Delimited, Scan_Quoted,
  16976. --| scan_Until, etc.
  16977.  
  16978. --| Requires: Scanner must have been created on S using start start_Scanner
  16979. --| prior to calling this routine.
  16980.  
  16981. --| N/A: Modifies, Raises
  16982.  
  16983. ------------------------------------------------------------------------
  16984.  
  16985. procedure scan_Until(    --| Scan up to but not including character C
  16986.     Scanner: in out Scanner_Type;
  16987.     S: in string;
  16988.     C: in character
  16989.     );
  16990.  
  16991. --| Effects: Scan in string S starting at Scanner.Index until the character
  16992. --| C is encountered or the string ends.  On return, if Scanner.Length > 0
  16993. --| then S(Scanner.First..Scanner.Last) contains the characters that
  16994. --| appeared before C and Scanner(Index) = C.  If C was not found, then
  16995. --| the scanner is not affected except to set Scanner.Length to 0.
  16996.  
  16997. --| Requires: Scanner must have been created on S using start start_Scanner
  16998. --| prior to calling this routine.
  16999.  
  17000. --| N/A: Modifies, Raises
  17001.  
  17002. ------------------------------------------------------------------------
  17003.  
  17004. procedure scan_Word(    --| Scan past a sequence of non-blank characters
  17005.     Scanner: in out Scanner_Type;
  17006.     S: in string
  17007.     );
  17008.  
  17009. --| Effects: Scan in string S for a sequence of non-blank characters,
  17010. --| starting at Scanner.Index.  On return, if Scanner.Length > 0
  17011. --| then S(Scanner.First..Scanner.Last) is a word and Scanner.Index is 
  17012. --| just past the end of the word (Scanner.Last+1), ready to scan the next
  17013. --| item.  
  17014.  
  17015. --| Requires: Scanner must have been created on S using start start_Scanner
  17016. --| prior to calling this routine.  The scanner must be at a non blank
  17017. --| character (the beginning of a word) or nothing will be scanned.
  17018.  
  17019. --| N/A: Modifies, Raises
  17020.  
  17021. ------------------------------------------------------------------------
  17022.  
  17023. procedure scan_Number(
  17024.     Scanner: in out scanner_Type;
  17025.     S: in string
  17026.     );
  17027.  
  17028. --| Effects: Scan in string S for a sequence of numeric characters,
  17029. --| optionally preceeded by a sign (+/-), starting at Scanner.Index.  On
  17030. --| return, if Scanner.Length > 0 then S(Scanner.First..Scanner.Last) is a
  17031. --| number and Scanner.Index is just past the end of the number
  17032. --| (Scanner.Last+1), ready to scan the next item.
  17033.  
  17034. --| Requires: Scanner must have been created on S using start start_Scanner
  17035. --| prior to calling this routine.  Scanner must be positioned at a digit
  17036. --| or sign (+/-) when this routine is called or nothing will be scanned.
  17037.  
  17038. --| N/A: Modifies, Raises
  17039.  
  17040. ------------------------------------------------------------------------
  17041.  
  17042. procedure scan_Delimited(    --| Scan string delimited by a single character
  17043.     Scanner: in out scanner_Type;
  17044.     S: in string
  17045.     );
  17046.  
  17047. --| Effects: The character S(Scanner.Index) is considered a "quote".  
  17048. --| Scanner.First is set to the Scanner.Index+1, and Scanner.Index is 
  17049. --| incremented until another "quote" is encountered or the end of the
  17050. --| string is reached.  On return, Scanner.Last is the index of the closing
  17051. --| "quote" or the last character in S if no closing "quote" was found.
  17052.  
  17053. --| Requires: Scanner must have been created on S using start start_Scanner
  17054. --| prior to calling this routine.
  17055. --| N/A: Modifies, Raises
  17056.  
  17057. ------------------------------------------------------------------------
  17058.  
  17059. procedure scan_Quoted(    --| Scan quoted string
  17060.     Scanner: in out scanner_Type;
  17061.     S: in out string
  17062.     );
  17063.  
  17064. --| Effects: The character S(Scanner.Index) is considered a "quote".  
  17065. --| The string S is scanned for a closing "quote".  During the scan,
  17066. --| two quotes in a row are replaced by a single quote.  On return,
  17067. --| Scanner.First is the first character of the quoted string, and
  17068. --| Scanner.Last is the last character.  (The outermost quotes are
  17069. --| not included.)  Scanner.Index is the first character after the
  17070. --| closing quote, Scanner.Length is the number of characters in the
  17071. --| quoted string.  Note that the string being scanned (S) is modified
  17072. --| by this routine (to remove the extra quotes, if any).
  17073.  
  17074. --| Requires: Scanner must have been created on S using start start_Scanner
  17075. --| prior to calling this routine.
  17076.  
  17077. --| N/A: Modifies, Raises
  17078.  
  17079. ------------------------------------------------------------------------
  17080.  
  17081. end scanners;
  17082. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17083. --SCANNERS.BDY
  17084. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17085. package body scanners is    --| Scan tokens from strings
  17086.  
  17087. ----------------------------------------------------------------------------
  17088. -- Local function specs:
  17089.  
  17090. function is_Space(C: Character) return boolean;
  17091. --| Return True iff C is a space or tab.
  17092. pragma inline(is_Space);
  17093.  
  17094. ----------------------------------------------------------------------------
  17095.  
  17096. procedure start_Scanner(    --| Initialize a scanner
  17097.     Scanner: in out Scanner_Type;    --| Scanner to be initialized
  17098.     S: in string;            --| String to be scanned
  17099.     Last: in natural            --| Last scannable character in S.
  17100.     )
  17101. is
  17102.  
  17103. begin
  17104.     Scanner.Index := S'First;
  17105.     Scanner.Max_Index := Last;
  17106.     Scanner.First := 1;
  17107.     Scanner.Last := 0;
  17108.     Scanner.Length := 0;
  17109.  
  17110. end start_Scanner;
  17111.  
  17112. ----------------------------------------------------------------------------
  17113.  
  17114. function is_Empty(    --| Return False if Scanner can scan more characters
  17115.     Scanner: in Scanner_Type
  17116.     ) return boolean is
  17117.  
  17118. begin
  17119.     return Scanner.Index > Scanner.Max_Index;
  17120.  
  17121. end is_Empty;
  17122.  
  17123. ----------------------------------------------------------------------------
  17124.  
  17125. function is_Alpha(    --| Check for alphabetic character
  17126.     Scanner: in scanner_Type;
  17127.     S: in string
  17128.     ) return boolean is
  17129.  
  17130. begin
  17131.     return Scanner.Index <= scanner.Max_Index and then 
  17132.        (S(Scanner.Index) in 'a'..'z' or else
  17133.        S(Scanner.Index) in 'A'..'Z');
  17134.  
  17135. end is_Alpha;
  17136.  
  17137. ----------------------------------------------------------------------------
  17138.  
  17139. function is_Digit(    --| Check for start of  unsigned number
  17140.     Scanner: in scanner_Type;
  17141.     S: in string
  17142.     ) return boolean is
  17143.  
  17144. begin
  17145.     return Scanner.Index <= scanner.Max_Index and then 
  17146.            S(Scanner.Index) in '0'..'9';
  17147.  
  17148. end is_Digit;
  17149.  
  17150. ----------------------------------------------------------------------------
  17151.  
  17152. function is_Sign(    --| Check for '+' or '-'
  17153.     Scanner: in scanner_Type;
  17154.     S: in string
  17155.     ) return boolean is
  17156.  
  17157. begin
  17158.     return Scanner.Index <= scanner.Max_Index and then 
  17159.        (S(Scanner.Index) = '+' or else S(Scanner.Index) = '-');
  17160.  
  17161. end is_Sign;
  17162.  
  17163. ----------------------------------------------------------------------------
  17164.  
  17165. function is_Digit_or_Sign(    --| Check for start of optionally signed number
  17166.     Scanner: in scanner_Type;
  17167.     S: in string
  17168.     ) return boolean is
  17169.  
  17170. begin
  17171.     return Scanner.Index <= scanner.Max_Index and then 
  17172.        (S(Scanner.Index) in '0'..'9'
  17173.        or else S(Scanner.Index) = '+' or else S(Scanner.Index) = '-');
  17174.  
  17175. end is_Digit_or_Sign;
  17176.  
  17177.  
  17178. ----------------------------------------------------------------------------
  17179.  
  17180. procedure skip_Blanks(    --| Skip leading blanks in S
  17181.     Scanner: in out Scanner_Type;    --| Scanner to be updated
  17182.     S: in string            --| String being scanned
  17183.     ) is
  17184.  
  17185. begin
  17186.     Scanner.First := Scanner.Index;
  17187.     Scanner.Length := 0;
  17188.     if Scanner.Index <= Scanner.Max_Index then
  17189.       while is_Space(S(Scanner.Index)) loop
  17190.     Scanner.Index := Scanner.Index + 1;
  17191.     exit when Scanner.Index > Scanner.Max_Index;
  17192.       end loop;
  17193.       Scanner.Length := Scanner.Index - Scanner.First;
  17194.     end if;
  17195.  
  17196. end skip_Blanks;
  17197.  
  17198. ----------------------------------------------------------------------------
  17199.  
  17200. procedure trim_blanks(
  17201.     Scanner: in out Scanner_Type;
  17202.     S: in string
  17203.     ) is
  17204. begin
  17205.     while Scanner.First < Scanner.Last and then is_Space(S(Scanner.First)) loop
  17206.     Scanner.First := Scanner.First + 1;
  17207.     end loop;
  17208.     while Scanner.Last >= Scanner.First and then is_Space(S(Scanner.Last)) loop
  17209.     Scanner.Last := Scanner.Last - 1;
  17210.     end loop;
  17211.     Scanner.Length := Scanner.Last - Scanner.First + 1;
  17212.  
  17213. end trim_Blanks;
  17214.  
  17215. ----------------------------------------------------------------------------
  17216.  
  17217. procedure scan_Until(    --| Scan until C is found
  17218.     Scanner: in out Scanner_Type;
  17219.     S: in string;
  17220.     C: in character
  17221.     )
  17222. is
  17223.     Index: natural := Scanner.Index;
  17224.  
  17225. begin
  17226.     Scanner.Length := 0;
  17227.     if Index <= Scanner.Max_Index then
  17228.       while S(Index) /= C loop
  17229.     Index := Index + 1;
  17230.     if Index > Scanner.Max_Index then    -- Didn't find C
  17231.       return;
  17232.     end if;
  17233.       end loop;
  17234.       Scanner.First := Scanner.Index;    -- First character scanned
  17235.       Scanner.Length := Index - Scanner.First;
  17236.       Scanner.Last := Index - 1;
  17237.       Scanner.Index := Index;
  17238.     end if;
  17239.  
  17240. end scan_Until;
  17241.  
  17242. ----------------------------------------------------------------------------
  17243.  
  17244. procedure scan_Word(    --| Scan past a sequence of non-blank characters
  17245.     Scanner: in out Scanner_Type;
  17246.     S: in string
  17247.     ) is
  17248.  
  17249. begin
  17250.     Scanner.First := Scanner.Index;
  17251.     Scanner.Last := Scanner.First - 1;
  17252.     Scanner.Length := 0;
  17253.     if Scanner.Index <= Scanner.Max_Index then
  17254.       while not is_Space(S(Scanner.Index)) loop
  17255.     Scanner.Index := Scanner.Index + 1;
  17256.     exit when Scanner.Index > Scanner.Max_Index;
  17257.       end loop;
  17258.       Scanner.Length := Scanner.Index - Scanner.First;
  17259.       Scanner.Last := Scanner.Index - 1;
  17260.     end if;
  17261.  
  17262. end scan_Word;
  17263.  
  17264. ----------------------------------------------------------------------------
  17265.  
  17266. procedure scan_Number(
  17267.     Scanner: in out scanner_Type;
  17268.     S: in string
  17269.     ) is
  17270.  
  17271. begin
  17272.     Scanner.First := Scanner.Index;
  17273.     if Scanner.Index <= Scanner.Max_Index then
  17274.       if S(Scanner.Index) = '-' or else S(Scanner.Index) = '+' then
  17275.     Scanner.Index := Scanner.Index + 1;
  17276.       end if;
  17277.       while Scanner.Index <= Scanner.Max_Index
  17278.         and then S(Scanner.Index) in '0'..'9'
  17279.       loop
  17280.     Scanner.Index := Scanner.Index + 1;
  17281.       end loop;
  17282.     end if;
  17283.     Scanner.Length := Scanner.Index - Scanner.First;
  17284.     Scanner.Last := Scanner.Index - 1;
  17285.  
  17286. end scan_Number;
  17287.  
  17288. ----------------------------------------------------------------------------
  17289.  
  17290. procedure scan_Delimited(    --| Scan string delimited by a single character
  17291.     Scanner: in out scanner_Type;
  17292.     S: in string
  17293.     )
  17294. is
  17295.     quote: character;
  17296.  
  17297. begin
  17298.     Scanner.First := Scanner.Index;
  17299.     if Scanner.Index <= Scanner.Max_Index then
  17300.     quote := S(Scanner.Index);
  17301.     Scanner.Index := Scanner.Index + 1;
  17302.     Scanner.First := Scanner.Index;
  17303.     while Scanner.Index <= Scanner.Max_Index 
  17304.           and then S(Scanner.Index) /= quote
  17305.     loop
  17306.       Scanner.Index := Scanner.Index + 1;
  17307.     end loop;
  17308.     end if;
  17309.     Scanner.Length := Scanner.Index - Scanner.First;
  17310.     Scanner.Last := Scanner.Index - 1;
  17311.     if Scanner.Index <= Scanner.Max_Index
  17312.     and then S(Scanner.Index) = quote then    -- Null string?
  17313.     Scanner.Index := Scanner.Index + 1;
  17314.     end if;
  17315.  
  17316. end scan_Delimited;
  17317.  
  17318. ----------------------------------------------------------------------------
  17319.  
  17320. procedure scan_Quoted(    --| Scan quoted string
  17321.     Scanner: in out scanner_Type;
  17322.     S: in out string
  17323.     )
  17324. is
  17325.     quote: character;
  17326.     di: natural;
  17327.  
  17328. begin
  17329.     Scanner.First := Scanner.Index;
  17330.     di := Scanner.Index;
  17331.     if Scanner.Index <= Scanner.Max_Index then
  17332.     quote := S(Scanner.Index);
  17333.     Scanner.Index := Scanner.Index + 1;
  17334.     Scanner.First := Scanner.Index;
  17335.     di := scanner.Index;
  17336.     while Scanner.Index <= Scanner.Max_Index loop
  17337.        if S(Scanner.Index) = quote then    -- Closing quote?
  17338.         if Scanner.Index < Scanner.Max_Index
  17339.         and then S(Scanner.Index + 1) = quote then    -- Doubled quote?
  17340.         Scanner.Index := Scanner.Index + 1;    -- skip it
  17341.         else
  17342.         exit;    -- Found closing quote at Scanner.Index
  17343.         end if;
  17344.       end if;
  17345.       S(di) := S(Scanner.Index);
  17346.       Scanner.Index := Scanner.Index + 1;
  17347.       di := di + 1;
  17348.     end loop;
  17349.     end if;
  17350.     Scanner.Length := di - Scanner.First;
  17351.     Scanner.Last := di - 1;
  17352.     Scanner.Index := Scanner.Index + 1;    -- Skip closing quote
  17353.  
  17354. end scan_Quoted;
  17355.  
  17356. ----------------------------------------------------------------------------
  17357. -- Local function bodies:
  17358.  
  17359. function is_Space(C: Character) return boolean is
  17360. --| Return True iff C is a space or tab.
  17361. begin
  17362.     return C = ' ' or else C = ASCII.HT;
  17363.  
  17364. end is_Space;
  17365.  
  17366. ----------------------------------------------------------------------------
  17367.  
  17368. end scanners;
  17369. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17370. --STRING.BDY
  17371. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17372. -- $Source: /nosc/work/abstractions/string/RCS/string.bdy,v $
  17373. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:58:51 $ -- $Author: ron $
  17374.  
  17375. -- $Source: /nosc/work/abstractions/string/RCS/string.bdy,v $
  17376. -- $Revision: 1.3 $ -- $Date: 85/02/01 10:58:51 $ -- $Author: ron $
  17377.  
  17378. with unchecked_deallocation;
  17379. with lists, stack_pkg;
  17380. with case_insensitive_string_comparison;
  17381.  
  17382. package body string_pkg is
  17383.  
  17384. --| Overview:
  17385. --| The implementation for most operations is fairly straightforward.
  17386. --| The interesting aspects involve the allocation and deallocation of
  17387. --| heap space.  This is done as follows:
  17388. --|
  17389. --|     1. A stack of accesses to lists of string_type values is set up
  17390. --|        so that the top of the stack always refers to a list of values
  17391. --|        that were allocated since the last invocation of mark.
  17392. --|        The stack is called scopes, referring to the dynamic scopes
  17393. --|        defined by the invocations of mark and release.
  17394. --|        There is an implicit invocation of mark when the
  17395. --|        package body is elaborated; this is implemented with an explicit 
  17396. --|        invocation in the package initialization code.
  17397. --|
  17398. --|     2. At each invocation of mark, a pointer to an empty list
  17399. --|        is pushed onto the stack.
  17400. --|
  17401. --|     3. At each invocation of release, all of the values in the
  17402. --|        list referred to by the pointer at the top of the stack are
  17403. --|        returned to the heap.  Then the list, and the pointer to it,
  17404. --|        are returned to the heap.  Finally, the stack is popped.
  17405.  
  17406.     package CISC renames case_insensitive_string_comparison;
  17407.  
  17408.     package string_list_pkg is new lists(string_type);
  17409.     subtype string_list is string_list_pkg.list;
  17410.  
  17411.     type string_list_ptr is access string_list;
  17412.  
  17413.     package scope_stack_pkg is new stack_pkg(string_list_ptr);
  17414.     subtype scope_stack is scope_stack_pkg.stack;
  17415.  
  17416.     use string_list_pkg;
  17417.     use scope_stack_pkg;
  17418.  
  17419.     scopes: scope_stack;     -- See package body overview.
  17420.  
  17421.     current_comparison_option: comparison_option := case_sensitive;
  17422.  
  17423.     -- Utility functions/procedures:
  17424.  
  17425.     function enter(s: string_type)
  17426.         return string_type;
  17427.  
  17428.       --| Raises: illegal_alloc
  17429.       --| Effects:
  17430.       --| Stores s, the address of s.all, in current scope list (top(scopes)),
  17431.       --| and returns s.  Useful for functions that create and return new
  17432.       --| string_type values.
  17433.       --| Raises illegal_alloc if the scopes stack is empty.
  17434.  
  17435.     function string_lower(s: string)
  17436.     return string;
  17437.  
  17438.       --| Effects:
  17439.       --| Return a string with the same bounds and contents as s, with the
  17440.       --| exception that all upper case characters are replaced with their
  17441.       --| lower case counterparts.
  17442.  
  17443.     function string_upper(s: string)
  17444.     return string;
  17445.  
  17446.       --| Effects:
  17447.       --| Return a string with the same bounds and contents as s, with the
  17448.       --| exception that all lower case characters are replaced with their
  17449.       --| upper case counterparts.
  17450.  
  17451.     function string_equal(s1, s2: string)
  17452.     return boolean;
  17453.  
  17454.       --| Effects: 
  17455.       --| If current_comparison_option = case_sensitive, then return 
  17456.       --| (s1 = s2); otherwise, return string_lower(s1) = string_lower(s2).
  17457.  
  17458.     function string_less(s1, s2: string)
  17459.     return boolean;
  17460.  
  17461.       --| Effects: 
  17462.       --| If current_comparison_option = case_sensitive, then return 
  17463.       --| (s1 < s2); otherwise, return string_lower(s1) < string_lower(s2).
  17464.  
  17465.     function string_less_or_equal(s1, s2: string)
  17466.     return boolean; 
  17467.  
  17468.       --| Effects: 
  17469.       --| If current_comparison_option = case_sensitive, then return 
  17470.       --| (s1 <= s2); otherwise, return string_lower(s1) <= string_lower(s2).
  17471.  
  17472.     function match_string(s1, s2: string; start: positive := 1)
  17473.         return natural;
  17474.  
  17475.       --| Raises: no_match
  17476.       --| Effects:
  17477.       --| Returns the minimum index, i, in s1'range such that
  17478.       --| s1(i..i + s2'length - 1) = s2.  Returns 0 if no such index.
  17479.       --| Requires:
  17480.       --| s1'first = 1.
  17481.  
  17482. -- Constructors:
  17483.  
  17484.     function create(s: string)
  17485.         return string_type is
  17486.         subtype constr_str is string(1..s'length);
  17487.         dec_s: constr_str := s;
  17488.     begin
  17489.           return enter(new constr_str'(dec_s));
  17490.     end create;
  17491.  
  17492.  
  17493.     function "&"(s1, s2: string_type)
  17494.         return string_type is
  17495.     begin
  17496.     if is_empty(s1) then return enter(make_persistent(s2)); end if;
  17497.     if is_empty(s2) then return enter(make_persistent(s1)); end if; 
  17498.         return create(s1.all & s2.all);
  17499.     end "&";
  17500.  
  17501.     function "&"(s1: string_type; s2: string)
  17502.         return string_type is
  17503.     begin
  17504.     if s1 = null then return create(s2); end if; 
  17505.     return create(s1.all & s2); 
  17506.     end "&";
  17507.  
  17508.     function "&"(s1: string; s2: string_type)
  17509.         return string_type is
  17510.     begin
  17511.     if s2 = null then return create(s1); end if; 
  17512.     return create(s1 & s2.all); 
  17513.     end "&";
  17514.     
  17515.     function substr(s: string_type; i: positive; len: natural)
  17516.         return string_type is
  17517.     begin
  17518.         if len = 0 then return null; end if; 
  17519.         return create(s(i..(i + len - 1)));
  17520.     exception
  17521.     when constraint_error =>      -- on array fetch or null deref
  17522.         raise bounds;
  17523.     end substr;
  17524.  
  17525.     function splice(s: string_type; i: positive; len: natural)
  17526.         return string_type is
  17527.     begin
  17528.         if len = 0 then return enter(make_persistent(s)); end if;
  17529.         if i + len - 1 > length(s) then raise bounds; end if; 
  17530.  
  17531.         return create(s(1..(i - 1)) & s((i + len)..length(s)));
  17532.     end splice;
  17533.  
  17534.     function insert(s1, s2: string_type; i: positive)
  17535.         return string_type is
  17536.     begin
  17537.         if i > length(s1) + 1 then raise bounds; end if;
  17538.  
  17539.     if s1 = null then return create(value(s2)); end if;
  17540.     if s2 = null then return create(s1.all); end if;
  17541.  
  17542.         return create(s1(1..(i - 1)) & s2.all & s1(i..s1'last));
  17543.     end insert;
  17544.  
  17545.     function insert(s1: string_type; s2: string; i: positive)
  17546.         return string_type is
  17547.     begin
  17548.         if i > length(s1) + 1 then raise bounds; end if;
  17549.     if s1 = null then return create(s2); end if;
  17550.  
  17551.         return create(s1(1..(i - 1)) & s2 & s1(i..s1'last));
  17552.     end insert;
  17553.  
  17554.     function insert(s1: string; s2: string_type; i: positive)
  17555.         return string_type is
  17556.     begin
  17557.     if i not in s1'first..s1'last + 1 then raise bounds; end if;
  17558.     if s2 = null then return create(s1); end if; 
  17559.  
  17560.         return create(s1(s1'first..(i - 1)) & s2.all & s1(i..s1'last));
  17561.     end insert;
  17562.  
  17563.     function lower(s: string)
  17564.     return string_type is  
  17565.     begin
  17566.     return create(string_lower(s));
  17567.     end lower;
  17568.  
  17569.     function lower(s: string_type)
  17570.     return string_type is
  17571.     begin
  17572.     if s = null then return null; end if; 
  17573.     return create(string_lower(s.all));
  17574.     end lower;
  17575.  
  17576.     function upper(s: string)
  17577.     return string_type is
  17578.     begin
  17579.     return create(string_upper(s));
  17580.     end upper;
  17581.  
  17582.     function upper(s: string_type)
  17583.     return string_type is
  17584.     begin
  17585.     if s = null then return null; end if; 
  17586.     return create(string_upper(s.all));
  17587.     end upper;
  17588.       
  17589.     
  17590. -- Heap Management:
  17591.  
  17592.     function make_persistent(s: string_type)
  17593.     return string_type is
  17594.         subtype constr_str is string(1..length(s));
  17595.     begin
  17596.         if s = null or else s.all = "" then return null;
  17597.         else return new constr_str'(s.all);
  17598.         end if; 
  17599.     end make_persistent; 
  17600.     
  17601.     function make_persistent(s: string)
  17602.     return string_type is
  17603.         subtype constr_str is string(1..s'length);
  17604.         dec_s: constr_str := s;
  17605.     begin
  17606.     if dec_s = "" then return null; 
  17607.         else return new constr_str'(dec_s); end if; 
  17608.     end make_persistent; 
  17609.  
  17610.     procedure real_flush is new unchecked_deallocation(string,
  17611.                                                        string_type);
  17612.       --| Effect:
  17613.       --| Return space used by argument to heap.  Does nothing if null.
  17614.       --| Notes:
  17615.       --| This procedure is actually the body for the flush procedure,
  17616.       --| but a generic instantiation cannot be used as a body for another
  17617.       --| procedure.  You tell me why.
  17618.  
  17619.     procedure flush(s: in out string_type) is
  17620.     begin
  17621.         if s /= null then real_flush(s); end if;
  17622.         -- Actually, the if isn't needed; however, DECada compiler chokes
  17623.         -- on deallocation of null.
  17624.     end flush;
  17625.  
  17626.     procedure mark is
  17627.     begin
  17628.         push(scopes, new string_list'(create));
  17629.     end mark;
  17630.  
  17631.     procedure release is
  17632.         procedure flush_list_ptr is
  17633.             new unchecked_deallocation(string_list, string_list_ptr);
  17634.         iter: string_list_pkg.ListIter;
  17635.         top_list: string_list_ptr;
  17636.         s: string_type;
  17637.     begin
  17638.         pop(scopes, top_list);
  17639.         iter := MakeListIter(top_list.all);
  17640.         while more(iter) loop
  17641.             next(iter, s);
  17642.             flush(s);             -- real_flush is bad, DECada bug
  17643. --          real_flush(s);            
  17644.         end loop;
  17645.         destroy(top_list.all);
  17646.         flush_list_ptr(top_list);
  17647.     exception
  17648.         when empty_stack =>
  17649.             raise illegal_dealloc;
  17650.     end release;
  17651.     
  17652.     
  17653. -- Queries:
  17654.  
  17655.     function is_empty(s: string_type)
  17656.         return boolean is
  17657.     begin
  17658.         return (s = null) or else (s.all = "");
  17659.     end is_empty;
  17660.  
  17661.     function length(s: string_type)
  17662.         return natural is
  17663.     begin
  17664.     if s = null then return 0; end if; 
  17665.         return(s.all'length);
  17666.     end length;
  17667.  
  17668.     function value(s: string_type)
  17669.         return string is
  17670.         subtype null_range is positive range 1..0;
  17671.         subtype null_string is string(null_range);
  17672.     begin
  17673.     if s = null then return null_string'(""); end if; 
  17674.         return s.all;
  17675.     end value;
  17676.  
  17677.     function fetch(s: string_type; i: positive)
  17678.         return character is
  17679.     begin
  17680.     if is_empty(s) or else (i not in s'range) then raise bounds; end if; 
  17681.         return s(i);
  17682.     end fetch;
  17683.  
  17684.     procedure set_comparison_option(choice: comparison_option) is
  17685.     begin
  17686.     current_comparison_option := choice; 
  17687.     end set_comparison_option;
  17688.  
  17689.     function get_comparison_option
  17690.     return comparison_option is
  17691.     begin
  17692.     return current_comparison_option; 
  17693.     end get_comparison_option;
  17694.  
  17695.     function equal(s1, s2: string_type)
  17696.         return boolean is
  17697.     begin
  17698.         if is_empty(s1) then return is_empty(s2); end if; 
  17699.         return (s2 /= null) and then string_equal(s1.all, s2.all);
  17700.     end equal;
  17701.  
  17702.     function equal(s1: string_type; s2: string)
  17703.         return boolean is
  17704.     begin
  17705.     if s1 = null then return s2 = ""; end if;
  17706.         return string_equal(s1.all, s2);
  17707.     end equal;
  17708.  
  17709.     function equal(s1: string; s2: string_type)
  17710.         return boolean is
  17711.     begin
  17712.     if s2 = null then return s1 = ""; end if;
  17713.         return string_equal(s1, s2.all);
  17714.     end equal;
  17715.  
  17716.     function "<"(s1, s2: string_type)
  17717.         return boolean is
  17718.     begin
  17719.         if is_empty(s1) then
  17720.         return (not is_empty(s2));
  17721.     else
  17722.         return (s1.all < s2);
  17723.     end if; 
  17724.     end "<";
  17725.  
  17726.     function "<"(s1: string_type; s2: string)
  17727.         return boolean is 
  17728.     begin
  17729.     if s1 = null then return s2 /= ""; end if; 
  17730.         return string_less(s1.all, s2);
  17731.     end "<";
  17732.  
  17733.     function "<"(s1: string; s2: string_type)
  17734.         return boolean is 
  17735.     begin
  17736.     if s2 = null then return false; end if; 
  17737.         return string_less(s1, s2.all);
  17738.     end "<";
  17739.  
  17740.     function "<="(s1, s2: string_type)
  17741.         return boolean is 
  17742.     begin
  17743.     if is_empty(s1) then return true; end if; 
  17744.     return (s1.all <= s2); 
  17745.     end "<=";
  17746.  
  17747.     function "<="(s1: string_type; s2: string)
  17748.         return boolean is 
  17749.     begin
  17750.     if s1 = null then return true; end if; 
  17751.         return string_less_or_equal(s1.all, s2);
  17752.     end "<=";
  17753.  
  17754.     function "<="(s1: string; s2: string_type)
  17755.         return boolean is 
  17756.     begin
  17757.     if s2 = null then return s1 = ""; end if; 
  17758.         return string_less_or_equal(s1, s2.all); 
  17759.     end "<=";
  17760.  
  17761.     function match_c(s: string_type; c: character; start: positive := 1)
  17762.         return natural is
  17763.     begin
  17764.     if s = null then return 0; end if; 
  17765.         for i in start..s.all'last loop
  17766.             if s(i) = c then
  17767.                 return i;
  17768.             end if;
  17769.         end loop;
  17770.         return 0;
  17771.     end match_c;
  17772.  
  17773.     function match_not_c(s: string_type; c: character; start: positive := 1)
  17774.         return natural is
  17775.     begin
  17776.     if s = null then return 0; end if; 
  17777.         for i in start..s.all'last loop
  17778.         if s(i) /= c then
  17779.         return i;
  17780.         end if;
  17781.         end loop;
  17782.     return 0;
  17783.     end match_not_c;
  17784.  
  17785.     function match_s(s1, s2: string_type; start: positive := 1)
  17786.         return natural is
  17787.     begin
  17788.     if (s1 = null) or else (s2 = null) then return 0; end if; 
  17789.         return match_string(s1.all, s2.all, start);
  17790.     end match_s;
  17791.  
  17792.     function match_s(s1: string_type; s2: string; start: positive := 1)
  17793.         return natural is
  17794.     begin
  17795.     if s1 = null then return 0; end if; 
  17796.         return match_string(s1.all, s2, start);
  17797.     end match_s;
  17798.  
  17799.     function match_any(s, any: string_type; start: positive := 1)
  17800.         return natural is
  17801.     begin
  17802.     if any = null then raise any_empty; end if; 
  17803.         return match_any(s, any.all, start);
  17804.     end match_any;
  17805.  
  17806.     function match_any(s: string_type; any: string; start: positive := 1)
  17807.         return natural is
  17808.     begin
  17809.         if any = "" then raise any_empty; end if;
  17810.         if s = null then return 0; end if;
  17811.  
  17812.         for i in start..s.all'last loop
  17813.             for j in any'range loop
  17814.                 if s(i) = any(j) then
  17815.                     return i;
  17816.                 end if;
  17817.             end loop;
  17818.         end loop;
  17819.         return 0;
  17820.     end match_any;
  17821.  
  17822.     function match_none(s, none: string_type; start: positive := 1)
  17823.         return natural is
  17824.     begin
  17825.     if is_empty(s) then return 0; end if; 
  17826.     if is_empty(none) then return 1; end if; 
  17827.  
  17828.         return match_none(s, none.all, start);
  17829.     end match_none;
  17830.  
  17831.     function match_none(s: string_type; none: string; start: positive := 1)
  17832.         return natural is
  17833.         found: boolean;
  17834.     begin
  17835.     if is_empty(s) then return 0; end if; 
  17836.  
  17837.         for i in start..s.all'last loop
  17838.             found := true;
  17839.             for j in none'range loop
  17840.                 if s(i) = none(j) then
  17841.                     found := false;
  17842.                     exit;
  17843.                 end if;
  17844.             end loop;
  17845.             if found then return i; end if;
  17846.         end loop;
  17847.         return 0;
  17848.     end match_none;
  17849.  
  17850.  
  17851.     -- Utilities:
  17852.  
  17853.     function enter(s: string_type)
  17854.         return string_type is
  17855.     begin
  17856.         top(scopes).all := attach(top(scopes).all, s);
  17857.         return s;
  17858.     exception
  17859.         when empty_stack =>
  17860.             raise illegal_alloc;
  17861.     end enter;
  17862.  
  17863.     function string_lower(s: string)
  17864.     return string is  
  17865.  
  17866.     begin
  17867.     return CISC.downCase(S);
  17868.  
  17869.     end string_lower; 
  17870.  
  17871.     function string_upper(s: string)
  17872.     return string is
  17873.  
  17874.     begin
  17875.     return CISC.upCase(S);
  17876.  
  17877.     end string_upper; 
  17878.  
  17879.     function string_equal(s1, s2: string)
  17880.     return boolean is
  17881.     begin
  17882.     if current_comparison_option = case_sensitive then
  17883.         return s1 = s2;
  17884.     else
  17885.         return CISC.equal(S1, S2);
  17886.     end if;
  17887.  
  17888.     end string_equal;
  17889.  
  17890.     function string_less(s1, s2: string)
  17891.     return boolean is
  17892.     begin
  17893.     if current_comparison_option = case_sensitive then 
  17894.         return s1 < s2;
  17895.     else
  17896.         return CISC.less(S1, S2);
  17897.     end if;
  17898.  
  17899.     end string_less;
  17900.  
  17901.     function string_less_or_equal(s1, s2: string)
  17902.     return boolean is
  17903.     begin
  17904.     if current_comparison_option = case_sensitive then 
  17905.         return s1 <= s2;
  17906.     else
  17907.         return CISC.less_or_equal(S1, S2);
  17908.     end if;
  17909.  
  17910.     end string_less_or_equal;
  17911.  
  17912.     function match_string(s1, s2: string; start: positive := 1)
  17913.         return natural is
  17914.         offset: natural;
  17915.     begin
  17916.         offset := s2'length - 1;
  17917.         for i in start..(s1'last - offset) loop
  17918.             if s1(i..(i + offset)) = s2 then
  17919.                 return i;
  17920.             end if;
  17921.         end loop;
  17922.         return 0; 
  17923.     exception when constraint_error =>    -- on offset := s2'length (= 0)
  17924.         return 0; 
  17925.     end match_string;
  17926.  
  17927.  
  17928. begin    -- Initialize the scopes stack with an implicit mark.
  17929.     scopes := create;
  17930.     mark;
  17931. end string_pkg;
  17932.  
  17933.  
  17934. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17935. --TERMIO.SPC
  17936. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  17937. -------------------------------------------------------------------------------
  17938. with HOST_LIB;
  17939.  
  17940. package Terminal_IO is 
  17941. --| Video terminal input/output for various kinds of terminals
  17942.  
  17943. --| Overview
  17944. --| This package provides a set of functions for interacting with
  17945. --| a video terminal.  The terminal type is specified in a call to
  17946. --| Initialize.  All output is to the file STANDARD_OUTPUT.  All input
  17947. --| is from the file STANDARD_INPUT.
  17948. --| 
  17949. --|-For output, three functions are provided:
  17950. --| 
  17951. --|   clear_line()    Clears from the cursor to the end of line
  17952. --|   clear_screen()    Clears from the cursor to the end of screen 
  17953. --|   set_cursor(R, C)     Place cursor at row R, column C
  17954. --| 
  17955. --| For input, two functions are provided:
  17956. --| 
  17957. --|   read()        Reads a line from the terminal, with echo
  17958. --|   blind_read()    Reads a line from the terminal without echo
  17959. --| 
  17960. --| The following queries are provided:
  17961. --| 
  17962. --|   max_row()        Returns the number of rows on the screen
  17963. --|   max_column()    Returns the number of columns on the screen
  17964.  
  17965. --|-Notes
  17966.  
  17967. --| 1. This package is designed to be as simple as possible.  Functionality
  17968. --|    is limited to the "lowest common denominator".
  17969. --| 
  17970. --| 2. Since TEXT_IO is used for output of data, this package cannot
  17971. --|    track the cursor position at all times.  Since many terminals cannot
  17972. --|    report the current cursor position, no query for the current cursor
  17973. --|    position is provided.  Users should position the cursor immediately
  17974. --|    before reading from or writing to the terminal.
  17975.  
  17976. -------------------------------------------------------------------------------
  17977.  
  17978. Unsupported_Terminal : exception;
  17979. --| Raised if initialize called with an unsupported terminal type.
  17980.  
  17981. End_of_File_Error    : exception;
  17982. --| Raised if End_Error is raised while reading from the terminal.
  17983.  
  17984. subtype Terminal_Type is host_lib.Terminal_Type;
  17985.  
  17986. ---------------------------------------------------------------------------
  17987. -- Initialization (and finalization?) --
  17988. ---------------------------------------------------------------------------
  17989.  
  17990. procedure Initialize(    --| Initialize the terminal
  17991.     Terminal: in Terminal_Type
  17992.     ); --| Raises: Unsupported_Terminal.
  17993.  
  17994.  
  17995. --| Effects: Sets the terminal type for subsequent operations to terminal
  17996. --| type.  If Terminal denotes a terminal for which the remaining functions 
  17997. --| in this package cannot be or are not supported, the exception
  17998. --| Unsupported_Terminal is raised.
  17999.  
  18000. ---------------------------------------------------------------------------
  18001. -- Output primitives --
  18002. ---------------------------------------------------------------------------
  18003.  
  18004. procedure Clear_Line;
  18005. --| Clear from the cursor to the end of the current line, inclusive.
  18006.  
  18007. --| Effects: Clears from the cursor to the end of the current line, 
  18008. --| inclusive.
  18009.  
  18010. --| N/A: Raises, Requires, Modifies, Errors
  18011.  
  18012. ---------------------------------------------------------------------------
  18013.  
  18014. procedure Clear_Screen;
  18015. --| Clear the screen from current cursor position.
  18016.  
  18017. --| Effects: Clears the screen starting at the current cursor
  18018. --| position to the end of the screen, inclusive.
  18019.  
  18020. --| N/A: Raises, Requires, Modifies, Errors
  18021.  
  18022. ---------------------------------------------------------------------------
  18023.  
  18024. procedure Set_Cursor(  --| Move the cursor
  18025.     Row: in positive;
  18026.     Column: in positive
  18027.     );
  18028.  
  18029. --| Effects:  Positions the cursor at the line and column specified
  18030. --| by (Row, Column).  (1, 1) is the upper left corner of the screen.
  18031. --| If Row or Column is beyond the edge of the screen, the cursor is
  18032. --| placed at the last row and/or column.
  18033.  
  18034. --| N/A: Raises, Requires, Modifies, Errors
  18035.  
  18036. ---------------------------------------------------------------------------
  18037. -- Input Primitives --
  18038. ---------------------------------------------------------------------------
  18039.  
  18040. function read        --| Read a line from the terminal
  18041.     return STRING;
  18042.     --| Raises: End_of_File_Error
  18043.  
  18044. --| Effects: A line of text is read from the file STANDARD_INPUT.
  18045. --| Characters are echoed as they are typed, and any line-editing
  18046. --| functions supported by the host OS (eg. backspace) may be used.
  18047. --| End_of_File_Error is raised if End_Error is raised while reading.
  18048.  
  18049. --| N/A: Requires, Modifies, Errors
  18050.  
  18051.  
  18052. function blind_read    --| Read a line from the terminal with no echo
  18053.     return STRING;
  18054.     --| Raises: End_of_File_Error
  18055.  
  18056. --| Effects: A line of text is read from the file STANDARD_INPUT.
  18057. --| Characters are NOT echoed as they are typed, but any line-editing
  18058. --| functions supported by the host OS (eg. backspace) may be used.
  18059. --| End_of_File_Error is raised if End_Error is raised while reading.
  18060.  
  18061. --| N/A: Requires, Modifies, Errors
  18062.  
  18063. ---------------------------------------------------------------------------
  18064. -- Queries --
  18065. ---------------------------------------------------------------------------
  18066.  
  18067. function max_row    --| Return the number of rows on the screen
  18068.     return positive;
  18069.  
  18070. --| Effects: Return the number of lines available on the current terminal.
  18071. --| N/A: Raises, Requires, Modifies, Errors
  18072.  
  18073. function max_column    --| Return the number of columns on the screen
  18074.     return positive;
  18075.  
  18076. --| Effects: Return the number of columns available on the current terminal.
  18077. --| N/A: Raises, Requires, Modifies, Errors
  18078.  
  18079. ---------------------------------------------------------------------------
  18080.  
  18081. end Terminal_IO; 
  18082.  
  18083. ---------------------------------------------------------------------------
  18084. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18085. --TERMIO.BDY
  18086. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18087. -------------------------------------------------------------------------------
  18088.  
  18089. with string_pkg; use string_pkg;
  18090. with TEXT_IO; use TEXT_IO;
  18091.  
  18092. package body Terminal_IO is 
  18093. --| Video terminal input/output for various kinds of terminals
  18094.  
  18095. -------------------------------------------------------------------------------
  18096.  
  18097. use ASCII;
  18098. use host_Lib;
  18099.  
  18100. type Internal_Terminal_Type is (VT100_like, VT52_like, UNSUPPORTED);
  18101. --| All terminals this package knows about internally
  18102.  
  18103. subtype supported_Terminals is Internal_Terminal_Type 
  18104.     range VT100_like .. VT52_like;
  18105.  
  18106. type Terminal_Type_Array is array (Terminal_Type) of Internal_Terminal_Type;
  18107.  
  18108. terminal_Equivalance_array: Terminal_Type_Array := Terminal_Type_Array'(
  18109.   VT52 => VT52_like,
  18110.   VT100 | VT101 | VT102 | VT105 | VT125 | VT131 | VT132 | VT200_SERIES
  18111.     => VT100_like,
  18112.   others => UNSUPPORTED
  18113.   );
  18114.  
  18115. type terminal_descriptor is record
  18116.     max_rows: positive;        --| Number of rows on screen
  18117.     max_cols: positive;        --| Number of columns on screen
  18118.     clear_line: string_type;    --| Code sequence to clear to end of line
  18119.     clear_screen: string_type;    --| Code sequence to clear to end of string
  18120.     motion_prefix: string_type;    --| Initial code sequence for moving cursor
  18121.     -- Cursor positioning depends on both terminal type and (R, C) and is
  18122.     -- difficult to encode.
  18123. end record;
  18124.  
  18125. subtype input_string_range is positive range 1..256;
  18126.  
  18127. terminal_descriptions: 
  18128.   array (Supported_Terminals) of terminal_descriptor := (
  18129.     VT100_Like => (
  18130.     max_rows => 24, 
  18131.     max_cols => 80,
  18132.     clear_line => Create(esc & "[K"),
  18133.     clear_screen => Create(esc & "[J"),
  18134.     motion_prefix => Create(esc & "[")
  18135.     ),
  18136.     VT52_Like => (
  18137.     max_rows => 24, 
  18138.     max_cols => 80,
  18139.     clear_line => Create(esc & "K"),
  18140.     clear_screen => Create(esc & "J"),
  18141.     motion_prefix => Create(esc & "Y")
  18142.     )
  18143.     );
  18144.  
  18145. current_terminal: internal_terminal_type := VT100_Like;
  18146. --| Current terminal type
  18147.  
  18148. ---------------------------------------------------------------------------
  18149. -- Local subprograms --
  18150. ---------------------------------------------------------------------------
  18151.  
  18152. procedure Send(S: string_type) is
  18153. --| Send a string to the terminal
  18154.  
  18155. begin
  18156.   PUT(value(S));
  18157. end Send;
  18158.  
  18159. procedure Send(S: string) is
  18160. --| Send a string to the terminal
  18161.  
  18162. begin
  18163.   PUT(S);
  18164. end Send;
  18165.  
  18166. procedure Send(C: character) is
  18167. --| Send a single character to the terminal
  18168.  
  18169. begin
  18170.   PUT(C);
  18171. end Send;
  18172.  
  18173. ---------------------------------------------------------------------------
  18174. -- Initialization (and finalization?) --
  18175. ---------------------------------------------------------------------------
  18176.  
  18177. procedure Initialize(Terminal: in Terminal_Type) is
  18178. --| Sets terminal to terminal type
  18179.  
  18180. begin
  18181.  
  18182.   if terminal_Equivalance_array(Terminal) = UNSUPPORTED then
  18183.     raise Unsupported_Terminal;
  18184.   end if;
  18185.   current_terminal :=  terminal_Equivalance_array(Terminal);
  18186.  
  18187. end Initialize;
  18188.  
  18189. ---------------------------------------------------------------------------
  18190. -- Output primitives --
  18191. ---------------------------------------------------------------------------
  18192.  
  18193. procedure Clear_Line is
  18194. --| Clears from the cursor to the end of the current line, inclusive.
  18195. --| N/A: Raises, Requires, Modifies, Errors
  18196.  
  18197. begin
  18198.  
  18199.   send(terminal_descriptions(current_terminal).clear_line); 
  18200.  
  18201. end clear_line;
  18202.  
  18203. ---------------------------------------------------------------------------
  18204.  
  18205. procedure Clear_Screen is
  18206. --| Clears the screen from current cursor position.
  18207. --| N/A: Raises, Requires, Modifies, Errors
  18208.  
  18209. begin
  18210.  
  18211.   send(terminal_descriptions(current_terminal).clear_screen); 
  18212.  
  18213. end clear_screen;
  18214.  
  18215. ---------------------------------------------------------------------------
  18216.  
  18217. procedure Set_Cursor(  --| Move the cursor
  18218.     Row: in positive;
  18219.     Column: in positive
  18220.     ) is
  18221.  
  18222. --| N/A: Raises, Requires, Modifies, Errors
  18223.  
  18224.  
  18225. begin
  18226.  
  18227.   send(terminal_descriptions(current_terminal).motion_prefix); 
  18228.   case current_terminal is
  18229.     when VT100_Like =>
  18230.     send(positive'image(Row)(2..positive'image(Row)'last));
  18231.     send(';');
  18232.     send(positive'image(Column)(2..positive'image(Column)'last));
  18233.     send(";f");
  18234.     when VT52_Like =>
  18235.     send(character'val(character'pos(' ') - 1 + Row));
  18236.     send(character'val(character'pos(' ') - 1 + Column));
  18237.     when others =>
  18238.         null;
  18239.   end case;
  18240.    
  18241. end set_cursor;
  18242.  
  18243. ---------------------------------------------------------------------------
  18244. -- Input Primitives --
  18245. ---------------------------------------------------------------------------
  18246.  
  18247. function read        --| Read a line from the terminal
  18248.     return STRING is
  18249.     --| Raises: End_of_File_Error
  18250.  
  18251. --| N/A: Requires, Modifies, Errors
  18252.  
  18253.   S: string(input_string_range);
  18254.   L: natural;
  18255.  
  18256. begin
  18257.  
  18258.   get_line(S, L);
  18259.   return S(S'First..L);
  18260.  
  18261. exception
  18262.  
  18263.   when End_Error =>
  18264.     raise End_of_File_Error;
  18265.   when Use_Error =>
  18266.     return "";
  18267.  
  18268. end read;
  18269.  
  18270. function blind_read    --| Read a line from the terminal with no echo
  18271.     return STRING is
  18272.     --| Raises: End_of_File_Error
  18273.  
  18274. --| N/A: Requires, Modifies, Errors
  18275.  
  18276. begin
  18277.  
  18278.   return HOST_LIB.Read_No_Echo;
  18279.  
  18280. exception
  18281.  
  18282.     when End_Error =>
  18283.       raise End_of_File_Error;
  18284.     when Use_Error =>
  18285.       return "";
  18286.  
  18287. end blind_read;
  18288.  
  18289. ---------------------------------------------------------------------------
  18290. -- Queries --
  18291. ---------------------------------------------------------------------------
  18292.  
  18293. function max_row    --| Return the number of rows on the screen
  18294.     return positive is
  18295. --| N/A: Raises, Requires, Modifies, Errors
  18296.  
  18297. begin
  18298.  
  18299.   return terminal_descriptions(current_terminal).max_rows; 
  18300.  
  18301. end max_row;
  18302.  
  18303. function max_column    --| Return the number of columns on the screen
  18304.     return positive is
  18305. --| N/A: Raises, Requires, Modifies, Errors
  18306.  
  18307. begin
  18308.  
  18309.   return terminal_descriptions(current_terminal).max_cols; 
  18310.  
  18311. end max_column;
  18312.  
  18313. ---------------------------------------------------------------------------
  18314.  
  18315. end Terminal_IO; 
  18316.  
  18317. ---------------------------------------------------------------------------
  18318. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18319. --ILISTS.SPC
  18320. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18321. with Lists;
  18322.  
  18323. package Integer_Lists is new Lists(
  18324.         ItemType => INTEGER);
  18325.  
  18326. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18327. --SINTF.SPC
  18328. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18329. with String_Pkg;
  18330. with String_Lists;
  18331. with Integer_Lists;
  18332. with Lists;
  18333. with Paginated_Output;
  18334.  
  18335. package Standard_Interface is        --| Standard interface package
  18336.  
  18337. --| Overview
  18338. --| This package is used to:
  18339. --|-
  18340. --|   1. parse a line of arguments expressed in Ada (valid Ada is accepted but
  18341. --|      may not be required depending on the set of switches defined below)
  18342. --|   2. create a paginated output file with a standardized header and/or footer
  18343. --|      text(s) and page size
  18344. --|+
  18345. --| Given a specification of the arguments to be parsed, the subprogram
  18346. --| Parse_Line parses a given line.  If there were errors, they are reported*
  18347. --| on the current output and a description* of valid input is given and
  18348. --| Abort_Process exception is raised.  If there are no errors, the process
  18349. --| and argument(s) are echoed* to current output using named parameter
  18350. --| associations, showing the values of every parameter, even those that were
  18351. --| defaulted.  A prompt* is given to continue with the process or to abort by
  18352. --| raising Abort_Process exception.
  18353. --|-
  18354. --|    * : These operations are controlled by switches
  18355. --|+
  18356. --| If Parse_Line is successful (returns TRUE), a subprogram Get_Argument may
  18357. --| be called to obtain the value of an argument by its named association.
  18358. --| Six types of arguments are supported :
  18359. --| integer, string, enumeration, list of integers, list of strings, and list
  18360. --| of enumeration values.
  18361. --|
  18362. --| Generic package Command_Line is provided for parsing an enumerated set
  18363. --| of commands and their corresponding arguments.
  18364. --|
  18365. --| Generic packages Enumerated_Argument, Emunerated_List_Argument,
  18366. --| Integer_Argument, Integer_List_Argument, and String_List_Argument
  18367. --| are provided for arguments which are enumeration type, list of enumeration
  18368. --| type, integer subtype (ie. range), list of integer subtype, and list of
  18369. --| string type, respectively.  These package must be instantiated with proper
  18370. --| types to obtain the appropriate subprograms for a given type.
  18371. --|
  18372. --| The subprogram Define_Output returns a paginated file handle to be used for
  18373. --| subsequent output operations, or will create a paginated output file and
  18374. --| set the current paginated output file to be the specified file.
  18375. --|
  18376. --|
  18377. --| The syntax of a process is specified by providing the following information: 
  18378. --|-
  18379. --|   1. Name of the process
  18380. --|   2. General help pertaining to this process (optional)
  18381. --|   3. For each argument
  18382. --|      a. Name - a string
  18383. --|      b. Help - a string (optional)
  18384. --|      c. Default value - type of argument being defined (optional)
  18385. --|   4. Any other text to appear in the help message (optional)
  18386. --|+
  18387.                                                                     pragma page;
  18388. --| Notes:
  18389. --|-
  18390. --|      The format of the standard header is :
  18391. --|
  18392. --|           +------------------------- // -------------------------+
  18393. --|           |            (intentionally left blank)                |
  18394. --|           +------------------------- // -------------------------+
  18395. --|           | Standard Header (ie. Name, Date, Time, Page)         |
  18396. --|           +------------------------- // -------------------------+
  18397. --|           | User Defined Non-standard Header 1                   |
  18398. --|           +------------------------- // -------------------------+
  18399. --|           |                                                      |
  18400. --|           -                                                      -
  18401. --|           |                                                      |
  18402. --|           +------------------------- // -------------------------+
  18403. --|           | User Defined Non-standard Header n                   |
  18404. --|           +------------------------- // -------------------------+
  18405. --|           |            (intentionally left blank)                |
  18406. --|           +------------------------- // -------------------------+
  18407. --|           | (First line of text)                                 |
  18408. --|           |                                                      |
  18409. --|
  18410. --|                 where n may be 0 to 9
  18411. --|+
  18412. --| Goals
  18413. --|- 1. It should be easy to write the definition of a command line
  18414. --|  2. It should be easy for the user to type commands
  18415. --|  3. It should accept valid Ada (but not require it)
  18416. --|  4. Handle ALL aspects of parsing, reporting errors, etc.
  18417. --|  5. Use not limited to command line parsing
  18418. --|+
  18419.                                                                     pragma page;
  18420. ----------------------------------------------------------------
  18421.  
  18422. package SL renames String_Lists;
  18423.  
  18424. package SP renames String_Pkg;
  18425.  
  18426. package IL renames Integer_Lists;
  18427.  
  18428. package PO renames Paginated_Output;
  18429.  
  18430. ----------------------------------------------------------------
  18431.  
  18432. type Process_Handle is limited private;
  18433.             --| Holds all command and parameter information
  18434. subtype Size is INTEGER range 0 .. 9;
  18435.             --| Non standard header size
  18436. subtype Number is INTEGER range 1 .. Size'last;
  18437.             --| Non standard header number
  18438. type Switch is (ON, OFF);
  18439.             --| Switch (boolean) variable
  18440.  
  18441. type Parsing_Checks is (    --| Parsing switches
  18442.     Ending_Delimiter,
  18443.     Argument_Enclosure,
  18444.     Quote_Enclosure );
  18445.  
  18446. type Action_Checks is (        --| Action switches
  18447.     Show_Help,
  18448.     Show_Error,
  18449.     Show_Help_on_Error,
  18450.     Echo_Command,
  18451.     Prompt_for_Reply );
  18452.  
  18453. type Command_Checks is (    --| Command action switches
  18454.     Show_Help,
  18455.     Show_Error,
  18456.     Show_Help_on_Null,
  18457.     Show_Help_on_Error);
  18458.  
  18459. -----------------------   Parsing Switches   -----------------------------------
  18460.  
  18461. Parsing_Switches : array (Parsing_Checks) of Switch :=
  18462.  
  18463.     --| The elements of the Parsing_Switches may be changed to control
  18464.     --| parsing actions.  Setting these switches OFF will relax parsing
  18465.     --| stipulations but may result in ambiguities.
  18466.  
  18467.     (Ending_Delimiter   => ON,    --| Check for ending delimiter
  18468.      Argument_Enclosure => ON,    --| Check for enclosing charactrers
  18469.      Quote_Enclosure    => ON);    --| Check strings enclosing quotes
  18470.  
  18471. -----------------------   Action Switches   ------------------------------------
  18472.  
  18473. Action_Switches  : array (Action_Checks) of Switch :=
  18474.  
  18475.     --| The elements of the Action_Switches may be changed to control
  18476.     --| actions taken by the standard interface.
  18477.  
  18478.     (Show_Help          => ON,    --| Display help message if no argument(s)
  18479.      Show_Error         => ON,    --| Display message on detecting error(s)
  18480.      Show_Help_on_Error => ON,    --| Display Help message on error(s)
  18481.      Echo_Command       => ON,    --| Echo arguments
  18482.      Prompt_for_Reply   => OFF);    --| Prompt to continue/abort
  18483.  
  18484. -----------------------   Command Switches   -----------------------------------
  18485.  
  18486. Command_Switches  : array (Command_Checks) of Switch :=
  18487.  
  18488.     --| The elements of the Command_Switches may be changed to control
  18489.     --| actions taken by the standard interface command parser.
  18490.  
  18491.     (Show_Help          => ON,    --| Display command help message
  18492.      Show_Error         => ON,    --| Display message on detecting error(s)
  18493.      Show_Help_on_Null  => OFF,    --| Display help when no command is entered
  18494.      Show_Help_on_Error => OFF);    --| Display help message on command error
  18495.  
  18496. -----------------------   Parsing Strings   ------------------------------------
  18497.  
  18498. Delimiter : SP.String_Type :=        --| Argument seperator
  18499.     SP.Make_Persistent(",");
  18500.  
  18501. --| Delimiter string defines a set of characters that are recognized as
  18502. --| argument delimiters. 
  18503. --| To change the delimiter characters
  18504. --|     SP.Flush(Delimiter);                    -- free storage
  18505. --|     Delimiter := SP.Make_Persistent("|/");  -- | and / as a delimiters
  18506. --| The default delimiter character is ","
  18507.  
  18508. Assignment : SP.String_Type :=        --| Assignment string
  18509.     SP.Make_Persistent("=>");
  18510.  
  18511. --| Assignment string defines a string that is recognized as an assigment
  18512. --| indicator.  To change the assigment string follow procedures shown
  18513. --| for changing delimiter characters.
  18514. --| The default assignment string is "=>"
  18515.  
  18516. Left_Enclosure  : CHARACTER := '(';    --| Argument/list left enclosure
  18517.  
  18518. Right_Enclosure : CHARACTER := ')';    --| Argument/list right enclosure
  18519.  
  18520. End_Delimiter   : CHARACTER := ';';    --| Ending delimiter
  18521.  
  18522. --| Left_Enclosure, Right_Enclosure, and End_Delimiter may be changed by
  18523. --| simple character assigment.  The defaults are "(", ")", and ";" respectively
  18524.  
  18525. ----------------------------------------------------------------
  18526.  
  18527. Duplicate_Name    : exception;    --| Raised if an attempt is made to define
  18528.                 --| an existing argument 
  18529. Invalid_Name      : exception;    --| Raised if the specified name (prcoess or
  18530.                 --| argument) is not an Ada identifier
  18531. Undefined_Name    : exception;    --| Raised if attempt is made to obtain the
  18532.                 --| value of an argument that was not defined
  18533. Uninitialized     : exception;    --| Raised if operation is attempted with an
  18534.                 --| uninitialized handle
  18535. Already_Exists    : exception;    --| Raised if a handle to be assigned is
  18536.                 --| already initialized
  18537. Invalid_Kind      : exception;    --| Raised if information sought is not
  18538.                 --| pertinent to the named argument
  18539. Not_Yet_Parsed    : exception;    --| Raised if information is sought before
  18540.                 --| (command) line is parsed
  18541. Already_Parsed    : exception;    --| Raised if attempt is made to define an
  18542.                 --| object after (command) line is parsed
  18543. Invalid_Type      : exception;    --| Raised if the integer subtype instantiation
  18544.                 --| is invalid
  18545. Abort_Process     : exception;    --| Raised if error(s) is detected or abort is
  18546.                 --| requested (via reply to a prompt)
  18547. Process_Help      : exception;    --| Raised if the Help message is printed 
  18548.                 --| (by other than error conditions)
  18549. No_Default        : exception;    --| Raised if a request is made for a default
  18550.                 --| value where non was defined
  18551. Abort_Command     : exception;    --| Raised if command error(s) is detected
  18552.  
  18553. Command_Help      : exception;    --| Raised if the predefined HELP command is
  18554.                 --| entered
  18555. Command_Exit      : exception;    --| Raised if the predefined EXIT command is
  18556.                 --| entered
  18557. No_Command        : exception;    --| Raised if no command is entered 
  18558.  
  18559. Identifier_Error  : exception;    --| Tool identifier has not been set or
  18560.                 --| set more than once
  18561. Internal_Error    : exception;    --| Raised for internal errors
  18562.                                                                     pragma page;
  18563. ----------------------------------------------------------------
  18564.  
  18565. procedure Set_Tool_Identifier(        --| Set identifier
  18566.     Identifier : in STRING        --| Identifier string
  18567.     );
  18568.     --| Raises: Identifier_Error
  18569.  
  18570. --| Effects:
  18571. --| Sets the tool identifier to be displayed in the help message.
  18572.  
  18573. ----------------------------------------------------------------
  18574.  
  18575. function Get_Tool_Identifier        --| Get identifier
  18576.     return STRING;
  18577.     --| Raises: Identifier_Error
  18578.  
  18579. --| Effects:
  18580. --| Gets the tool identifier.
  18581.  
  18582. ----------------------------------------------------------------
  18583.  
  18584. procedure Define_Process(        --| Define a process
  18585.     Name    : in     STRING;        --| Process name
  18586.     Help    : in     STRING;        --| Explanation of process
  18587.     Proc    : in out Process_Handle    --| Process handle
  18588.     );
  18589.     --| Raises: Already_Exists, Invalid_Name, Already_Parsed, Identifier_Error
  18590.  
  18591. --| Effects:
  18592. --| Defines the name of the process for use in displaying help or echoing
  18593. --| the actual parameters.  Return value is the internal representation
  18594. --| of the process definition.
  18595.  
  18596. ----------------------------------------------------------------
  18597.  
  18598. procedure Redefine_Process(        --| Redefine a process
  18599.     Proc : in Process_Handle        --| Process handle
  18600.     );
  18601.     --| Raises: Uninitialized
  18602.  
  18603. --| Effects:
  18604. --| Re-defines the process after parsing so that another line may be parsed
  18605. --| using the same process handle
  18606.  
  18607. ----------------------------------------------------------------
  18608.  
  18609. procedure Undefine_Process(        --| Delete process structure
  18610.     Proc : in out Process_Handle    --| Process handle
  18611.     );
  18612.  
  18613. --| Effects:
  18614. --| Deletes the process and its associated argument definitions and frees
  18615. --| storage used.
  18616.  
  18617. ----------------------------------------------------------------
  18618.  
  18619. procedure Define_Process_Name(        --| Provide general help
  18620.     Proc    : in Process_Handle;    --| Process being defined
  18621.     Name    : in STRING            --| Process name
  18622.     );
  18623.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  18624.  
  18625. --| Effects:
  18626. --| Override current process name in the internal process representatio
  18627.  
  18628. ----------------------------------------------------------------
  18629.  
  18630. procedure Define_Process_Help(        --| Provide general help
  18631.     Proc : in Process_Handle;        --| Process being defined
  18632.     Help : in STRING
  18633.     );
  18634.     --| Raises: Uninitialized, Already_Parsed
  18635.  
  18636. --| Effects:
  18637. --| Define Help message internally stored for output if errors are
  18638. --| detected.
  18639.  
  18640. ----------------------------------------------------------------
  18641.  
  18642. procedure Append_Process_Help(        --| Provide general help
  18643.     Proc : in Process_Handle;        --| Process being defined
  18644.     Help : in STRING
  18645.     );
  18646.     --| Raises: Uninitialized, Already_Parsed
  18647.  
  18648. --| Effects:
  18649. --| Appends to the Help message internally stored
  18650.  
  18651. ----------------------------------------------------------------
  18652.  
  18653. procedure Define_Help(            --| Provide general help
  18654.     Proc : in Process_Handle;        --| Process being defined
  18655.     Help : in STRING
  18656.     );
  18657.     --| Raises: Uninitialized, Already_Parsed
  18658.  
  18659. --| Effects:
  18660. --| Define general Help message for output in the help message
  18661.  
  18662. ----------------------------------------------------------------
  18663.  
  18664. procedure Append_Help(            --| Provide general help
  18665.     Proc : in Process_Handle;        --| Process being defined
  18666.     Help : in STRING
  18667.     );
  18668.     --| Raises: Uninitialized, Already_Parsed
  18669.  
  18670. --| Effects:
  18671. --| Appends to the general Help message internally stored.
  18672.  
  18673. ----------------------------------------------------------------
  18674.  
  18675. procedure Parse_Line(            --| Parse the command line arguments
  18676.     Proc : in Process_Handle        --| Porcess defined
  18677.     );
  18678.     --| Raises: Uninitialized, Already_Parsed, Abort_Process, Process_Help
  18679.  
  18680. --| Effects:
  18681. --| Parse the commmand line according the process specification given by the
  18682. --| process handle.
  18683. --| Error message, help message, echoing, and/or prompt depends on the switches.
  18684. --| If any errors are detected (regardless of the above switches) Abort_Process
  18685. --| exception will be raised.
  18686. --|
  18687. --| Errors
  18688. --| The following errors are detected:
  18689. --|-
  18690. --|  1. Invalid command line syntax (eg. missing semicolon)
  18691. --|  2. Wrong type of argument supplied
  18692. --|  3. Required argument missing
  18693. --|  3. Value not in range (for integer and enumeration types)
  18694. --|+
  18695.  
  18696. ----------------------------------------------------------------
  18697.  
  18698. procedure Parse_Line(            --| Parse the line arguments
  18699.     Proc : in Process_Handle;        --| Process being defined
  18700.     Line : in STRING            --| Parameters to be parsed
  18701.     );
  18702.     --| Raises: Uninitialized, Already_Parsed, Abort_Process, Process_Help
  18703.  
  18704. --| Effects:
  18705. --| Parse the given line according the process specification given by the
  18706. --| process handle.
  18707. --| Error message, help message, echoing, and/or prompt depends on the switches.
  18708. --| If any errors are detected (regardless of the above switches) Abort_Process
  18709. --| exception will be raised.
  18710. --|
  18711. --| Errors
  18712. --| The following errors are detected:
  18713. --|-
  18714. --|  1. Invalid line syntax (eg. missing semicolon)
  18715. --|  2. Wrong type of argument supplied
  18716. --|  3. Required argument missing
  18717. --|  3. Value not in range (for integer and enumeration types)
  18718. --|+
  18719.  
  18720. ----------------------------------------------------------------
  18721.  
  18722. procedure Show_Help(
  18723.     Proc : in Process_Handle
  18724.     );
  18725.     --| Raises: Uninitialized
  18726.  
  18727. --| Effects:
  18728. --| Outputs the general Help message.
  18729.  
  18730. ----------------------------------------------------------------
  18731.  
  18732. procedure Echo_Process(
  18733.     Proc : in Process_Handle
  18734.     );
  18735.  
  18736.     --| Raises: Uninitialized, Not_Yet_Parsed
  18737.  
  18738. --| Effects:
  18739. --| Outputs the "echo" of the process arguments.
  18740.  
  18741. ----------------------------------------------------------------
  18742.  
  18743. function Continue(
  18744.     Proc : in Process_Handle
  18745.     ) return BOOLEAN;
  18746.  
  18747.     --| Raises: Uninitialized, Not_Yet_Parsed
  18748.  
  18749. --| Effects:
  18750. --| Prompts for a reply to continue or abort.
  18751. --| Returns TRUE if the reply was to continue, FALSE otherwise.
  18752.  
  18753. ----------------------------------------------------------------
  18754.  
  18755. procedure Define_Output(        --| Define paginated output
  18756.     Proc        : in Process_Handle;    --| Process handle
  18757.     File_Name   : in STRING;        --| File name
  18758.     Header_Size : in Size := 0;        --| Size of the user defined header
  18759.     Paginate    : in BOOLEAN := TRUE    --| Pagination switch
  18760.     );
  18761.     --| Raises: Paginated_Output.File_Already_Open, Paginated_Output.File_Error,
  18762.     --|         Paginated_Output.Page_Layout_Error;
  18763.  
  18764. --| Effects:
  18765. --| Create a paginated output file with File_Name and set paginated standard
  18766. --| output to this file
  18767.  
  18768. ----------------------------------------------------------------
  18769.  
  18770. procedure Define_Output(        --| Define paginated output
  18771.     Proc        : in     Process_Handle;--| Process handle
  18772.     File_Name   : in     STRING;    --| File name
  18773.     Header_Size : in     Size := 0;    --| Size of the user defined header
  18774.     File_Handle : in out PO.Paginated_File_Handle;
  18775.                     --| Handle to paginated file
  18776.     Paginate    : in     BOOLEAN := TRUE--| Pagination switch
  18777.     );
  18778.     --| Raises: Paginated_Output.File_Already_Open, Paginated_Output.File_Error,
  18779.     --|         Paginated_Output.Page_Layout_Error;
  18780.  
  18781. --| Effects:
  18782. --| Create a paginated output file with File_Name and return a handle
  18783.  
  18784. ----------------------------------------------------------------
  18785.  
  18786. procedure Define_Header(        --| Define non standard header
  18787.     Line : in Number;            --| Line number of the header
  18788.     Text : in STRING            --| Header text
  18789.     );
  18790.     --| Raises: Paginated_Output.Invalid_File, Paginated_Output.Text_Overflow,
  18791.  
  18792. --| Effects:
  18793. --| Defines the Line'th line of the non standard header.
  18794.  
  18795. ----------------------------------------------------------------
  18796.  
  18797. procedure Define_Header(        --| Define non standard header
  18798.     File_Handle : in PO.Paginated_File_Handle;
  18799.                     --| Handle to paginated file
  18800.     Line        : in Number;        --| Line number of the header
  18801.     Text        : in STRING        --| Header text
  18802.     );
  18803.     --| Raises: Paginated_Output.Invalid_File, Paginated_Output.Text_Overflow,
  18804.  
  18805. --| Effects:
  18806. --| Defines the Line'th line of the non standard header.
  18807.  
  18808. ----------------------------------------------------------------
  18809.                                                                     pragma page;
  18810. generic
  18811.  
  18812.     type Enum_Type is (<>);
  18813.     Enum_Type_Name : STRING;
  18814.  
  18815. package Enumerated_Argument is
  18816.  
  18817. ----------------------------------------------------------------
  18818.  
  18819.     procedure Define_Argument(        --| Define an input argument
  18820.     Proc    : in Process_Handle;    --| Process being defined
  18821.     Name    : in STRING;        --| Name of the argument
  18822.     Help    : in STRING        --| Explanation of the argument
  18823.     );
  18824.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  18825.  
  18826.     --| Effects:
  18827.     --| Each time this procedure is called, it defines a new
  18828.     --| process argument; the first call defines the first argument,
  18829.     --| the second the second argument, etc.  Exceptions are raised if
  18830.     --| a duplicate name is defined.
  18831.  
  18832. ----------------------------------------------------------------
  18833.  
  18834.     procedure Define_Argument(        --| Define an input argument
  18835.     Proc    : in Process_Handle;    --| Process being defined
  18836.     Name    : in STRING;        --| Name of the argument
  18837.     Default : in Enum_Type;        --| Default value
  18838.     Help    : in STRING        --| Explanation of the argument
  18839.     );
  18840.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  18841.  
  18842.     --| Effects:
  18843.     --| Each time this procedure is called, it defines a new
  18844.     --| process argument; the first call defines the first argument,
  18845.     --| the second the second argument, etc.  Exceptions are raised if
  18846.     --| a duplicate name is defined.
  18847.  
  18848. ----------------------------------------------------------------
  18849.  
  18850.     procedure Define_Argument_Help(    --| Provide general help
  18851.     Proc : in Process_Handle;    --| Process handle
  18852.     Name : in STRING;        --| Argument being defined
  18853.     Help : in STRING        --| Help string
  18854.     );
  18855.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  18856.  
  18857.     --| Effects:
  18858.     --| Store Help message for the argument
  18859.  
  18860. ----------------------------------------------------------------
  18861.  
  18862.     procedure Append_Argument_Help(    --| Provide general help
  18863.     Proc : in Process_Handle;    --| Process handle
  18864.     Name : in STRING;        --| Argument being defined
  18865.     Help : in STRING        --| Help string
  18866.     );
  18867.     --| Raises: Uninitialized, Undefined_Name, Already_Parsed
  18868.  
  18869.     --| Effects:
  18870.     --| Append to the Help message associated with the argument.
  18871.  
  18872. ----------------------------------------------------------------
  18873.  
  18874.     function Get_Argument(        --| Return the specified argument
  18875.     Proc : in Process_Handle;    --| Definition of the process
  18876.     Name : in STRING        --| Name of the desired argument
  18877.     ) return Enum_Type;
  18878.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind
  18879.  
  18880.     --| Effects:
  18881.     --| Return an argument value from the argument called Name on the command
  18882.     --| line (or the default value if no value was supplied).
  18883.  
  18884. ----------------------------------------------------------------
  18885.  
  18886.     function Get_Default(        --| Return the default for specified
  18887.                     --| argument if one exists
  18888.     Proc : in Process_Handle;    --| Definition of the process
  18889.     Name : in STRING        --| Name of the desired argument
  18890.     ) return Enum_Type;
  18891.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind,
  18892.     --|        No_Default
  18893.  
  18894.     --| Effects:
  18895.     --| Return the default value from the argument called Name
  18896.     --| An exception is raised if no default was defined for the argument.
  18897.  
  18898. ----------------------------------------------------------------
  18899.  
  18900.     function Defaulted(            --| Return defaulted/specified status
  18901.     Proc : in     Process_Handle;    --| Definition of the process
  18902.     Name : in     STRING        --| Name of the desired argument
  18903.     ) return BOOLEAN;
  18904.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed
  18905.  
  18906.     --| Effects:
  18907.     --| Return a boolean indication TRUE if the value is defaulted
  18908.     --| FALSE if specified
  18909.  
  18910. ----------------------------------------------------------------
  18911.  
  18912. end Enumerated_Argument;
  18913.                                                                     pragma page;
  18914. generic
  18915.  
  18916.     type Enum_Type is (<>);
  18917.     Enum_Type_Name : STRING;
  18918.     Enum_Type_List : STRING;
  18919.  
  18920. package Enumerated_List_Argument is
  18921.  
  18922.     package Enumerated_Lists is new Lists(Enum_Type);
  18923.     package EL renames Enumerated_Lists;
  18924.  
  18925.     type Enum_Type_Array is array (POSITIVE range <>) of Enum_Type;
  18926.  
  18927. ----------------------------------------------------------------
  18928.  
  18929.     procedure Define_Argument(        --| Define an input argument
  18930.     Proc    : in Process_Handle;    --| Process being defined
  18931.     Name    : in STRING;        --| Name of the argument
  18932.     Help    : in STRING        --| Explanation of the argument
  18933.     );
  18934.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  18935.  
  18936.     --| Effects:
  18937.     --| Each time this procedure is called, it defines a new
  18938.     --| process argument; the first call defines the first argument,
  18939.     --| the second the second argument, etc.  Exceptions are raised if
  18940.     --| a duplicate name is defined.
  18941.  
  18942. ----------------------------------------------------------------
  18943.  
  18944.     procedure Define_Argument(        --| Define an input argument
  18945.     Proc    : in Process_Handle;    --| Process being defined
  18946.     Name    : in STRING;        --| Name of the argument
  18947.     Default : in Enum_Type_Array;    --| Default value
  18948.     Help    : in STRING        --| Explanation of the argument
  18949.     );
  18950.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  18951.  
  18952.     --| Effects:
  18953.     --| Each time this procedure is called, it defines a new
  18954.     --| process argument; the first call defines the first argument,
  18955.     --| the second the second argument, etc.  Exceptions are raised if
  18956.     --| a duplicate name is defined.
  18957.  
  18958. ----------------------------------------------------------------
  18959.  
  18960.     procedure Define_Argument_Help(    --| Provide general help
  18961.     Proc : in Process_Handle;    --| Process handle
  18962.     Name : in STRING;        --| Argument being defined
  18963.     Help : in STRING        --| Help string
  18964.     );
  18965.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  18966.  
  18967.     --| Effects:
  18968.     --| Store Help message for the argument
  18969.  
  18970. ----------------------------------------------------------------
  18971.  
  18972.     procedure Append_Argument_Help(    --| Provide general help
  18973.     Proc : in Process_Handle;    --| Process handle
  18974.     Name : in STRING;        --| Argument being defined
  18975.     Help : in STRING        --| Help string
  18976.     );
  18977.     --| Raises: Uninitialized, Undefined_Name, Already_Parsed
  18978.  
  18979.     --| Effects:
  18980.     --| Append to the Help message associated with the argument.
  18981.  
  18982. ----------------------------------------------------------------
  18983.  
  18984.     function Get_Argument(        --| Return the specified argument
  18985.     Proc : in Process_Handle;    --| Definition of the command
  18986.     Name : in STRING        --| Name of the desired argument
  18987.     ) return EL.List;
  18988.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind
  18989.  
  18990.     --| Effects:
  18991.     --| Return an argument value from the argument called Name on the command
  18992.     --| line (or the default value if no value was supplied).
  18993.  
  18994. ----------------------------------------------------------------
  18995.  
  18996.     function Get_Default(        --| Return the default for specified
  18997.                     --| argument if one exists
  18998.     Proc : in Process_Handle;    --| Definition of the process
  18999.     Name : in STRING        --| Name of the desired argument
  19000.     ) return EL.List;
  19001.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind,
  19002.     --|        No_Default
  19003.  
  19004.     --| Effects:
  19005.     --| Return the default value from the argument called Name
  19006.     --| An exception is raised if no default was defined for the argument.
  19007.  
  19008. ----------------------------------------------------------------
  19009.  
  19010.     function Defaulted(            --| Return defaulted/specified status
  19011.     Proc : in     Process_Handle;    --| Definition of the process
  19012.     Name : in     STRING        --| Name of the desired argument
  19013.     ) return BOOLEAN;
  19014.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed
  19015.  
  19016.     --| Effects:
  19017.     --| Return a boolean indication TRUE if the value is defaulted
  19018.     --| FALSE if specified
  19019.  
  19020. ----------------------------------------------------------------
  19021.  
  19022. end Enumerated_List_Argument;
  19023.                                                                     pragma page;
  19024. generic
  19025.  
  19026.     type Integer_Type is range <>;
  19027.     Integer_Type_Name : STRING;
  19028.  
  19029. package Integer_Argument is
  19030.  
  19031. ----------------------------------------------------------------
  19032.  
  19033.     procedure Define_Argument(        --| Define an input argument
  19034.     Proc    : in Process_Handle;    --| Process being defined
  19035.     Name    : in STRING;        --| Name of the argument
  19036.     Help    : in STRING        --| Explanation of the argument
  19037.     );
  19038.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19039.  
  19040.     --| Effects:
  19041.     --| Each time this procedure is called, it defines a new
  19042.     --| process argument; the first call defines the first argument,
  19043.     --| the second the second argument, etc.  Exceptions are raised if
  19044.     --| a duplicate name is defined.
  19045.  
  19046. ----------------------------------------------------------------
  19047.  
  19048.     procedure Define_Argument(        --| Define an input argument
  19049.     Proc    : in Process_Handle;    --| Process being defined
  19050.     Name    : in STRING;        --| Name of the argument
  19051.     Default : in Integer_Type;    --| Default value
  19052.     Help    : in STRING        --| Explanation of the argument
  19053.     );
  19054.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19055.  
  19056.     --| Effects:
  19057.     --| Each time this procedure is called, it defines a new
  19058.     --| process argument; the first call defines the first argument,
  19059.     --| the second the second argument, etc.  Exceptions are raised if
  19060.     --| a duplicate name is defined.
  19061.  
  19062. ----------------------------------------------------------------
  19063.  
  19064.     procedure Define_Argument_Help(    --| Provide general help
  19065.     Proc : in Process_Handle;    --| Process handle
  19066.     Name : in STRING;        --| Argument being defined
  19067.     Help : in STRING        --| Help string
  19068.     );
  19069.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  19070.  
  19071.     --| Effects:
  19072.     --| Store Help message for the argument
  19073.  
  19074. ----------------------------------------------------------------
  19075.  
  19076.     procedure Append_Argument_Help(    --| Provide general help
  19077.     Proc : in Process_Handle;    --| Process handle
  19078.     Name : in STRING;        --| Argument being defined
  19079.     Help : in STRING        --| Help string
  19080.     );
  19081.     --| Raises: Uninitialized, Undefined_Name, Already_Parsed
  19082.  
  19083.     --| Effects:
  19084.     --| Append to the Help message associated with the argument.
  19085.  
  19086. ----------------------------------------------------------------
  19087.  
  19088.     function Get_Argument(        --| Return the specified argument
  19089.     Proc : in Process_Handle;    --| Definition of the process
  19090.     Name : in STRING        --| Name of the desired argument
  19091.     ) return Integer_Type;
  19092.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind
  19093.  
  19094.     --| Effects:
  19095.     --| Return an argument value from the argument called Name on the command
  19096.     --| line (or the default value if no value was supplied).
  19097.  
  19098. ----------------------------------------------------------------
  19099.  
  19100.     function Get_Default(        --| Return the default for specified
  19101.                     --| argument if one exists
  19102.     Proc : in Process_Handle;    --| Definition of the process
  19103.     Name : in STRING        --| Name of the desired argument
  19104.     ) return Integer_Type;
  19105.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind,
  19106.     --|        No_Default
  19107.  
  19108.     --| Effects:
  19109.     --| Return the default value from the argument called Name
  19110.     --| An exception is raised if no default was defined for the argument.
  19111.  
  19112. ----------------------------------------------------------------
  19113.  
  19114.     function Defaulted(            --| Return defaulted/specified status
  19115.     Proc : in     Process_Handle;    --| Definition of the process
  19116.     Name : in     STRING        --| Name of the desired argument
  19117.     ) return BOOLEAN;
  19118.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed
  19119.  
  19120.     --| Effects:
  19121.     --| Return a boolean indication TRUE if the value is defaulted
  19122.     --| FALSE if specified
  19123.  
  19124. ----------------------------------------------------------------
  19125.  
  19126. end Integer_Argument;
  19127.                                                                     pragma page;
  19128. generic
  19129.  
  19130.     type Integer_Type is range <>;
  19131.     Integer_Type_Name : STRING;
  19132.     Integer_Type_List : STRING;
  19133.  
  19134. package Integer_List_Argument is
  19135.  
  19136.     type Integer_Type_Array is array (POSITIVE range <>) of Integer_Type;
  19137.  
  19138. ----------------------------------------------------------------
  19139.  
  19140.     procedure Define_Argument(        --| Define an input argument
  19141.     Proc    : in Process_Handle;    --| Process being defined
  19142.     Name    : in STRING;        --| Name of the argument
  19143.     Help    : in STRING        --| Explanation of the argument
  19144.     );
  19145.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19146.  
  19147.     --| Effects:
  19148.     --| Each time this procedure is called, it defines a new
  19149.     --| process argument; the first call defines the first argument,
  19150.     --| the second the second argument, etc.  Exceptions are raised if
  19151.     --| a duplicate name is defined.
  19152.  
  19153. ----------------------------------------------------------------
  19154.  
  19155.     procedure Define_Argument(        --| Define an input argument
  19156.     Proc    : in Process_Handle;    --| Process being defined
  19157.     Name    : in STRING;        --| Name of the argument
  19158.     Default : in Integer_Type_Array;--| Default value
  19159.     Help    : in STRING        --| Explanation of the argument
  19160.     );
  19161.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19162.  
  19163.     --| Effects:
  19164.     --| Each time this procedure is called, it defines a new
  19165.     --| process argument; the first call defines the first argument,
  19166.     --| the second the second argument, etc.  Exceptions are raised if
  19167.     --| a duplicate name is defined.
  19168.  
  19169. ----------------------------------------------------------------
  19170.  
  19171.     procedure Define_Argument_Help(    --| Provide general help
  19172.     Proc : in Process_Handle;    --| Process handle
  19173.     Name : in STRING;        --| Argument being defined
  19174.     Help : in STRING        --| Help string
  19175.     );
  19176.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  19177.  
  19178.     --| Effects:
  19179.     --| Store Help message for the argument
  19180.  
  19181. ----------------------------------------------------------------
  19182.  
  19183.     procedure Append_Argument_Help(    --| Provide general help
  19184.     Proc : in Process_Handle;    --| Process handle
  19185.     Name : in STRING;        --| Argument being defined
  19186.     Help : in STRING        --| Help string
  19187.     );
  19188.     --| Raises: Uninitialized, Undefined_Name, Already_Parsed
  19189.  
  19190.     --| Effects:
  19191.     --| Append to the Help message associated with the argument.
  19192.  
  19193. ----------------------------------------------------------------
  19194.  
  19195.     function Get_Argument(        --| Return the specified argument
  19196.     Proc : in Process_Handle;    --| Definition of the command
  19197.     Name : in STRING        --| Name of the desired argument
  19198.     ) return IL.List;
  19199.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind
  19200.  
  19201.     --| Effects:
  19202.     --| Return an argument value from the argument called Name on the command
  19203.     --| line (or the default value if no value was supplied).
  19204.  
  19205. ----------------------------------------------------------------
  19206.  
  19207.     function Get_Default(        --| Return the default for specified
  19208.                     --| argument if one exists
  19209.     Proc : in Process_Handle;    --| Definition of the process
  19210.     Name : in STRING        --| Name of the desired argument
  19211.     ) return IL.List;
  19212.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind,
  19213.     --|        No_Default
  19214.  
  19215.     --| Effects:
  19216.     --| Return the default value from the argument called Name
  19217.     --| An exception is raised if no default was defined for the argument.
  19218.  
  19219. ----------------------------------------------------------------
  19220.  
  19221.     function Defaulted(            --| Return defaulted/specified status
  19222.     Proc : in     Process_Handle;    --| Definition of the process
  19223.     Name : in     STRING        --| Name of the desired argument
  19224.     ) return BOOLEAN;
  19225.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed
  19226.  
  19227.     --| Effects:
  19228.     --| Return a boolean indication TRUE if the value is defaulted
  19229.     --| FALSE if specified
  19230.  
  19231. ----------------------------------------------------------------
  19232.  
  19233. end Integer_List_Argument;
  19234.                                                                     pragma page;
  19235. generic
  19236.  
  19237.     String_Type_Name : STRING;
  19238.  
  19239. package String_Argument is
  19240.  
  19241. ----------------------------------------------------------------
  19242.  
  19243.     procedure Define_Argument(        --| Define an input argument
  19244.     Proc    : in Process_Handle;    --| Process being defined
  19245.     Name    : in STRING;        --| Name of the argument
  19246.     Help    : in STRING        --| Explanation of the argument
  19247.     );
  19248.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19249.  
  19250.     --| Effects:
  19251.     --| Each time this procedure is called, it defines a new
  19252.     --| process argument; the first call defines the first argument,
  19253.     --| the second the second argument, etc.  Exceptions are raised if
  19254.     --| a duplicate name is defined.
  19255.  
  19256. ----------------------------------------------------------------
  19257.  
  19258.     procedure Define_Argument(        --| Define an input argument
  19259.     Proc    : in Process_Handle;    --| Process being defined
  19260.     Name    : in STRING;        --| Name of the argument
  19261.     Default : in STRING;        --| Default value
  19262.     Help    : in STRING        --| Explanation of the argument
  19263.     );
  19264.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19265.  
  19266.     --| Effects:
  19267.     --| Each time this procedure is called, it defines a new
  19268.     --| process argument; the first call defines the first argument,
  19269.     --| the second the second argument, etc.  Exceptions are raised if
  19270.     --| a duplicate name is defined.
  19271.  
  19272. ----------------------------------------------------------------
  19273.  
  19274.     procedure Define_Argument_Help(    --| Provide general help
  19275.     Proc : in Process_Handle;    --| Process handle
  19276.     Name : in STRING;        --| Argument being defined
  19277.     Help : in STRING        --| Help string
  19278.     );
  19279.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  19280.  
  19281.     --| Effects:
  19282.     --| Store Help message for the argument
  19283.  
  19284. ----------------------------------------------------------------
  19285.  
  19286.     procedure Append_Argument_Help(    --| Provide general help
  19287.     Proc : in Process_Handle;    --| Process handle
  19288.     Name : in STRING;        --| Argument being defined
  19289.     Help : in STRING        --| Help string
  19290.     );
  19291.     --| Raises: Uninitialized, Undefined_Name, Already_Parsed
  19292.  
  19293.     --| Effects:
  19294.     --| Append to the Help message associated with the argument.
  19295.  
  19296. ----------------------------------------------------------------
  19297.  
  19298.     function Get_Argument(        --| Return the specified argument
  19299.     Proc : in Process_Handle;    --| Definition of the process
  19300.     Name : in STRING        --| Name of the desired argument
  19301.     ) return SP.String_Type;
  19302.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind
  19303.  
  19304.     --| Effects:
  19305.     --| Return an argument value from the argument called Name on the command
  19306.     --| line (or the default value if no value was supplied).
  19307.  
  19308. ----------------------------------------------------------------
  19309.  
  19310.     function Get_Default(        --| Return the default for specified
  19311.                     --| argument if one exists
  19312.     Proc : in Process_Handle;    --| Definition of the process
  19313.     Name : in STRING        --| Name of the desired argument
  19314.     ) return SP.String_Type;
  19315.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind,
  19316.     --|        No_Default
  19317.  
  19318.     --| Effects:
  19319.     --| Return the default value from the argument called Name
  19320.     --| An exception is raised if no default was defined for the argument.
  19321.  
  19322. ----------------------------------------------------------------
  19323.  
  19324.     function Defaulted(            --| Return defaulted/specified status
  19325.     Proc : in     Process_Handle;    --| Definition of the process
  19326.     Name : in     STRING        --| Name of the desired argument
  19327.     ) return BOOLEAN;
  19328.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed
  19329.  
  19330.     --| Effects:
  19331.     --| Return a boolean indication TRUE if the value is defaulted
  19332.     --| FALSE if specified
  19333.  
  19334. ----------------------------------------------------------------
  19335.  
  19336. end String_Argument;
  19337.                                                                     pragma page;
  19338. generic
  19339.  
  19340.     String_Type_Name : STRING;
  19341.     String_Type_List : STRING;
  19342.  
  19343. package String_List_Argument is
  19344.  
  19345. ----------------------------------------------------------------
  19346.  
  19347.     procedure Define_Argument(        --| Define an input argument
  19348.     Proc    : in Process_Handle;    --| Process being defined
  19349.     Name    : in STRING;        --| Name of the argument
  19350.     Help    : in STRING        --| Explanation of the argument
  19351.     );
  19352.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19353.  
  19354.     --| Effects:
  19355.     --| Each time this procedure is called, it defines a new
  19356.     --| process argument; the first call defines the first argument,
  19357.     --| the second the second argument, etc.  Exceptions are raised if
  19358.     --| a duplicate name is defined.
  19359.  
  19360. ----------------------------------------------------------------
  19361.  
  19362.     procedure Define_Argument(        --| Define an input argument
  19363.     Proc    : in Process_Handle;    --| Process being defined
  19364.     Name    : in STRING;        --| Name of the argument
  19365.     Default : in SL.List;        --| Default value
  19366.     Help    : in STRING        --| Explanation of the argument
  19367.     );
  19368.     --| Raises: Duplicate_Name, Uninitialized, Invalid_Name, Already_Parsed
  19369.  
  19370.     --| Effects:
  19371.     --| Each time this procedure is called, it defines a new
  19372.     --| process argument; the first call defines the first argument,
  19373.     --| the second the second argument, etc.  Exceptions are raised if
  19374.     --| a duplicate name is defined.
  19375.  
  19376. ----------------------------------------------------------------
  19377.  
  19378.     procedure Define_Argument_Help(    --| Provide general help
  19379.     Proc : in Process_Handle;    --| Process handle
  19380.     Name : in STRING;        --| Argument being defined
  19381.     Help : in STRING        --| Help string
  19382.     );
  19383.     --| Raises: Uninitialized, Invalid_Name, Already_Parsed
  19384.  
  19385.     --| Effects:
  19386.     --| Store Help message for the argument
  19387.  
  19388. ----------------------------------------------------------------
  19389.  
  19390.     procedure Append_Argument_Help(    --| Provide general help
  19391.     Proc : in Process_Handle;    --| Process handle
  19392.     Name : in STRING;        --| Argument being defined
  19393.     Help : in STRING        --| Help string
  19394.     );
  19395.     --| Raises: Uninitialized, Undefined_Name, Already_Parsed
  19396.  
  19397.     --| Effects:
  19398.     --| Append to the Help message associated with the argument.
  19399.  
  19400. ----------------------------------------------------------------
  19401.  
  19402.     function Get_Argument(        --| Return the specified argument
  19403.     Proc : in Process_Handle;    --| Definition of the command
  19404.     Name : in STRING        --| Name of the desired argument
  19405.     ) return SL.List;
  19406.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind
  19407.  
  19408.     --| Effects:
  19409.     --| Return an argument value from the argument called Name on the command
  19410.     --| line (or the default value if no value was supplied).
  19411.  
  19412. ----------------------------------------------------------------
  19413.  
  19414.     function Get_Default(        --| Return the default for specified
  19415.                     --| argument if one exists
  19416.     Proc : in Process_Handle;    --| Definition of the process
  19417.     Name : in STRING        --| Name of the desired argument
  19418.     ) return SL.List;
  19419.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed, Invalid_Kind,
  19420.     --|        No_Default
  19421.  
  19422.     --| Effects:
  19423.     --| Return the default value from the argument called Name
  19424.     --| An exception is raised if no default was defined for the argument.
  19425.  
  19426. ----------------------------------------------------------------
  19427.  
  19428.     function Defaulted(            --| Return defaulted/specified status
  19429.     Proc : in     Process_Handle;    --| Definition of the process
  19430.     Name : in     STRING        --| Name of the desired argument
  19431.     ) return BOOLEAN;
  19432.     --| Raises: Undefined_Name, Uninitialized, Not_Yet_Parsed
  19433.  
  19434.     --| Effects:
  19435.     --| Return a boolean indication TRUE if the value is defaulted
  19436.     --| FALSE if specified
  19437.  
  19438. ----------------------------------------------------------------
  19439.  
  19440. end String_List_Argument;
  19441.                                                                     pragma page;
  19442. generic
  19443.  
  19444.     type Command_Enumeration is (<>);
  19445.  
  19446. package Command_Line is
  19447.  
  19448.     type Process_Handle_Array is array (Command_Enumeration) of Process_Handle;
  19449.  
  19450. ----------------------------------------------------------------
  19451.  
  19452.     function Parse_Command_Line(    --| Parse a line including command
  19453.     Handles : in Process_Handle_Array;
  19454.                     --| Array of process handles
  19455.     Line    : in STRING        --| Line to be parsed
  19456.     ) return Command_Enumeration;    
  19457.     --| Raises: Undefined_Command, Uninitialized, Already_Parsed,
  19458.     --|         Abort_Process, Process_Help
  19459.  
  19460.     --| Effects:
  19461.     --| First parse the line for valid command and if found parse the arguments
  19462.     --| according to the specification given by the corresponding process
  19463.     --| handle (See Parse_Line for details of argument parsing).
  19464.     --| If parsing is successful returns an enumeration type of the command
  19465.  
  19466. ----------------------------------------------------------------
  19467.  
  19468. end Command_Line;
  19469.                                                                     pragma page;
  19470. private
  19471.                                                                     pragma List(off);
  19472. type Argument_Kind is (INT, INT_LIST, STR, STR_LIST, ENUM, ENUM_LIST);
  19473.                     -- Kinds of argument 
  19474.  
  19475. type Argument_Record is 
  19476.     record
  19477.     name     : SP.String_Type;    -- Specifies the name of an argument
  19478.     typename : SP.String_Type;    -- Argument type name
  19479.     listname : SP.String_Type;    -- Argument list type name
  19480.     kind     : Argument_Kind;    -- Specifies the argument type
  19481.     help     : SL.List := SL.Create;-- Help message for this argument
  19482.     default  : SL.List := SL.Create;-- Specifies a default value
  19483.     value    : SL.List := SL.Create;-- Argument value
  19484.     required : BOOLEAN;        -- Required argument switch
  19485.     supplied : BOOLEAN := FALSE;    -- Argument supplied switch
  19486.     low      : INTEGER;        -- Integer type range low
  19487.     high     : INTEGER;        -- Integer type range high
  19488.     valid    : SL.List := SL.Create;-- Valid Enum_Type
  19489.     end record;    
  19490.  
  19491. type Argument_Handle is access Argument_Record;
  19492.  
  19493. package AL is new Lists(Argument_Handle);
  19494.  
  19495. type Process_Record is 
  19496.     record
  19497.     parsed      : BOOLEAN        := FALSE;
  19498.     name        : SP.String_Type := SP.Make_Persistent("");
  19499.     help        : SL.List        := SL.Create;
  19500.     args        : AL.List        := AL.Create;
  19501.     msgs        : SL.List        := SL.Create;
  19502.     maxname     : NATURAL        := 0;
  19503.     maxtypename : NATURAL        := 0;
  19504.     maxtype     : NATURAL        := 0;
  19505.     typecolumn  : POSITIVE       := 6;
  19506.     end record;
  19507.  
  19508. type Process_Handle is access Process_Record;
  19509.                                                                     pragma List(on);
  19510. end Standard_Interface;
  19511.                                                                     pragma page;
  19512. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  19513. --SINTF.BDY
  19514. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  19515. with String_Utilities;
  19516. with Unchecked_Deallocation;
  19517. with Host_Lib;
  19518. with Text_IO;
  19519.  
  19520. package body Standard_Interface is
  19521.  
  19522. ----------------------------------------------------------------
  19523.  
  19524.     package HL renames Host_Lib;
  19525.  
  19526.     package SU renames String_Utilities;
  19527.  
  19528.     package SS is new SU.Generic_String_Utilities(SP.String_Type,
  19529.                           SP.Make_Persistent,
  19530.                           SP.Value);
  19531.  
  19532. ----------------------------------------------------------------
  19533.  
  19534.     type Token_Kind is (NAME, BIND, LIST, QUOTED, VALUE, DONE, NONE);
  19535.  
  19536.     type Process_Status is (CLEAN, ERROR, SEVERE);
  19537.  
  19538.     type Error_Types is (Missing_End_Delimiter,
  19539.              Missing_Argument_Enclosure,
  19540.              Missing_Quotes,
  19541.              Non_Ada_Name,
  19542.              Name_Not_Defined,
  19543.              Missing_Name,
  19544.              Missing_Argument,
  19545.              Missing_Required_Argument,
  19546.              Missing_Named_Value,
  19547.              Invalid_Value,
  19548.              Invalid_List,
  19549.              Too_Many_Arguments,
  19550.              Positional_After_Named,
  19551.              Invalid_Command);
  19552.  
  19553.     type Error_Action is (CONTINUE, STOP);
  19554.  
  19555.     type Error_Record is
  19556.     record
  19557.         msg  : SP.String_Type;
  19558.         flag : Error_Action;
  19559.         end record;
  19560.  
  19561. ----------------------------------------------------------------
  19562.  
  19563.     Status     : Process_Status;
  19564.     Short_Help : BOOLEAN := FALSE;
  19565.     Set_ID     : BOOLEAN := FALSE;
  19566.     ID         : SP.String_Type;
  19567.  
  19568. --------------------- Error Messages ---------------------------
  19569.  
  19570.     -- Substitutions are made for
  19571.     --    ~A : Name of the argument as defined
  19572.     --    ~N : Name of the argument as entered
  19573.     --    ~V : Value of the argument as entered
  19574.  
  19575.     Errors : constant array (Error_Types) of Error_Record := 
  19576.     (Missing_End_Delimiter      =>
  19577.         (SP.Make_Persistent("Missing an ending delimiter ~A"),
  19578.          CONTINUE),
  19579.      Missing_Argument_Enclosure =>
  19580.         (SP.Make_Persistent("Arguments not enclosed in ~A"),
  19581.          CONTINUE),
  19582.      Missing_Quotes             =>
  19583.         (SP.Make_Persistent("String value ~V not enclosed in quotes"),
  19584.          CONTINUE),
  19585.      Non_Ada_Name               =>
  19586.         (SP.Make_Persistent("Specified name ~N is not a valid identifier"),
  19587.          CONTINUE),
  19588.      Name_Not_Defined           =>
  19589.         (SP.Make_Persistent("Specified name ~N is not defined"),
  19590.          CONTINUE),
  19591.      Missing_Name               =>
  19592.         (SP.Make_Persistent("Name not specified"),
  19593.          CONTINUE),
  19594.      Missing_Argument           =>
  19595.         (SP.Make_Persistent("Argument not specified"),
  19596.          CONTINUE),
  19597.      Missing_Required_Argument  =>
  19598.         (SP.Make_Persistent("Required argument ~A not specified"),
  19599.          CONTINUE),
  19600.      Missing_Named_Value        =>
  19601.         (SP.Make_Persistent("Named value ~N not specified"),
  19602.          CONTINUE),
  19603.      Invalid_Value              =>
  19604.         (SP.Make_Persistent("Specified argument ~V not valid"),
  19605.          CONTINUE),
  19606.      Invalid_List               =>
  19607.         (SP.Make_Persistent("List specification ~V not valid"),
  19608.          CONTINUE),
  19609.      Too_Many_Arguments         =>
  19610.         (SP.Make_Persistent("Too many arguments specified"),
  19611.          CONTINUE),
  19612.      Positional_After_Named     =>
  19613.         (SP.Make_Persistent("A positional association must not occur after a named association"),
  19614.          STOP),
  19615.      Invalid_Command            =>
  19616.         (SP.Make_Persistent("Command ~V not defined"),
  19617.          STOP));
  19618.  
  19619. -------------------- Common File Header -------------------------
  19620.  
  19621.     -- The header is prepended by name of the process as defined
  19622.     -- by Define_Process
  19623.  
  19624.     File_Header : constant SP.String_Type :=
  19625.             SP.Make_Persistent("~D  ~T   Page ~P(R3)");
  19626.                                                                     pragma Page;
  19627. ---------------- Local Subprogam Specifications ----------------
  19628.  
  19629. procedure Free_Process_Structure is
  19630.     new Unchecked_Deallocation(Process_Record, Process_Handle);
  19631.  
  19632. ----------------------------------------------------------------
  19633.  
  19634. procedure Free_Argument_Structure is
  19635.     new Unchecked_Deallocation(Argument_Record, Argument_Handle);
  19636.  
  19637. ----------------------------------------------------------------
  19638.  
  19639. function Release return STRING;
  19640.  
  19641. ----------------------------------------------------------------
  19642.  
  19643. procedure Check_ID;
  19644.  
  19645. ----------------------------------------------------------------
  19646.  
  19647. procedure Check_Uninitialized(
  19648.     Proc : in Process_Handle
  19649.     );
  19650.  
  19651. ----------------------------------------------------------------
  19652.  
  19653. procedure Check_Already_Exists(
  19654.     Proc : in Process_Handle
  19655.     );
  19656.  
  19657. ----------------------------------------------------------------
  19658.  
  19659. procedure Check_Invalid_Name(
  19660.     Name : in STRING
  19661.     );
  19662.  
  19663. ----------------------------------------------------------------
  19664.  
  19665. procedure Check_Undefined_Name(
  19666.     Proc : in Process_Handle;
  19667.     Name : in STRING
  19668.     );
  19669.  
  19670. ----------------------------------------------------------------
  19671.  
  19672. procedure Check_Duplicate_Name(
  19673.     Proc : in Process_Handle;
  19674.     Name : in STRING
  19675.     );
  19676.  
  19677. ----------------------------------------------------------------
  19678.  
  19679. procedure Check_Not_Yet_Parsed(
  19680.     Proc : in Process_Handle
  19681.     );
  19682.  
  19683. ----------------------------------------------------------------
  19684.  
  19685. procedure Check_Already_Parsed(
  19686.     Proc : in Process_Handle
  19687.     );
  19688.  
  19689. ----------------------------------------------------------------
  19690.  
  19691. procedure Check_Invalid_Kind(
  19692.     Proc : in Process_Handle;
  19693.     Name : in STRING;
  19694.     Kind : in Argument_Kind
  19695.     );
  19696.  
  19697. ----------------------------------------------------------------
  19698.  
  19699. procedure Write(
  19700.     Text  : in STRING
  19701.     );
  19702.  
  19703. ----------------------------------------------------------------
  19704.  
  19705. procedure New_Line(
  19706.     Count : in POSITIVE
  19707.     );
  19708.  
  19709. ----------------------------------------------------------------
  19710.  
  19711. procedure Write_List_Vertical(
  19712.     Header  : in STRING;
  19713.     List    : in SL.List
  19714.     );
  19715.  
  19716. ----------------------------------------------------------------
  19717.  
  19718. procedure Write_List_Horizontal(
  19719.     List    : in SL.List;
  19720.     Quoted  : in BOOLEAN := FALSE
  19721.     );
  19722.  
  19723. ----------------------------------------------------------------
  19724.  
  19725. function Find_Match(
  19726.     Proc : in Process_Handle;
  19727.     Name : in STRING
  19728.     ) return Argument_Handle;
  19729.  
  19730. ----------------------------------------------------------------
  19731.  
  19732. function Get_Argument_Handle(
  19733.     Proc : in Process_Handle;
  19734.     Name : in STRING
  19735.     ) return Argument_Handle;
  19736.  
  19737. ----------------------------------------------------------------
  19738.  
  19739. procedure Destroy_String_List is new SL.DestroyDeep(Dispose => SP.Flush);
  19740.  
  19741. ----------------------------------------------------------------
  19742.  
  19743. procedure Destroy_Argument_Help(
  19744.     Proc : in Process_Handle;
  19745.     Name : in STRING
  19746.     );
  19747.  
  19748. ----------------------------------------------------------------
  19749.  
  19750. procedure Set_Argument_Help(
  19751.     Proc : in Process_Handle;
  19752.     Name : in STRING;
  19753.     Help : in STRING
  19754.     );
  19755.  
  19756. ----------------------------------------------------------------
  19757.  
  19758. function Set_Argument(
  19759.     Proc     : in     Process_Handle;
  19760.     Name     : in     STRING;
  19761.     Kind     : in     Argument_Kind;
  19762.     Typename : in     STRING;
  19763.     Listname : in     STRING;
  19764.     Required : in     BOOLEAN
  19765.     ) return Argument_Handle;
  19766.  
  19767. ----------------------------------------------------------------
  19768.  
  19769. procedure Point_Next_Token(
  19770.     Scanner : in SU.Scanner
  19771.     );
  19772.  
  19773. ----------------------------------------------------------------
  19774.  
  19775. procedure Get_Next_Token(
  19776.     Scanner : in     SU.Scanner;
  19777.     Kind    :    out Token_Kind;
  19778.     Token   : in out SP.String_Type
  19779.     );
  19780.  
  19781. ----------------------------------------------------------------
  19782.  
  19783. procedure Parse_Argument(
  19784.     Argument : in Argument_Handle;
  19785.     Item     : in SP.String_Type;
  19786.     Kind     : in Token_Kind
  19787.     );
  19788.  
  19789. ----------------------------------------------------------------
  19790.  
  19791. procedure Report_Error(
  19792.     Kind     : in Error_Types;
  19793.     Argument : in STRING := "";
  19794.     Name     : in STRING := "";
  19795.     Value    : in STRING := ""
  19796.     );
  19797.  
  19798. ----------------------------------------------------------------
  19799.                                                                     pragma Page;
  19800. ---------------------- Visible Subprogams ----------------------
  19801.  
  19802. procedure Set_Tool_Identifier(
  19803.     Identifier : in STRING
  19804.     ) is
  19805.  
  19806. begin
  19807.  
  19808.     Check_ID;
  19809.     raise Identifier_Error;
  19810.  
  19811. exception
  19812.     when Identifier_Error =>
  19813.     Set_ID := TRUE;
  19814.     ID := SP.Make_Persistent(Identifier);
  19815.  
  19816. end Set_Tool_Identifier;
  19817.  
  19818. ----------------------------------------------------------------
  19819.  
  19820. function Get_Tool_Identifier
  19821.     return STRING is
  19822.  
  19823. begin
  19824.  
  19825.     Check_ID;
  19826.     return Release & '-' & SP.Value(ID);
  19827.  
  19828. end Get_Tool_Identifier;
  19829.  
  19830. ----------------------------------------------------------------
  19831.  
  19832. procedure Define_Process(
  19833.     Name    : in     STRING;
  19834.     Help    : in     STRING;
  19835.     Proc    : in out Process_Handle
  19836.     ) is
  19837.  
  19838. begin
  19839.  
  19840.     Check_ID;
  19841.     Check_Invalid_Name(Name);
  19842.     Check_Already_Exists(Proc);
  19843.     Proc := new Process_Record;    
  19844.     Define_Process_Name(Proc, Name);
  19845.     Define_Process_Help(Proc, Help);
  19846.  
  19847. end Define_Process;
  19848.  
  19849. ----------------------------------------------------------------
  19850.  
  19851. procedure Redefine_Process(
  19852.     Proc    : in Process_Handle
  19853.     ) is
  19854.  
  19855.     Iterator : AL.ListIter;
  19856.     Item     : Argument_Handle;
  19857.  
  19858. begin
  19859.  
  19860.     Check_Not_Yet_Parsed(Proc);
  19861.     Iterator := AL.MakeListIter(Proc.args);
  19862.     while AL.More(Iterator) loop
  19863.     AL.Next(Iterator, Item);
  19864.     if Item.supplied then
  19865.         Item.supplied := FALSE;
  19866.         Destroy_String_List(Item.value);
  19867.         Item.value := SL.Create;
  19868.     end if;
  19869.     end loop;
  19870.     Proc.parsed := FALSE;
  19871.     
  19872. exception
  19873.  
  19874.     when Not_Yet_Parsed =>
  19875.     null;
  19876.  
  19877. end Redefine_Process;
  19878.  
  19879. ----------------------------------------------------------------
  19880.  
  19881. procedure Undefine_Process(
  19882.     Proc : in out Process_Handle
  19883.     ) is
  19884.  
  19885.     Iterator : AL.ListIter;
  19886.     Item     : Argument_Handle;
  19887.  
  19888. begin
  19889.  
  19890.     if Proc /= null then
  19891.     SP.Flush(Proc.name);
  19892.     Destroy_String_List(Proc.help);
  19893.     Iterator := AL.MakeListIter(Proc.args);
  19894.     while AL.More(Iterator) loop
  19895.         AL.Next(Iterator, Item);
  19896.         SP.Flush(Item.name);
  19897.         SP.Flush(Item.typename);
  19898.         SP.Flush(Item.listname);
  19899.         Destroy_String_List(Item.help);
  19900.         Destroy_String_List(Item.default);
  19901.         Destroy_String_List(Item.value);
  19902.         Free_Argument_Structure(Item);
  19903.     end loop;
  19904.     AL.Destroy(Proc.args);
  19905.     Destroy_String_List(Proc.msgs);
  19906.     end if;
  19907.     Free_Process_Structure(Proc);
  19908.  
  19909. end Undefine_Process;
  19910.  
  19911. ----------------------------------------------------------------
  19912.  
  19913. procedure Define_Process_Name(
  19914.     Proc    : in Process_Handle;
  19915.     Name    : in STRING
  19916.     ) is
  19917.  
  19918. begin
  19919.  
  19920.     Check_Invalid_Name(Name);
  19921.     Check_Already_Parsed(Proc);
  19922.     SP.Flush(Proc.name);
  19923.     Proc.name := SP.Make_Persistent(SP.Upper(Name));
  19924.  
  19925. end Define_Process_Name;
  19926.  
  19927. ----------------------------------------------------------------
  19928.  
  19929. procedure Define_Process_Help(
  19930.     Proc : in Process_Handle;
  19931.     Help : in STRING
  19932.     ) is
  19933.  
  19934. begin
  19935.  
  19936.     Check_Already_Parsed(Proc);
  19937.     Destroy_String_List(Proc.help);
  19938.     Proc.help := SL.Create;
  19939.     Append_Process_Help(Proc, Help);
  19940.  
  19941. end Define_Process_Help;
  19942.  
  19943. ----------------------------------------------------------------
  19944.  
  19945. procedure Append_Process_Help(
  19946.     Proc : in Process_Handle;
  19947.     Help : in STRING
  19948.     ) is
  19949.  
  19950. begin
  19951.  
  19952.     Check_Already_Parsed(Proc);
  19953.     SL.Attach(Proc.help, SP.Make_Persistent(Help));
  19954.  
  19955. end Append_Process_Help;
  19956.  
  19957. ----------------------------------------------------------------
  19958.  
  19959. procedure Define_Help(
  19960.     Proc : in Process_Handle;
  19961.     Help : in STRING
  19962.     ) is
  19963.  
  19964. begin
  19965.  
  19966.     Check_Already_Parsed(Proc);
  19967.     Destroy_String_List(Proc.msgs);
  19968.     Proc.msgs := SL.Create;
  19969.     Append_Help(Proc, Help);
  19970.  
  19971. end Define_Help;
  19972.  
  19973. ----------------------------------------------------------------
  19974.  
  19975. procedure Append_Help(
  19976.     Proc : in Process_Handle;
  19977.     Help : in STRING
  19978.     ) is
  19979.  
  19980. begin
  19981.  
  19982.     Check_Already_Parsed(Proc);
  19983.     SL.Attach(Proc.msgs, SP.Make_Persistent(Help));
  19984.  
  19985. end Append_Help;
  19986.  
  19987. ----------------------------------------------------------------
  19988.  
  19989. procedure Parse_Line(
  19990.     Proc : in Process_Handle;
  19991.     Line : in STRING
  19992.     ) is
  19993.  
  19994.     S_Str    : SP.String_Type;
  19995.     Current  : Token_Kind;
  19996.     Previous : Token_Kind := NONE;
  19997.     Name_Val : SP.String_Type;
  19998.     Named    : BOOLEAN := FALSE;
  19999.     Iterator : AL.ListIter;
  20000.     Item     : Argument_Handle;
  20001.     Scanner  : SU.Scanner;
  20002.     Found    : BOOLEAN;
  20003.  
  20004. begin
  20005.  
  20006.     Check_Already_Parsed(Proc);
  20007.  
  20008.     Status := CLEAN;
  20009.  
  20010.     SP.Mark;
  20011.     S_Str := SS.Strip(Line);
  20012.     if SP.Length(S_Str) /= 0 then
  20013.     if SP.Fetch(S_Str, SP.Length(S_Str)) = End_Delimiter then
  20014.         S_Str := SS.Strip_Trailing(SP.Substr(S_Str, 1, SP.Length(S_Str) - 1));    
  20015.     elsif Parsing_Switches(Ending_Delimiter) = ON then
  20016.         Report_Error(Missing_End_Delimiter,
  20017.              Argument => "'" & End_Delimiter & "'");     
  20018.     end if;
  20019.     elsif Parsing_Switches(Ending_Delimiter) = ON then
  20020.     if Action_Switches(Show_Help) = ON then
  20021.         Show_Help(Proc);
  20022.     end if;
  20023.     raise Process_Help;
  20024.     end if;                
  20025.  
  20026.     Scanner := SS.Make_Scanner(S_Str);
  20027.     SP.Release;
  20028.     SU.Mark(Scanner);
  20029.     if SU.More(Scanner) then
  20030.     if SU.Is_Enclosed(Left_Enclosure, Right_Enclosure, Scanner) then
  20031.         SS.Scan_Enclosed(Left_Enclosure, Right_Enclosure, Scanner, Found, S_Str);
  20032.         if SU.More(Scanner) then
  20033.         SU.Restore(Scanner);
  20034.         if Parsing_Switches(Argument_Enclosure) = ON then
  20035.             Report_Error(Missing_Argument_Enclosure,
  20036.                  Argument => "'" & Left_Enclosure & "' and '" & Right_Enclosure & "'");
  20037.         end if;
  20038.         else
  20039.         SU.Destroy_Scanner(Scanner);
  20040.         Scanner := SS.Make_Scanner(S_Str);
  20041.         end if;
  20042.         SP.Flush(S_Str);
  20043.     elsif Parsing_Switches(Argument_Enclosure) = ON then
  20044.         Report_Error(Missing_Argument_Enclosure,
  20045.              Argument => "'" & Left_Enclosure & "' and '" & Right_Enclosure & "'");
  20046.     end if;
  20047.     end if;
  20048.  
  20049.     SU.Skip_Space(Scanner);
  20050.     S_Str := SS.Get_Remainder(Scanner);
  20051.     SU.Destroy_Scanner(Scanner);
  20052.     SP.Mark;
  20053.  
  20054.     S_Str := SS.Strip(S_Str);
  20055.     if SP.Length(S_Str) = 0 then
  20056.     Scanner := SS.Make_Scanner(S_Str);
  20057.     else
  20058.     Scanner := SS.Make_Scanner(SP."&"(S_Str, "" & SP.Fetch(Delimiter, 1)));
  20059.     end if;
  20060.     SP.Flush(S_Str);
  20061.     SP.Release;
  20062.  
  20063.     Proc.parsed := TRUE;
  20064.  
  20065.     Iterator := AL.MakeListIter(Proc.args);
  20066.     while AL.More(Iterator) and Previous /= DONE and Status /= SEVERE and not Named loop
  20067.     AL.Next(Iterator, Item);
  20068.     Get_Next_Token(Scanner, Current, S_Str);
  20069.     case Current is
  20070.         when NONE =>
  20071.         Report_Error(Missing_Argument);     
  20072.         when DONE =>
  20073.         null;
  20074.         when NAME =>
  20075.         Named := TRUE;
  20076.         Name_Val := S_Str;
  20077.         begin
  20078.             Item := Get_Argument_Handle(Proc, SP.Value(Name_Val));
  20079.         exception
  20080.             when Invalid_Name =>
  20081.             Report_Error(Non_Ada_Name,
  20082.                      Name => SP.Value(Name_Val));
  20083.             when Undefined_Name =>
  20084.             Report_Error(Name_Not_Defined,
  20085.                      Name => SP.Value(Name_Val));
  20086.         end;
  20087.         when BIND =>
  20088.         Report_Error(Missing_Name);
  20089.         when others =>
  20090.         SP.Mark;
  20091.         Parse_Argument(Item, S_Str, Current);
  20092.         SP.Release;
  20093.     end case;
  20094.     Previous := Current;
  20095.     end loop;
  20096.  
  20097.     if Named then
  20098.     while Previous /= DONE and Status /= SEVERE loop
  20099.         Get_Next_Token(Scanner, Current, S_Str);
  20100.         case Previous is
  20101.         when NAME =>
  20102.             null;
  20103.         when BIND =>
  20104.             case Current is
  20105.             when NAME | NONE | DONE | BIND =>
  20106.                 Report_Error(Missing_Named_Value,
  20107.                      Name => SP.Value(Item.name));
  20108.                 if Current = BIND then
  20109.                 Report_Error(Missing_Name);
  20110.                 end if;
  20111.             when others =>
  20112.                 SP.Mark;
  20113.                 Parse_Argument(Item, S_Str, Current);
  20114.                 SP.Release;
  20115.             end case;
  20116.         when others =>
  20117.             case Current is
  20118.             when DONE =>
  20119.                 null;
  20120.             when NAME =>
  20121.                 Name_Val := S_Str;
  20122.                 begin
  20123.                 Item := Get_Argument_Handle(Proc, SP.Value(Name_Val));
  20124.                 exception
  20125.                 when Invalid_Name =>
  20126.                     Report_Error(Non_Ada_Name,
  20127.                          Name => SP.Value(Name_Val));
  20128.                 when Undefined_Name =>
  20129.                     Report_Error(Name_Not_Defined,
  20130.                          Name => SP.Value(Name_Val));
  20131.                 end;
  20132.             when NONE =>
  20133.                 Report_Error(Missing_Argument);
  20134.             when others =>
  20135.                 Report_Error(Positional_After_Named);
  20136.             end case;
  20137.         end case;
  20138.         Previous := Current;
  20139.     end loop;
  20140.     else
  20141.     Get_Next_Token(Scanner, Current, S_Str);
  20142.     if Current /= DONE then
  20143.         Report_Error(Too_Many_Arguments);
  20144.     end if;
  20145.     end if;
  20146.  
  20147.     Iterator := AL.MakeListIter(Proc.args);
  20148.     while AL.More(Iterator) loop
  20149.     AL.Next(Iterator, Item);
  20150.     if Item.required and not Item.supplied then
  20151.         Report_Error(Missing_Required_Argument, Argument=>SP.Value(Item.name));
  20152.     end if;
  20153.     end loop;
  20154.  
  20155.     if Status = CLEAN then
  20156.     if Action_Switches(Echo_Command) = ON then
  20157.         Echo_Process(Proc);
  20158.     end if;
  20159.     if Action_Switches(Prompt_for_Reply) = ON then
  20160.         if not Continue(Proc) then
  20161.         Redefine_Process(Proc);
  20162.         raise Abort_Process;
  20163.         end if;
  20164.     end if;
  20165.     else
  20166.     if Action_Switches(Show_Help_on_Error) = ON then
  20167.         Show_Help(Proc);
  20168.     end if;
  20169.     Redefine_Process(Proc);
  20170.     raise Abort_Process;
  20171.     end if;
  20172.  
  20173. end Parse_Line;
  20174.  
  20175. ----------------------------------------------------------------
  20176.  
  20177. procedure Parse_Line(
  20178.     Proc : in Process_Handle
  20179.     ) is
  20180.  
  20181. begin
  20182.  
  20183.     Parse_Line(Proc, HL.Get_Item(HL.ARGUMENTS, HL.EDIT));
  20184.  
  20185. end Parse_Line;
  20186.  
  20187. ----------------------------------------------------------------
  20188.  
  20189. procedure Show_Help(
  20190.     Proc : in Process_Handle
  20191.     ) is
  20192.  
  20193.     IterA : AL.ListIter;
  20194.     IterB : AL.ListIter;
  20195.     Arg   : Argument_Handle;
  20196.     Argx  : Argument_Handle;
  20197.     First : BOOLEAN := TRUE;
  20198.     S_Str : SP.String_Type;
  20199.     Found : BOOLEAN;
  20200.  
  20201. begin
  20202.  
  20203.     Check_Uninitialized(Proc);
  20204.  
  20205.     SP.Mark;
  20206.  
  20207.     HL.Set_Error;
  20208.  
  20209.     if Short_Help then
  20210.     Write_List_Vertical(SP.Value(Proc.name) & " : ", Proc.help);
  20211.     SP.Release;
  20212.     HL.Reset_Error;
  20213.     return;
  20214.     end if;
  20215.     New_Line(1);
  20216.     Write_List_Vertical(SP.Value(Proc.name) & " : ", Proc.help);
  20217.     Write("-- " & Get_Tool_Identifier);
  20218.     New_line(2);
  20219.  
  20220.     IterA := AL.MakeListIter(Proc.args);
  20221.     if AL.More(IterA) then
  20222.     First := FALSE;
  20223.     end if;
  20224.     while AL.More(IterA) loop
  20225.     AL.Next(IterA, Arg);
  20226.     case Arg.kind is
  20227.         when ENUM =>
  20228.         Found := FALSE;
  20229.         IterB := AL.MakeListIter(Proc.args);
  20230.         while AL.More(IterB) loop
  20231.             AL.Next(IterB, Argx);
  20232.             if Arg = Argx then
  20233.             exit;
  20234.             elsif SP.Equal(Arg.typename, Argx.typename) then
  20235.             Found := TRUE;
  20236.             exit;
  20237.             end if;
  20238.         end loop;
  20239.         if not Found and
  20240.            not SP.Equal(Arg.typename, "BOOLEAN") and
  20241.            not SP.Equal(Arg.typename, "CHARACTER") then
  20242.             TEXT_IO.PUT("type");
  20243.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20244.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtypename));
  20245.             TEXT_IO.PUT(" is ");
  20246.             TEXT_IO.PUT(Left_Enclosure);
  20247.             Write_List_Horizontal(Arg.valid);
  20248.             TEXT_IO.PUT(Right_Enclosure);
  20249.             TEXT_IO.PUT(End_Delimiter);
  20250.             New_Line(1);
  20251.         end if;
  20252.         when ENUM_LIST =>
  20253.         Found := FALSE;
  20254.         IterB := AL.MakeListIter(Proc.args);
  20255.         while AL.More(IterB) loop
  20256.             AL.Next(IterB, Argx);
  20257.             if Arg = Argx then
  20258.             exit;
  20259.             elsif SP.Equal(Arg.typename, Argx.typename) then
  20260.             Found := TRUE;
  20261.             exit;
  20262.             end if;
  20263.         end loop;
  20264.         if not Found and
  20265.            not SP.Equal(Arg.typename, "BOOLEAN") and
  20266.            not SP.Equal(Arg.typename, "CHARACTER") then
  20267.             TEXT_IO.PUT("type");
  20268.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20269.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtypename));
  20270.             TEXT_IO.PUT(" is ");
  20271.             TEXT_IO.PUT(Left_Enclosure);
  20272.             Write_List_Horizontal(Arg.valid);
  20273.             TEXT_IO.PUT(Right_Enclosure);
  20274.             TEXT_IO.PUT(End_Delimiter);
  20275.             New_Line(1);
  20276.         end if;
  20277.         Found := FALSE;
  20278.         IterB := AL.MakeListIter(Proc.args);
  20279.         while AL.More(IterB) loop
  20280.             AL.Next(IterB, Argx);
  20281.             if Arg = Argx then
  20282.             exit;
  20283.             elsif SP.Equal(Arg.listname, Argx.listname) then
  20284.             Found := TRUE;
  20285.             exit;
  20286.             end if;
  20287.         end loop;
  20288.         if not Found then
  20289.             TEXT_IO.PUT("type");
  20290.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20291.             TEXT_IO.PUT(SS.Left_Justify(Arg.listname, Proc.maxtypename));
  20292.             TEXT_IO.PUT(" is array (POSITIVE range <>) of ");
  20293.             TEXT_IO.PUT(SP.Value(Arg.typename));
  20294.             TEXT_IO.PUT(End_Delimiter);
  20295.             New_Line(1);
  20296.         end if;
  20297.         when INT =>
  20298.         Found := FALSE;
  20299.         IterB := AL.MakeListIter(Proc.args);
  20300.         while AL.More(IterB) loop
  20301.             AL.Next(IterB, Argx);
  20302.             if Arg = Argx then
  20303.             exit;
  20304.             elsif SP.Equal(Arg.typename, Argx.typename) then
  20305.             Found := TRUE;
  20306.             exit;
  20307.             end if;
  20308.         end loop;
  20309.         if not Found and
  20310.            not SP.Equal(Arg.typename, "INTEGER") and
  20311.            not SP.Equal(Arg.typename, "POSITIVE") and
  20312.            not SP.Equal(Arg.typename, "NATURAL") then
  20313.             TEXT_IO.PUT("subtype");
  20314.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20315.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtypename));
  20316.             TEXT_IO.PUT(" is INTEGER range ");
  20317.             TEXT_IO.PUT(SU.Image(Arg.low));
  20318.             TEXT_IO.PUT(" .. ");
  20319.             TEXT_IO.PUT(SU.Image(Arg.high));
  20320.             TEXT_IO.PUT(End_Delimiter);
  20321.             New_Line(1);
  20322.         end if;
  20323.         when INT_LIST  =>
  20324.         Found := FALSE;
  20325.         IterB := AL.MakeListIter(Proc.args);
  20326.         while AL.More(IterB) loop
  20327.             AL.Next(IterB, Argx);
  20328.             if Arg = Argx then
  20329.             exit;
  20330.             elsif SP.Equal(Arg.typename, Argx.typename) then
  20331.             Found := TRUE;
  20332.             exit;
  20333.             end if;
  20334.         end loop;
  20335.         if not Found and
  20336.            not SP.Equal(Arg.typename, "INTEGER") and
  20337.            not SP.Equal(Arg.typename, "POSITIVE") and
  20338.            not SP.Equal(Arg.typename, "NATURAL") then
  20339.             TEXT_IO.PUT("subtype");
  20340.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20341.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtypename));
  20342.             TEXT_IO.PUT(" is INTEGER range ");
  20343.             TEXT_IO.PUT(SU.Image(Arg.low));
  20344.             TEXT_IO.PUT(" .. ");
  20345.             TEXT_IO.PUT(SU.Image(Arg.high));
  20346.             TEXT_IO.PUT(End_Delimiter);
  20347.             New_Line(1);
  20348.         end if;
  20349.         Found := FALSE;
  20350.         IterB := AL.MakeListIter(Proc.args);
  20351.         while AL.More(IterB) loop
  20352.             AL.Next(IterB, Argx);
  20353.             if Arg = Argx then
  20354.             exit;
  20355.             elsif SP.Equal(Arg.listname, Argx.listname) then
  20356.             Found := TRUE;
  20357.             exit;
  20358.             end if;
  20359.         end loop;
  20360.         if not Found then
  20361.             TEXT_IO.PUT("type");
  20362.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20363.             TEXT_IO.PUT(SS.Left_Justify(Arg.listname, Proc.maxtypename));
  20364.             TEXT_IO.PUT(" is array (POSITIVE range <>) of ");
  20365.             TEXT_IO.PUT(SP.Value(Arg.typename));
  20366.             TEXT_IO.PUT(End_Delimiter);
  20367.             New_Line(1);
  20368.         end if;
  20369.         when STR =>
  20370.         Found := FALSE;
  20371.         IterB := AL.MakeListIter(Proc.args);
  20372.         while AL.More(IterB) loop
  20373.             AL.Next(IterB, Argx);
  20374.             if Arg = Argx then
  20375.             exit;
  20376.             elsif SP.Equal(Arg.typename, Argx.typename) then
  20377.             Found := TRUE;
  20378.             exit;
  20379.             end if;
  20380.         end loop;
  20381.         if not Found and
  20382.            not SP.Equal(Arg.typename, "STRING") then
  20383.             TEXT_IO.PUT("subtype");
  20384.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20385.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtypename));
  20386.             TEXT_IO.PUT(" is STRING");
  20387.             TEXT_IO.PUT(End_Delimiter);
  20388.             New_Line(1);
  20389.         end if;
  20390.         when STR_LIST  =>
  20391.         Found := FALSE;
  20392.         IterB := AL.MakeListIter(Proc.args);
  20393.         while AL.More(IterB) loop
  20394.             AL.Next(IterB, Argx);
  20395.             if Arg = Argx then
  20396.             exit;
  20397.             elsif SP.Equal(Arg.typename, Argx.typename) then
  20398.             Found := TRUE;
  20399.             exit;
  20400.             end if;
  20401.         end loop;
  20402.         if not Found and
  20403.            not SP.Equal(Arg.typename, "STRING") then
  20404.             TEXT_IO.PUT("subtype");
  20405.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20406.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtypename));
  20407.             TEXT_IO.PUT(" is STRING");
  20408.             TEXT_IO.PUT(End_Delimiter);
  20409.             New_Line(1);
  20410.         end if;
  20411.         Found := FALSE;
  20412.         IterB := AL.MakeListIter(Proc.args);
  20413.         while AL.More(IterB) loop
  20414.             AL.Next(IterB, Argx);
  20415.             if Arg = Argx then
  20416.             exit;
  20417.             elsif SP.Equal(Arg.listname, Argx.listname) then
  20418.             Found := TRUE;
  20419.             exit;
  20420.             end if;
  20421.         end loop;
  20422.         if not Found then
  20423.             TEXT_IO.PUT("type");
  20424.             TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Proc.typecolumn));
  20425.             TEXT_IO.PUT(SS.Left_Justify(Arg.listname, Proc.maxtypename));
  20426.             TEXT_IO.PUT(" is array (POSITIVE range <>) of ");
  20427.             TEXT_IO.PUT(SP.Value(Arg.typename));
  20428.             TEXT_IO.PUT(End_Delimiter);
  20429.             New_Line(1);
  20430.         end if;
  20431.     end case;
  20432.     end loop;
  20433.     if not First then
  20434.     New_Line(1);
  20435.     end if;
  20436.  
  20437.     TEXT_IO.PUT("procedure ");
  20438.     TEXT_IO.PUT(SP.Value(Proc.name));
  20439.     First := TRUE;
  20440.     IterA := AL.MakeListIter(Proc.args);
  20441.     while AL.More(IterA) loop
  20442.     AL.Next(IterA, Arg);
  20443.     if not First then
  20444.         TEXT_IO.PUT(End_Delimiter);
  20445.     else
  20446.         First := FALSE;
  20447.         TEXT_IO.PUT(Left_Enclosure);
  20448.     end if;
  20449.     New_Line(1);
  20450.     TEXT_IO.SET_COL(4);
  20451.     TEXT_IO.PUT(SS.Left_Justify(Arg.name, Proc.maxname));
  20452.     TEXT_IO.PUT(" : in ");
  20453.     case Arg.kind is
  20454.         when ENUM | INT =>
  20455.         if Arg.required then
  20456.             TEXT_IO.PUT(SP.Value(Arg.typename));
  20457.         else
  20458.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtype));
  20459.             TEXT_IO.PUT(" := ");
  20460.             Write_List_Horizontal(Arg.default);
  20461.         end if;
  20462.         when STR =>
  20463.         if Arg.required then
  20464.             TEXT_IO.PUT(SP.Value(Arg.typename));
  20465.         else
  20466.             TEXT_IO.PUT(SS.Left_Justify(Arg.typename, Proc.maxtype));
  20467.             TEXT_IO.PUT(" := """);
  20468.             Write_List_Horizontal(Arg.default);
  20469.             TEXT_IO.PUT('"');
  20470.         end if;
  20471.         when ENUM_LIST | INT_LIST =>
  20472.         if Arg.required then
  20473.             TEXT_IO.PUT(SP.Value(Arg.listname));
  20474.         else
  20475.             TEXT_IO.PUT(SS.Left_Justify(Arg.listname, Proc.maxtype));
  20476.             TEXT_IO.PUT(" := (");
  20477.             Write_List_Horizontal(Arg.default, Quoted=>FALSE);
  20478.             TEXT_IO.PUT(Right_Enclosure);
  20479.         end if;
  20480.         when STR_LIST =>
  20481.         if Arg.required then
  20482.             TEXT_IO.PUT(SP.Value(Arg.listname));
  20483.         else
  20484.             TEXT_IO.PUT(SS.Left_Justify(Arg.listname, Proc.maxtype));
  20485.             TEXT_IO.PUT(" := (");
  20486.             Write_List_Horizontal(Arg.default, Quoted=>TRUE);
  20487.             TEXT_IO.PUT(Right_Enclosure);
  20488.         end if;
  20489.     end case;
  20490.     end loop;
  20491.     if not First then
  20492.     New_Line(1);
  20493.     TEXT_IO.SET_COL(4);
  20494.     TEXT_IO.PUT(Right_Enclosure);
  20495.     end if;
  20496.     TEXT_IO.PUT(End_Delimiter);
  20497.     New_Line(2);
  20498.  
  20499.     IterA := AL.MakeListIter(Proc.args);
  20500.     if AL.More(IterA) then
  20501.     while AL.More(IterA) loop
  20502.         AL.Next(IterA, Arg);
  20503.         S_Str := SP."&"(SS.Left_Justify(Arg.name, Proc.maxname), " : ");
  20504.         Write_List_Vertical(SP.Value(S_Str), Arg.help);
  20505.     end loop;
  20506.         New_Line(1);
  20507.     end if;
  20508.  
  20509.     if not SL.IsEmpty(Proc.msgs) then
  20510.     Write_List_Vertical("", Proc.msgs);
  20511.     New_Line(1);
  20512.     end if;
  20513.  
  20514.     HL.Reset_Error;
  20515.  
  20516.     SP.Release;
  20517.  
  20518. end Show_Help;
  20519.  
  20520. ----------------------------------------------------------------
  20521.  
  20522. procedure Echo_Process(
  20523.     Proc : in Process_Handle
  20524.     ) is
  20525.  
  20526.     IterA : AL.ListIter;
  20527.     Arg   : Argument_Handle;
  20528.     First : BOOLEAN;
  20529.     Num   : INTEGER;
  20530.  
  20531. begin
  20532.  
  20533.     Check_Not_Yet_Parsed(Proc);
  20534.  
  20535.     SP.Mark;
  20536.  
  20537.     HL.Set_Error;
  20538.  
  20539.     TEXT_IO.NEW_LINE(1);
  20540.  
  20541.     TEXT_IO.PUT(SP.Value(Proc.name));
  20542.     First := TRUE;
  20543.     IterA := AL.MakeListIter(Proc.args);
  20544.     while AL.More(IterA) loop
  20545.     AL.Next(IterA, Arg);
  20546.     if not First then
  20547.         TEXT_IO.PUT(SP.Fetch(Delimiter, 1));
  20548.         TEXT_IO.NEW_LINE(1);
  20549.     else
  20550.         First := FALSE;
  20551.         TEXT_IO.PUT(" ( ");
  20552.         Num := SP.Length(Proc.name) + 4;
  20553.     end if;
  20554.     TEXT_IO.SET_COL(TEXT_IO.POSITIVE_COUNT(Num));
  20555.     TEXT_IO.PUT(SS.Left_Justify(Arg.name, Proc.maxname));
  20556.     TEXT_IO.PUT(' ' & SP.Value(Assignment) & ' ');
  20557.     case Arg.kind is
  20558.         when ENUM | INT =>
  20559.         if Arg.supplied then
  20560.             Write_List_Horizontal(Arg.value);
  20561.         else
  20562.             Write_List_Horizontal(Arg.default);
  20563.         end if;
  20564.         when STR =>
  20565.         if Arg.supplied then
  20566.             Write_List_Horizontal(Arg.value, Quoted=>TRUE);
  20567.         else
  20568.             Write_List_Horizontal(Arg.default, Quoted=>TRUE);
  20569.         end if;
  20570.         when ENUM_LIST | INT_LIST =>
  20571.         TEXT_IO.PUT(Left_Enclosure);
  20572.         if Arg.supplied then
  20573.             Write_List_Horizontal(Arg.value);
  20574.         else
  20575.             Write_List_Horizontal(Arg.default);
  20576.         end if;
  20577.         TEXT_IO.PUT(Right_Enclosure);
  20578.         when STR_LIST =>
  20579.         TEXT_IO.PUT(Left_Enclosure);
  20580.         if Arg.supplied then
  20581.             Write_List_Horizontal(Arg.value, Quoted=>TRUE);
  20582.         else
  20583.             Write_List_Horizontal(Arg.default, Quoted=>TRUE);
  20584.         end if;
  20585.         TEXT_IO.PUT(Right_Enclosure);
  20586.     end case;
  20587.     end loop;
  20588.     if not First then
  20589.     TEXT_IO.PUT(" )");
  20590.     end if;
  20591.     TEXT_IO.PUT(End_Delimiter);
  20592.     TEXT_IO.NEW_LINE(2);
  20593.  
  20594.     HL.Reset_Error;
  20595.  
  20596.     SP.Release;
  20597.  
  20598. end Echo_Process;
  20599.  
  20600. ----------------------------------------------------------------
  20601.  
  20602. function Continue(
  20603.     Proc : in Process_Handle
  20604.     ) return BOOLEAN is
  20605.  
  20606.     Reply : STRING (1 .. 256);
  20607.     Len   : NATURAL;
  20608.     Str   : SP.String_Type;
  20609.     Ret   : BOOLEAN := FALSE;
  20610.  
  20611. begin
  20612.  
  20613.     Check_Not_Yet_Parsed(Proc);
  20614.  
  20615.     HL.Set_Error;
  20616.  
  20617.     TEXT_IO.PUT("Continue with procedure ");
  20618.     TEXT_IO.PUT(SP.Value(Proc.name));
  20619.     TEXT_IO.PUT(" ? (YES|NO) : ");
  20620.  
  20621.     HL.Reset_Error;
  20622.  
  20623.     TEXT_IO.GET_LINE(Reply, Len);
  20624.     if Len = 0 then
  20625.     return Continue(Proc);
  20626.     end if;
  20627.     SP.Mark;
  20628.     if SP.Match_S(SP.Create("YES"), SP.Upper(STRING'(SU.Strip(Reply(1 .. Len))))) = 0 then
  20629.     HL.Set_Error;
  20630.     TEXT_IO.PUT_LINE("Aborting");
  20631.     HL.Reset_Error;
  20632.     else
  20633.     Ret := TRUE;
  20634.     end if;
  20635.     SP.Release;
  20636.     return Ret;
  20637.  
  20638. end Continue;
  20639.  
  20640. ----------------------------------------------------------------
  20641.  
  20642. procedure Define_Output(
  20643.     Proc        : in Process_Handle;
  20644.     File_Name   : in STRING;
  20645.     Header_Size : in Size := 0;
  20646.     Paginate    : in BOOLEAN := TRUE
  20647.     ) is
  20648.  
  20649.     S_Str : SP.String_Type;
  20650.  
  20651. begin
  20652.  
  20653.     if Paginate then
  20654.     PO.Set_Standard_Paginated_File(File_Name, 66, Header_Size + 3, 2);
  20655.     SP.Mark;
  20656.     S_Str := SP."&"((SS.Left_Justify(Proc.name, 50) & ' '), File_Header);
  20657.     PO.Set_Header(2, S_Str);
  20658.     SP.Release;
  20659.     else
  20660.     PO.Set_Standard_Paginated_File(File_Name, 0, 0, 0);
  20661.     end if;
  20662.  
  20663. end Define_Output;
  20664.  
  20665. ----------------------------------------------------------------
  20666.  
  20667. procedure Define_Output(
  20668.     Proc        : in     Process_Handle;
  20669.     File_Name   : in     STRING;
  20670.     Header_Size : in     Size := 0;
  20671.     File_Handle : in out PO.Paginated_File_Handle;
  20672.     Paginate    : in     BOOLEAN := TRUE
  20673.     ) is
  20674.  
  20675.     S_Str : SP.String_Type;
  20676.  
  20677. begin
  20678.  
  20679.     if Paginate then
  20680.     PO.Create_Paginated_File(File_Name, File_Handle, 66, Header_Size + 3, 2);
  20681.     SP.Mark;
  20682.     S_Str := SP."&"((SS.Left_Justify(Proc.name, 50) & ' '), File_Header);
  20683.     PO.Set_Header(File_Handle, 2, S_Str);
  20684.     SP.Release;
  20685.     else
  20686.     PO.Create_Paginated_File(File_Name, File_Handle, 0, 0, 0);
  20687.     end if;
  20688.  
  20689. end Define_Output;
  20690.  
  20691. ----------------------------------------------------------------
  20692.  
  20693. procedure Define_Header(
  20694.     Line : in Number;
  20695.     Text : in STRING
  20696.     ) is
  20697.  
  20698. begin
  20699.  
  20700.     PO.Set_Header(Line + 2, Text);
  20701.  
  20702. end Define_Header;
  20703.  
  20704. ----------------------------------------------------------------
  20705.  
  20706. procedure Define_Header(
  20707.     File_Handle : in PO.Paginated_File_Handle;
  20708.     Line        : in Number;
  20709.     Text        : in STRING
  20710.     ) is
  20711.  
  20712. begin
  20713.  
  20714.     PO.Set_Header(File_Handle, Line + 2, Text);
  20715.  
  20716. end Define_Header;
  20717.                                                                     pragma Page;
  20718. package body Enumerated_Argument is
  20719.  
  20720.     TypeColumn : POSITIVE := 6;
  20721.  
  20722. ----------------------------------------------------------------
  20723.  
  20724.     procedure Define_Argument(
  20725.     Proc    : in Process_Handle;
  20726.     Name    : in STRING;
  20727.     Help    : in STRING
  20728.     ) is
  20729.  
  20730.     Argument : Argument_Handle;
  20731.  
  20732.     begin
  20733.  
  20734.     Argument := Set_Argument(Proc, Name, ENUM, Enum_Type_Name, "", TRUE);
  20735.     if Proc.typecolumn < TypeColumn then
  20736.         Proc.typecolumn := TypeColumn;
  20737.     end if;
  20738.     for i in Enum_Type loop
  20739.         SL.Attach(Argument.valid, SP.Make_Persistent(Enum_Type'image(i)));
  20740.     end loop;
  20741.     Define_Argument_Help(Proc, Name, Help);
  20742.  
  20743.     end Define_Argument;
  20744.  
  20745. ----------------------------------------------------------------
  20746.  
  20747.     procedure Define_Argument(
  20748.     Proc    : in Process_Handle;
  20749.     Name    : in STRING;
  20750.     Default : in Enum_Type;
  20751.     Help    : in STRING
  20752.     ) is
  20753.  
  20754.     Argument : Argument_Handle;
  20755.  
  20756.     begin
  20757.  
  20758.     Argument := Set_Argument(Proc, Name, ENUM, Enum_Type_Name, "", FALSE);
  20759.     if Proc.typecolumn < TypeColumn then
  20760.         Proc.typecolumn := TypeColumn;
  20761.     end if;
  20762.     SL.Attach(Argument.default, SP.Make_Persistent(Enum_Type'image(Default)));
  20763.     for i in Enum_Type loop
  20764.         SL.Attach(Argument.valid, SP.Make_Persistent(Enum_Type'image(i)));
  20765.     end loop;
  20766.     Define_Argument_Help(Proc, Name, Help);
  20767.  
  20768.     end Define_Argument;
  20769.  
  20770. ----------------------------------------------------------------
  20771.  
  20772.     procedure Define_Argument_Help(
  20773.     Proc : in Process_Handle;
  20774.     Name : in STRING;
  20775.     Help : in STRING
  20776.     ) is
  20777.  
  20778.     begin 
  20779.  
  20780.     Destroy_Argument_Help(Proc, Name);
  20781.     Set_Argument_Help(Proc, Name, Help);
  20782.  
  20783.     end Define_Argument_Help;
  20784.  
  20785. ----------------------------------------------------------------
  20786.  
  20787.     procedure Append_Argument_Help(
  20788.     Proc : in Process_Handle;
  20789.     Name : in STRING;
  20790.     Help : in STRING
  20791.     ) is
  20792.  
  20793.     begin 
  20794.  
  20795.     Set_Argument_Help(Proc, Name, Help);
  20796.  
  20797.     end Append_Argument_Help;
  20798.  
  20799. ----------------------------------------------------------------
  20800.  
  20801.     function Get_Argument(
  20802.     Proc : in Process_Handle;
  20803.     Name : in STRING
  20804.     ) return Enum_Type is
  20805.  
  20806.     begin
  20807.  
  20808.     Check_Invalid_Kind(Proc, Name, ENUM);
  20809.     if Get_Argument_Handle(Proc, Name).supplied then
  20810.         return Enum_Type'value(SP.Value(SL.FirstValue(Get_Argument_Handle(Proc, Name).value)));
  20811.     else
  20812.         return Enum_Type'value(SP.Value(SL.FirstValue(Get_Argument_Handle(Proc, Name).default)));
  20813.     end if;
  20814.  
  20815.     end Get_Argument;
  20816.  
  20817. ----------------------------------------------------------------
  20818.  
  20819.     function Get_Default(
  20820.     Proc : in Process_Handle;
  20821.     Name : in STRING
  20822.     ) return Enum_Type is
  20823.  
  20824.     begin
  20825.  
  20826.     Check_Invalid_Kind(Proc, Name, ENUM);
  20827.     if Get_Argument_Handle(Proc, Name).required then
  20828.         raise No_Default;
  20829.     else
  20830.         return Enum_Type'value(SP.Value(SL.FirstValue(Get_Argument_Handle(Proc, Name).default)));
  20831.     end if;
  20832.  
  20833.     end Get_Default;
  20834.  
  20835. ----------------------------------------------------------------
  20836.  
  20837.     function Defaulted(
  20838.     Proc : in Process_Handle;
  20839.     Name : in STRING
  20840.     ) return BOOLEAN is
  20841.  
  20842.     begin
  20843.  
  20844.     Check_Invalid_Kind(Proc, Name, ENUM);
  20845.     return not Get_Argument_Handle(Proc, Name).supplied;
  20846.  
  20847.     end Defaulted;
  20848.  
  20849. ----------------------------------------------------------------
  20850.  
  20851. begin
  20852.  
  20853.     SP.Mark;
  20854.  
  20855.     if SP.Equal(SP.Upper(Enum_Type_Name), "BOOLEAN") then
  20856.     if Enum_Type'pos(Enum_Type'first) /= BOOLEAN'pos(BOOLEAN'first) or
  20857.        Enum_Type'pos(Enum_Type'last) - Enum_Type'pos(Enum_Type'first) /=
  20858.         BOOLEAN'pos(BOOLEAN'last) - BOOLEAN'pos(BOOLEAN'first) then
  20859.         raise Invalid_Type;
  20860.     end if;
  20861.     if Enum_Type'image(Enum_Type'first) /= BOOLEAN'image(BOOLEAN'first) or
  20862.        Enum_Type'image(Enum_Type'last)  /= BOOLEAN'image(BOOLEAN'last) then
  20863.         raise Invalid_Type;
  20864.     end if;
  20865.  
  20866.     elsif SP.Equal(SP.Upper(Enum_Type_Name), "CHARACTER") then
  20867.     if Enum_Type'pos(Enum_Type'last) - Enum_Type'pos(Enum_Type'first) /=
  20868.        CHARACTER'pos(CHARACTER'last) - CHARACTER'pos(CHARACTER'first) then
  20869.         raise Invalid_Type;
  20870.     end if;
  20871.     if Enum_Type'image(Enum_Type'first) /= CHARACTER'image(CHARACTER'first) or
  20872.        Enum_Type'image(Enum_Type'last)  /= CHARACTER'image(CHARACTER'last) then
  20873.         raise Invalid_Type;
  20874.     end if;
  20875.  
  20876.     end if;
  20877.  
  20878.     SP.Release;
  20879.  
  20880. end Enumerated_Argument;
  20881.                                                                     pragma Page;
  20882. package body Enumerated_List_Argument is
  20883.  
  20884.     TypeColumn : POSITIVE := 6;
  20885.  
  20886. ----------------------------------------------------------------
  20887.  
  20888.     procedure Define_Argument(
  20889.     Proc    : in Process_Handle;
  20890.     Name    : in STRING;
  20891.     Help    : in STRING
  20892.     ) is
  20893.  
  20894.     Argument : Argument_Handle;
  20895.  
  20896.     begin
  20897.  
  20898.     Argument := Set_Argument(Proc, Name, ENUM_LIST, Enum_Type_Name, Enum_Type_List, TRUE);
  20899.     if Proc.typecolumn < TypeColumn then
  20900.         Proc.typecolumn := TypeColumn;
  20901.     end if;
  20902.     for i in Enum_Type loop
  20903.         SL.Attach(Argument.valid, SP.Make_Persistent(Enum_Type'image(i)));
  20904.     end loop;
  20905.     Define_Argument_Help(Proc, Name, Help);
  20906.  
  20907.     end Define_Argument;
  20908.  
  20909. ----------------------------------------------------------------
  20910.  
  20911.     procedure Define_Argument(
  20912.     Proc    : in Process_Handle;
  20913.     Name    : in STRING;
  20914.     Default : in Enum_Type_Array;
  20915.     Help    : in STRING
  20916.     ) is
  20917.  
  20918.     Argument : Argument_Handle;
  20919.  
  20920.     begin
  20921.  
  20922.     Argument := Set_Argument(Proc, Name, ENUM_LIST, Enum_Type_Name, Enum_Type_List, FALSE);
  20923.     if Proc.typecolumn < TypeColumn then
  20924.         Proc.typecolumn := TypeColumn;
  20925.     end if;
  20926.     for i in Default'range loop
  20927.         SL.Attach(Argument.default, SP.Make_Persistent(Enum_Type'image(Default(i))));
  20928.     end loop;
  20929.     for i in Enum_Type loop
  20930.         SL.Attach(Argument.valid, SP.Make_Persistent(Enum_Type'image(i)));
  20931.     end loop;
  20932.     Define_Argument_Help(Proc, Name, Help);
  20933.  
  20934.     end Define_Argument;
  20935.  
  20936. ----------------------------------------------------------------
  20937.  
  20938.     procedure Define_Argument_Help(
  20939.     Proc : in Process_Handle;
  20940.     Name : in STRING;
  20941.     Help : in STRING
  20942.     ) is
  20943.  
  20944.     begin 
  20945.  
  20946.     Destroy_Argument_Help(Proc, Name);
  20947.     Set_Argument_Help(Proc, Name, Help);
  20948.  
  20949.     end Define_Argument_Help;
  20950.  
  20951. ----------------------------------------------------------------
  20952.  
  20953.     procedure Append_Argument_Help(
  20954.     Proc : in Process_Handle;
  20955.     Name : in STRING;
  20956.     Help : in STRING
  20957.     ) is
  20958.  
  20959.     begin 
  20960.  
  20961.     Set_Argument_Help(Proc, Name, Help);
  20962.  
  20963.     end Append_Argument_Help;
  20964.  
  20965. ----------------------------------------------------------------
  20966.  
  20967.     function Get_Argument(
  20968.     Proc : in Process_Handle;
  20969.     Name : in STRING
  20970.     ) return EL.List is
  20971.  
  20972.     List     : EL.List := EL.Create;
  20973.     Item     : SP.String_Type;
  20974.     Iterator : SL.ListIter;
  20975.  
  20976.     begin
  20977.  
  20978.     Check_Invalid_Kind(Proc, Name, ENUM_LIST);
  20979.     if Get_Argument_Handle(Proc, Name).supplied then
  20980.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).value);
  20981.     else
  20982.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).default);
  20983.     end if;
  20984.     while SL.More(Iterator) loop
  20985.         SL.Next(Iterator, Item);
  20986.         EL.Attach(List, Enum_Type'value(SP.Value(Item)));
  20987.     end loop;
  20988.     return List;
  20989.  
  20990.     end Get_Argument;
  20991.  
  20992. ----------------------------------------------------------------
  20993.  
  20994.     function Get_Default(
  20995.     Proc : in Process_Handle;
  20996.     Name : in STRING
  20997.     ) return EL.List is
  20998.  
  20999.     List     : EL.List := EL.Create;
  21000.     Item     : SP.String_Type;
  21001.     Iterator : SL.ListIter;
  21002.  
  21003.     begin
  21004.  
  21005.     Check_Invalid_Kind(Proc, Name, ENUM_LIST);
  21006.     if Get_Argument_Handle(Proc, Name).required then
  21007.         raise No_Default;
  21008.     else
  21009.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).default);
  21010.     end if;
  21011.     while SL.More(Iterator) loop
  21012.         SL.Next(Iterator, Item);
  21013.         EL.Attach(List, Enum_Type'value(SP.Value(Item)));
  21014.     end loop;
  21015.     return List;
  21016.  
  21017.     end Get_Default;
  21018.  
  21019. ----------------------------------------------------------------
  21020.  
  21021.     function Defaulted(
  21022.     Proc : in Process_Handle;
  21023.     Name : in STRING
  21024.     ) return BOOLEAN is
  21025.  
  21026.     begin
  21027.  
  21028.     Check_Invalid_Kind(Proc, Name, ENUM_LIST);
  21029.     return not Get_Argument_Handle(Proc, Name).supplied;
  21030.  
  21031.     end Defaulted;
  21032.  
  21033. ----------------------------------------------------------------
  21034.  
  21035. begin
  21036.  
  21037.     SP.Mark;
  21038.  
  21039.     if SP.Equal(SP.Upper(Enum_Type_Name), "BOOLEAN") then
  21040.     if Enum_Type'pos(Enum_Type'first) /= BOOLEAN'pos(BOOLEAN'first) or
  21041.        Enum_Type'pos(Enum_Type'last) - Enum_Type'pos(Enum_Type'first) /=
  21042.         BOOLEAN'pos(BOOLEAN'last) - BOOLEAN'pos(BOOLEAN'first) then
  21043.         raise Invalid_Type;
  21044.     end if;
  21045.     if Enum_Type'image(Enum_Type'first) /= BOOLEAN'image(BOOLEAN'first) or
  21046.        Enum_Type'image(Enum_Type'last)  /= BOOLEAN'image(BOOLEAN'last) then
  21047.         raise Invalid_Type;
  21048.     end if;
  21049.  
  21050.     elsif SP.Equal(SP.Upper(Enum_Type_Name), "CHARACTER") then
  21051.     if Enum_Type'pos(Enum_Type'last) - Enum_Type'pos(Enum_Type'first) /=
  21052.        CHARACTER'pos(CHARACTER'last) - CHARACTER'pos(CHARACTER'first) then
  21053.         raise Invalid_Type;
  21054.     end if;
  21055.     if Enum_Type'image(Enum_Type'first) /= CHARACTER'image(CHARACTER'first) or
  21056.        Enum_Type'image(Enum_Type'last)  /= CHARACTER'image(CHARACTER'last) then
  21057.         raise Invalid_Type;
  21058.     end if;
  21059.  
  21060.     end if;
  21061.  
  21062.     SP.Release;
  21063.  
  21064. end Enumerated_List_Argument;
  21065.                                                                     pragma Page;
  21066. package body Integer_Argument is
  21067.  
  21068.     TypeColumn : POSITIVE := 6;
  21069.  
  21070. ----------------------------------------------------------------
  21071.  
  21072.     procedure Define_Argument(
  21073.     Proc    : in Process_Handle;
  21074.     Name    : in STRING;
  21075.     Help    : in STRING
  21076.     ) is
  21077.  
  21078.     Argument : Argument_Handle;
  21079.  
  21080.     begin
  21081.  
  21082.     Argument := Set_Argument(Proc, Name, INT, Integer_Type_Name, "", TRUE);
  21083.     if Proc.typecolumn < TypeColumn then
  21084.         Proc.typecolumn := TypeColumn;
  21085.     end if;
  21086.     Argument.low  := Integer_Type'pos(Integer_Type'first);
  21087.     Argument.high := Integer_Type'pos(Integer_Type'last);
  21088.     Define_Argument_Help(Proc, Name, Help);
  21089.  
  21090.     end Define_Argument;
  21091.  
  21092. ----------------------------------------------------------------
  21093.  
  21094.     procedure Define_Argument(
  21095.     Proc    : in Process_Handle;
  21096.     Name    : in STRING;
  21097.     Default : in Integer_Type;
  21098.     Help    : in STRING
  21099.     ) is
  21100.  
  21101.     Str      : SP.String_Type;
  21102.     Argument : Argument_Handle;
  21103.  
  21104.     begin
  21105.  
  21106.     Argument := Set_Argument(Proc, Name, INT, Integer_Type_Name, "", FALSE);
  21107.     if Proc.typecolumn < TypeColumn then
  21108.         Proc.typecolumn := TypeColumn;
  21109.     end if;
  21110.     SP.Mark;
  21111.     Str := SS.Image(INTEGER'value(Integer_Type'image(Default)));
  21112.     SL.Attach(Argument.default, SP.Make_Persistent(Str));
  21113.     SP.Release;
  21114.     Argument.low  := Integer_Type'pos(Integer_Type'first);
  21115.     Argument.high := Integer_Type'pos(Integer_Type'last);
  21116.     Define_Argument_Help(Proc, Name, Help);
  21117.  
  21118.  
  21119.     end Define_Argument;
  21120.  
  21121. ----------------------------------------------------------------
  21122.  
  21123.     procedure Define_Argument_Help(
  21124.     Proc : in Process_Handle;
  21125.     Name : in STRING;
  21126.     Help : in STRING
  21127.     ) is
  21128.  
  21129.     begin 
  21130.  
  21131.     Destroy_Argument_Help(Proc, Name);
  21132.     Set_Argument_Help(Proc, Name, Help);
  21133.  
  21134.     end Define_Argument_Help;
  21135.  
  21136. ----------------------------------------------------------------
  21137.  
  21138.     procedure Append_Argument_Help(
  21139.     Proc : in Process_Handle;
  21140.     Name : in STRING;
  21141.     Help : in STRING
  21142.     ) is
  21143.  
  21144.     begin 
  21145.  
  21146.     Set_Argument_Help(Proc, Name, Help);
  21147.  
  21148.     end Append_Argument_Help;
  21149.  
  21150. ----------------------------------------------------------------
  21151.  
  21152.     function Get_Argument(
  21153.     Proc : in Process_Handle;
  21154.     Name : in STRING
  21155.     ) return Integer_Type is
  21156.  
  21157.     begin
  21158.  
  21159.     Check_Invalid_Kind(Proc, Name, INT);
  21160.     if Get_Argument_Handle(Proc, Name).supplied then
  21161.         return Integer_Type'value(SP.Value(SL.FirstValue(Get_Argument_Handle(Proc, Name).value)));
  21162.     else
  21163.         return Integer_Type'value(SP.Value(SL.FirstValue(Get_Argument_Handle(Proc, Name).default)));
  21164.     end if;
  21165.  
  21166.     end Get_Argument;
  21167.  
  21168. ----------------------------------------------------------------
  21169.  
  21170.     function Get_Default(
  21171.     Proc : in Process_Handle;
  21172.     Name : in STRING
  21173.     ) return Integer_Type is
  21174.  
  21175.     begin
  21176.  
  21177.     Check_Invalid_Kind(Proc, Name, INT);
  21178.     if Get_Argument_Handle(Proc, Name).required then
  21179.         raise No_Default;
  21180.     else
  21181.         return Integer_Type'value(SP.Value(SL.FirstValue(Get_Argument_Handle(Proc, Name).default)));
  21182.     end if;
  21183.  
  21184.     end Get_Default;
  21185.  
  21186. ----------------------------------------------------------------
  21187.  
  21188.     function Defaulted(
  21189.     Proc : in Process_Handle;
  21190.     Name : in STRING
  21191.     ) return BOOLEAN is
  21192.  
  21193.     begin
  21194.  
  21195.     Check_Invalid_Kind(Proc, Name, INT);
  21196.     return not Get_Argument_Handle(Proc, Name).supplied;
  21197.  
  21198.     end Defaulted;
  21199.  
  21200. ----------------------------------------------------------------
  21201.  
  21202. begin
  21203.  
  21204.     SP.Mark;
  21205.  
  21206.     if SP.Equal(SP.Upper(Integer_Type_Name), "NATURAL") then
  21207.     if Integer_Type'pos(Integer_Type'first) /= NATURAL'first or
  21208.        Integer_Type'pos(Integer_Type'last)  /= NATURAL'last  then
  21209.         raise Invalid_Type;
  21210.     end if;
  21211.     TypeColumn := 9;
  21212.  
  21213.     elsif SP.Equal(SP.Upper(Integer_Type_Name), "POSITIVE") then
  21214.     if Integer_Type'pos(Integer_Type'first) /= POSITIVE'first or
  21215.        Integer_Type'pos(Integer_Type'last)  /= POSITIVE'last  then
  21216.         raise Invalid_Type;
  21217.     end if;
  21218.     TypeColumn := 9;
  21219.  
  21220.     elsif SP.Equal(SP.Upper(Integer_Type_Name), "INTEGER") then
  21221.     if Integer_Type'pos(Integer_Type'first) /= INTEGER'first or
  21222.        Integer_Type'pos(Integer_Type'last)  /= INTEGER'last  then
  21223.         raise Invalid_Type;
  21224.     end if;
  21225.     TypeColumn := 9;
  21226.  
  21227.     end if;
  21228.  
  21229.     SP.Release;
  21230.  
  21231. end Integer_Argument;
  21232.                                                                     pragma Page;
  21233. package body Integer_List_Argument is
  21234.  
  21235.     TypeColumn : POSITIVE := 6;
  21236.  
  21237. ----------------------------------------------------------------
  21238.  
  21239.     procedure Define_Argument(
  21240.     Proc    : in Process_Handle;
  21241.     Name    : in STRING;
  21242.     Help    : in STRING
  21243.     ) is
  21244.  
  21245.     Argument : Argument_Handle;
  21246.  
  21247.     begin
  21248.  
  21249.     Argument := Set_Argument(Proc, Name, INT_LIST, Integer_Type_Name, Integer_Type_List, TRUE);
  21250.     if Proc.typecolumn < TypeColumn then
  21251.         Proc.typecolumn := TypeColumn;
  21252.     end if;
  21253.     Argument.low  := Integer_Type'pos(Integer_Type'first);
  21254.     Argument.high := Integer_Type'pos(Integer_Type'last);
  21255.     Define_Argument_Help(Proc, Name, Help);
  21256.  
  21257.     end Define_Argument;
  21258.  
  21259. ----------------------------------------------------------------
  21260.  
  21261.     procedure Define_Argument(
  21262.     Proc    : in Process_Handle;
  21263.     Name    : in STRING;
  21264.     Default : in Integer_Type_Array;
  21265.     Help    : in STRING
  21266.     ) is
  21267.  
  21268.     Str      : SP.String_Type;
  21269.     Argument : Argument_Handle;
  21270.  
  21271.     begin
  21272.  
  21273.     Argument := Set_Argument(Proc, Name, INT_LIST, Integer_Type_Name, Integer_Type_List, FALSE);
  21274.     if Proc.typecolumn < TypeColumn then
  21275.         Proc.typecolumn := TypeColumn;
  21276.     end if;
  21277.     for i in Default'range loop
  21278.         SP.Mark;
  21279.         Str := SS.Image(INTEGER'value(Integer_Type'image(Default(i))));
  21280.         SL.Attach(Argument.default, SP.Make_Persistent(Str));
  21281.         SP.Release;
  21282.     end loop;
  21283.     Argument.low  := Integer_Type'pos(Integer_Type'first);
  21284.     Argument.high := Integer_Type'pos(Integer_Type'last);
  21285.     Define_Argument_Help(Proc, Name, Help);
  21286.  
  21287.     end Define_Argument;
  21288.  
  21289. ----------------------------------------------------------------
  21290.  
  21291.     procedure Define_Argument_Help(
  21292.     Proc : in Process_Handle;
  21293.     Name : in STRING;
  21294.     Help : in STRING
  21295.     ) is
  21296.  
  21297.     begin 
  21298.  
  21299.     Destroy_Argument_Help(Proc, Name);
  21300.     Set_Argument_Help(Proc, Name, Help);
  21301.  
  21302.     end Define_Argument_Help;
  21303.  
  21304. ----------------------------------------------------------------
  21305.  
  21306.     procedure Append_Argument_Help(
  21307.     Proc : in Process_Handle;
  21308.     Name : in STRING;
  21309.     Help : in STRING
  21310.     ) is
  21311.  
  21312.     begin 
  21313.  
  21314.     Set_Argument_Help(Proc, Name, Help);
  21315.  
  21316.     end Append_Argument_Help;
  21317.  
  21318. ----------------------------------------------------------------
  21319.  
  21320.     function Get_Argument(
  21321.     Proc : in Process_Handle;
  21322.     Name : in STRING
  21323.     ) return IL.List is
  21324.  
  21325.     List     : IL.List := IL.Create;
  21326.     Item     : SP.String_Type;
  21327.     Iterator : SL.ListIter;
  21328.  
  21329.     begin
  21330.  
  21331.     Check_Invalid_Kind(Proc, Name, INT_LIST);
  21332.     if Get_Argument_Handle(Proc, Name).supplied then
  21333.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).value);
  21334.     else
  21335.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).default);
  21336.     end if;
  21337.     while SL.More(Iterator) loop
  21338.         SL.Next(Iterator, Item);
  21339.         IL.Attach(List, INTEGER'value(SP.Value(Item)));
  21340.     end loop;
  21341.     return List;
  21342.  
  21343.     end Get_Argument;
  21344.  
  21345. ----------------------------------------------------------------
  21346.  
  21347.     function Get_Default(
  21348.     Proc : in Process_Handle;
  21349.     Name : in STRING
  21350.     ) return IL.List is
  21351.  
  21352.     List     : IL.List := IL.Create;
  21353.     Item     : SP.String_Type;
  21354.     Iterator : SL.ListIter;
  21355.  
  21356.     begin
  21357.  
  21358.     Check_Invalid_Kind(Proc, Name, INT_LIST);
  21359.     if Get_Argument_Handle(Proc, Name).required then
  21360.         raise No_Default;
  21361.     else
  21362.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).default);
  21363.     end if;
  21364.     while SL.More(Iterator) loop
  21365.         SL.Next(Iterator, Item);
  21366.         IL.Attach(List, INTEGER'value(SP.Value(Item)));
  21367.     end loop;
  21368.     return List;
  21369.  
  21370.     end Get_Default;
  21371.  
  21372. ----------------------------------------------------------------
  21373.  
  21374.     function Defaulted(
  21375.     Proc : in Process_Handle;
  21376.     Name : in STRING
  21377.     ) return BOOLEAN is
  21378.  
  21379.     begin
  21380.  
  21381.     Check_Invalid_Kind(Proc, Name, INT_LIST);
  21382.     return not Get_Argument_Handle(Proc, Name).supplied;
  21383.  
  21384.     end Defaulted;
  21385.  
  21386. ----------------------------------------------------------------
  21387.  
  21388. begin
  21389.  
  21390.     SP.Mark;
  21391.  
  21392.     if SP.Equal(SP.Upper(Integer_Type_Name), "NATURAL") then
  21393.     if Integer_Type'pos(Integer_Type'first) /= NATURAL'first or
  21394.        Integer_Type'pos(Integer_Type'last)  /= NATURAL'last  then
  21395.         raise Invalid_Type;
  21396.     end if;
  21397.     TypeColumn := 9;
  21398.  
  21399.     elsif SP.Equal(SP.Upper(Integer_Type_Name), "POSITIVE") then
  21400.     if Integer_Type'pos(Integer_Type'first) /= POSITIVE'first or
  21401.        Integer_Type'pos(Integer_Type'last)  /= POSITIVE'last  then
  21402.         raise Invalid_Type;
  21403.     end if;
  21404.     TypeColumn := 9;
  21405.  
  21406.     elsif SP.Equal(SP.Upper(Integer_Type_Name), "INTEGER") then
  21407.     if Integer_Type'pos(Integer_Type'first) /= INTEGER'first or
  21408.        Integer_Type'pos(Integer_Type'last)  /= INTEGER'last  then
  21409.         raise Invalid_Type;
  21410.     end if;
  21411.     TypeColumn := 9;
  21412.  
  21413.     end if;
  21414.  
  21415.     SP.Release;
  21416.  
  21417. end Integer_List_Argument;
  21418.                                                                     pragma Page;
  21419. package body String_Argument is
  21420.  
  21421.     TypeColumn : POSITIVE := 6;
  21422.  
  21423. ----------------------------------------------------------------
  21424.  
  21425.     procedure Define_Argument(
  21426.     Proc    : in Process_Handle;
  21427.     Name    : in STRING;
  21428.     Help    : in STRING
  21429.     ) is
  21430.  
  21431.     Argument : Argument_Handle;
  21432.  
  21433.     begin
  21434.  
  21435.     Argument := Set_Argument(Proc, Name, STR, String_Type_Name, "", TRUE);
  21436.     if Proc.typecolumn < TypeColumn then
  21437.         Proc.typecolumn := TypeColumn;
  21438.     end if;
  21439.     Define_Argument_Help(Proc, Name, Help);
  21440.  
  21441.     end Define_Argument;
  21442.  
  21443. ----------------------------------------------------------------
  21444.  
  21445.     procedure Define_Argument(
  21446.     Proc    : in Process_Handle;
  21447.     Name    : in STRING;
  21448.     Default : in STRING;
  21449.     Help    : in STRING
  21450.     ) is
  21451.  
  21452.     Argument : Argument_Handle;
  21453.  
  21454.     begin
  21455.  
  21456.     Argument := Set_Argument(Proc, Name, STR, String_Type_Name, "", FALSE);
  21457.     if Proc.typecolumn < TypeColumn then
  21458.         Proc.typecolumn := TypeColumn;
  21459.     end if;
  21460.     SL.Attach(Argument.default, SP.Make_Persistent(Default));
  21461.     Define_Argument_Help(Proc, Name, Help);
  21462.  
  21463.     end Define_Argument;
  21464.  
  21465. ----------------------------------------------------------------
  21466.  
  21467.     procedure Define_Argument_Help(
  21468.     Proc : in Process_Handle;
  21469.     Name : in STRING;
  21470.     Help : in STRING
  21471.     ) is
  21472.  
  21473.     begin 
  21474.  
  21475.     Destroy_Argument_Help(Proc, Name);
  21476.     Set_Argument_Help(Proc, Name, Help);
  21477.  
  21478.     end Define_Argument_Help;
  21479.  
  21480. ----------------------------------------------------------------
  21481.  
  21482.     procedure Append_Argument_Help(
  21483.     Proc : in Process_Handle;
  21484.     Name : in STRING;
  21485.     Help : in STRING
  21486.     ) is
  21487.  
  21488.     begin 
  21489.  
  21490.     Set_Argument_Help(Proc, Name, Help);
  21491.  
  21492.     end Append_Argument_Help;
  21493.  
  21494. ----------------------------------------------------------------
  21495.  
  21496.     function Get_Argument(
  21497.     Proc : in Process_Handle;
  21498.     Name : in STRING
  21499.     ) return SP.String_Type is
  21500.  
  21501.     begin
  21502.  
  21503.     Check_Invalid_Kind(Proc, Name, STR);
  21504.     if Get_Argument_Handle(Proc, Name).supplied then
  21505.         return SP.Make_Persistent(SL.FirstValue(Get_Argument_Handle(Proc, Name).value));
  21506.     else
  21507.         return SP.Make_Persistent(SL.FirstValue(Get_Argument_Handle(Proc, Name).default));
  21508.     end if;
  21509.  
  21510.     end Get_Argument;
  21511.  
  21512. ----------------------------------------------------------------
  21513.  
  21514.     function Get_Default(
  21515.     Proc : in Process_Handle;
  21516.     Name : in STRING
  21517.     ) return SP.String_Type is
  21518.  
  21519.     begin
  21520.  
  21521.     Check_Invalid_Kind(Proc, Name, STR);
  21522.     if Get_Argument_Handle(Proc, Name).required then
  21523.         raise No_Default;
  21524.     else
  21525.         return SP.Make_Persistent(SL.FirstValue(Get_Argument_Handle(Proc, Name).default));
  21526.     end if;
  21527.  
  21528.     end Get_Default;
  21529.  
  21530. ----------------------------------------------------------------
  21531.  
  21532.     function Defaulted(
  21533.     Proc : in Process_Handle;
  21534.     Name : in STRING
  21535.     ) return BOOLEAN is
  21536.  
  21537.     begin
  21538.  
  21539.     Check_Invalid_Kind(Proc, Name, STR);
  21540.     return not Get_Argument_Handle(Proc, Name).supplied;
  21541.  
  21542.     end Defaulted;
  21543.  
  21544. ----------------------------------------------------------------
  21545.  
  21546. begin
  21547.  
  21548.     SP.Mark;
  21549.  
  21550.     if not SP.Equal(SP.Upper(String_Type_Name), "STRING") then
  21551.     TypeColumn := 9;
  21552.     end if;
  21553.  
  21554.     SP.Release;
  21555.  
  21556. end String_Argument;
  21557.                                                                     pragma Page;
  21558. package body String_List_Argument is
  21559.  
  21560.     TypeColumn : POSITIVE := 6;
  21561.  
  21562. ----------------------------------------------------------------
  21563.  
  21564.     procedure Define_Argument(
  21565.     Proc    : in Process_Handle;
  21566.     Name    : in STRING;
  21567.     Help    : in STRING
  21568.     ) is
  21569.  
  21570.     Argument : Argument_Handle;
  21571.  
  21572.     begin
  21573.  
  21574.     Argument := Set_Argument(Proc, Name, STR_LIST, String_Type_Name, String_Type_List, TRUE);
  21575.     if Proc.typecolumn < TypeColumn then
  21576.         Proc.typecolumn := TypeColumn;
  21577.     end if;
  21578.     Define_Argument_Help(Proc, Name, Help);
  21579.  
  21580.     end Define_Argument;
  21581.  
  21582. ----------------------------------------------------------------
  21583.  
  21584.     procedure Define_Argument(
  21585.     Proc    : in Process_Handle;
  21586.     Name    : in STRING;
  21587.     Default : in SL.List;
  21588.     Help    : in STRING
  21589.     ) is
  21590.  
  21591.     Argument : Argument_Handle;
  21592.     Def_Iter : SL.ListIter;
  21593.     Def_Val  : SP.String_Type;
  21594.  
  21595.     begin
  21596.  
  21597.     Argument := Set_Argument(Proc, Name, STR_LIST, String_Type_Name, String_Type_List, FALSE);
  21598.     if Proc.typecolumn < TypeColumn then
  21599.         Proc.typecolumn := TypeColumn;
  21600.     end if;
  21601.     Def_Iter := SL.MakeListIter(Default);
  21602.     while SL.More(Def_Iter) loop
  21603.         SL.Next(Def_Iter, Def_Val);
  21604.         SL.Attach(Argument.default, SP.Make_Persistent(Def_Val));
  21605.     end loop;
  21606.     Define_Argument_Help(Proc, Name, Help);
  21607.  
  21608.     end Define_Argument;
  21609.  
  21610. ----------------------------------------------------------------
  21611.  
  21612.     procedure Define_Argument_Help(
  21613.     Proc : in Process_Handle;
  21614.     Name : in STRING;
  21615.     Help : in STRING
  21616.     ) is
  21617.  
  21618.     begin 
  21619.  
  21620.     Destroy_Argument_Help(Proc, Name);
  21621.     Set_Argument_Help(Proc, Name, Help);
  21622.  
  21623.     end Define_Argument_Help;
  21624.  
  21625. ----------------------------------------------------------------
  21626.  
  21627.     procedure Append_Argument_Help(
  21628.     Proc : in Process_Handle;
  21629.     Name : in STRING;
  21630.     Help : in STRING
  21631.     ) is
  21632.  
  21633.     begin 
  21634.  
  21635.     Set_Argument_Help(Proc, Name, Help);
  21636.  
  21637.     end Append_Argument_Help;
  21638.  
  21639. ----------------------------------------------------------------
  21640.  
  21641.     function Get_Argument(
  21642.     Proc : in Process_Handle;
  21643.     Name : in STRING
  21644.     ) return SL.List is
  21645.  
  21646.     List     : SL.List := SL.Create;
  21647.     Item     : SP.String_Type;
  21648.     Iterator : SL.ListIter;
  21649.  
  21650.     begin
  21651.  
  21652.     Check_Invalid_Kind(Proc, Name, STR_LIST);
  21653.     if Get_Argument_Handle(Proc, Name).supplied then
  21654.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).value);
  21655.     else
  21656.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).default);
  21657.     end if;
  21658.     while SL.More(Iterator) loop
  21659.         SL.Next(Iterator, Item);
  21660.         SL.Attach(List, Item);
  21661.     end loop;
  21662.     return List;
  21663.  
  21664.     end Get_Argument;
  21665.  
  21666. ----------------------------------------------------------------
  21667.  
  21668.     function Get_Default(
  21669.     Proc : in Process_Handle;
  21670.     Name : in STRING
  21671.     ) return SL.List is
  21672.  
  21673.     List     : SL.List := SL.Create;
  21674.     Item     : SP.String_Type;
  21675.     Iterator : SL.ListIter;
  21676.  
  21677.     begin
  21678.  
  21679.     Check_Invalid_Kind(Proc, Name, STR_LIST);
  21680.     if Get_Argument_Handle(Proc, Name).required then
  21681.         raise No_Default;
  21682.     else
  21683.         Iterator := SL.MakeListIter(Get_Argument_Handle(Proc, Name).default);
  21684.     end if;
  21685.     while SL.More(Iterator) loop
  21686.         SL.Next(Iterator, Item);
  21687.         SL.Attach(List, Item);
  21688.     end loop;
  21689.     return List;
  21690.  
  21691.     end Get_Default;
  21692.  
  21693. ----------------------------------------------------------------
  21694.  
  21695.     function Defaulted(
  21696.     Proc : in Process_Handle;
  21697.     Name : in STRING
  21698.     ) return BOOLEAN is
  21699.  
  21700.     begin
  21701.  
  21702.     Check_Invalid_Kind(Proc, Name, STR_LIST);
  21703.     return not Get_Argument_Handle(Proc, Name).supplied;
  21704.  
  21705.     end Defaulted;
  21706.  
  21707. ----------------------------------------------------------------
  21708.  
  21709. begin
  21710.  
  21711.     SP.Mark;
  21712.  
  21713.     if not SP.Equal(SP.Upper(String_Type_Name), "STRING") then
  21714.     TypeColumn := 9;
  21715.     end if;
  21716.  
  21717.     SP.Release;
  21718.  
  21719. end String_List_Argument;
  21720.                                                                     pragma Page;
  21721. package body Command_Line is
  21722.  
  21723. ----------------------------------------------------------------
  21724.  
  21725.     procedure Show_Command_Help(
  21726.     Handles : in Process_Handle_Array
  21727.     ) is
  21728.  
  21729.     begin
  21730.  
  21731.     Short_Help := TRUE;
  21732.     New_Line(1);
  21733.     for i in Command_Enumeration loop
  21734.         Show_Help(Handles(i));
  21735.     end loop;
  21736.     New_Line(1);
  21737.     Short_Help := FALSE;
  21738.  
  21739.     end Show_Command_Help;
  21740.  
  21741. ----------------------------------------------------------------
  21742.  
  21743.     function Parse_Command_Line(
  21744.     Handles : in Process_Handle_Array;
  21745.     Line    : in STRING
  21746.     ) return Command_Enumeration is
  21747.  
  21748.     Scanner : SU.Scanner;
  21749.     Found   : BOOLEAN;
  21750.     Cmd     : SP.String_Type;
  21751.     Arg     : SP.String_Type;
  21752.     Command : Command_Enumeration;
  21753.     
  21754.     begin
  21755.  
  21756.     if SU.Strip(Line) = "" then
  21757.         if Command_Switches(Show_Help_on_Null) = ON then
  21758.         Show_Command_Help(Handles);
  21759.         end if;
  21760.         raise No_Command;
  21761.     end if;
  21762.  
  21763.     SP.Mark;
  21764.     Scanner := SU.Make_Scanner(SU.Strip(Line));
  21765.     if SU.Is_Ada_Id(Scanner) then
  21766.         SS.Scan_Ada_Id(Scanner, Found, Cmd);
  21767.     else
  21768.         SS.Scan_Word(Scanner, Found, Cmd);
  21769.     end if;
  21770.     declare
  21771.         Command_String : STRING (1 .. SP.Length(Cmd)) := SP.Value(SP.Upper(Cmd));
  21772.     begin
  21773.         SP.Flush(Cmd);
  21774.         Command := Command_Enumeration'value(Command_String);
  21775.         SU.Skip_Space(Scanner);
  21776.         Arg := SS.Get_Remainder(Scanner);
  21777.         SU.Destroy_Scanner(Scanner);
  21778.         Parse_Line(Handles(Command), SP.Value(Arg));
  21779.         SP.Flush(Arg);
  21780.         SP.Release;
  21781.         return Command;
  21782.     exception
  21783.         when CONSTRAINT_ERROR =>
  21784.         SU.Destroy_Scanner(Scanner);
  21785.         if Command_String = "EXIT" then
  21786.             SP.Release;
  21787.             raise Command_Exit;
  21788.         elsif Command_String = "HELP" then
  21789.             if Command_Switches(Show_Help) = ON then
  21790.             Show_Command_Help(Handles);
  21791.             end if;
  21792.             SP.Release;
  21793.             raise Command_Help;
  21794.         else
  21795.             if Command_Switches(Show_Error) = ON then
  21796.             Report_Error(Invalid_Command, Value=>Command_String);
  21797.             end if;
  21798.             if Command_Switches(Show_Help_on_Error) = ON then
  21799.             Show_Command_Help(Handles);
  21800.             end if;
  21801.             SP.Release;
  21802.             raise Abort_Command;
  21803.         end if;
  21804.     end;
  21805.     raise Internal_Error;
  21806.  
  21807.     end Parse_Command_Line;    
  21808.  
  21809. end Command_Line;
  21810.                                                                     pragma Page;
  21811. ----------------------- Local Subprogams -----------------------
  21812.  
  21813. function Release return STRING is separate;
  21814.  
  21815. ----------------------------------------------------------------
  21816.  
  21817. procedure Check_ID is
  21818.  
  21819. begin
  21820.  
  21821.     if not Set_ID then
  21822.     raise Identifier_Error;
  21823.     end if;
  21824.  
  21825. end Check_ID;
  21826.  
  21827. ----------------------------------------------------------------
  21828.  
  21829. procedure Check_Uninitialized(
  21830.     Proc : in Process_Handle
  21831.     ) is
  21832.  
  21833. begin
  21834.  
  21835.     if Proc = null then
  21836.     Short_Help := FALSE;
  21837.     raise Uninitialized;
  21838.     end if;
  21839.  
  21840. end Check_Uninitialized;
  21841.  
  21842. ----------------------------------------------------------------
  21843.  
  21844. procedure Check_Already_Exists(
  21845.     Proc : in Process_Handle
  21846.     ) is
  21847.  
  21848. begin
  21849.  
  21850.     if Proc /= null then
  21851.     raise Already_Exists;
  21852.     end if;
  21853.  
  21854. end Check_Already_Exists;
  21855.  
  21856. ----------------------------------------------------------------
  21857.  
  21858. procedure Check_Invalid_Name(
  21859.     Name : in STRING
  21860.     ) is
  21861.  
  21862.     Scanner : SU.Scanner;
  21863.     Str     : SP.String_Type;
  21864.     Found   : BOOLEAN;
  21865.  
  21866. begin
  21867.  
  21868.     SP.Mark;
  21869.     Scanner := SS.Make_Scanner(SP.Create(Name));
  21870.     SS.Scan_Ada_Id(Scanner, Found, Str);
  21871.     SP.Release;
  21872.     if Found then
  21873.     SP.Flush(Str);
  21874.     if SU.More(Scanner) then
  21875.         Found := FALSE;
  21876.     end if;
  21877.     end if;
  21878.     if not Found then
  21879.     raise Invalid_Name;
  21880.     end if;
  21881.  
  21882. end Check_Invalid_Name;
  21883.  
  21884. ----------------------------------------------------------------
  21885.  
  21886. procedure Check_Undefined_Name(
  21887.     Proc : in Process_Handle;
  21888.     Name : in STRING
  21889.     ) is
  21890.  
  21891.     Item : Argument_Handle;
  21892.  
  21893. begin
  21894.  
  21895.     Check_Uninitialized(Proc);
  21896.     Check_Invalid_Name(Name);
  21897.     Item := Find_Match(Proc, Name);
  21898.     if Item = null then
  21899.     raise Undefined_Name;
  21900.     end if;
  21901.  
  21902. end Check_Undefined_Name;
  21903.  
  21904. ----------------------------------------------------------------
  21905.  
  21906. procedure Check_Duplicate_Name(
  21907.     Proc : in Process_Handle;
  21908.     Name : in STRING
  21909.     ) is
  21910.  
  21911. begin
  21912.  
  21913.     Check_Undefined_Name(Proc, Name);
  21914.     raise Duplicate_Name;
  21915.  
  21916. exception
  21917.     when Undefined_Name =>
  21918.     null;
  21919.  
  21920. end Check_Duplicate_Name;
  21921.  
  21922. ----------------------------------------------------------------
  21923.  
  21924. procedure Check_Not_Yet_Parsed(
  21925.     Proc : in Process_Handle
  21926.     ) is
  21927.  
  21928. begin
  21929.  
  21930.     Check_Uninitialized(Proc);
  21931.     if not Proc.parsed then
  21932.     raise Not_Yet_Parsed;
  21933.     end if;
  21934.  
  21935. end Check_Not_Yet_Parsed;
  21936.  
  21937. ----------------------------------------------------------------
  21938.  
  21939. procedure Check_Already_Parsed(
  21940.     Proc : in Process_Handle
  21941.     ) is
  21942.  
  21943. begin
  21944.  
  21945.     Check_Uninitialized(Proc);
  21946.     if Proc.parsed then
  21947.     raise Already_Parsed;
  21948.     end if;
  21949.  
  21950. end Check_Already_Parsed;
  21951.  
  21952. ----------------------------------------------------------------
  21953.  
  21954. procedure Check_Invalid_Kind(
  21955.     Proc : in Process_Handle;
  21956.     Name : in STRING;
  21957.     Kind : in Argument_Kind
  21958.     ) is
  21959.  
  21960. begin
  21961.  
  21962.     Check_Undefined_Name(Proc, Name);
  21963.     Check_Not_Yet_Parsed(Proc);
  21964.     if Get_Argument_Handle(Proc, Name).kind /= Kind then
  21965.     raise Invalid_Kind;
  21966.     end if;
  21967.  
  21968. end Check_Invalid_Kind;
  21969.  
  21970. ----------------------------------------------------------------
  21971.  
  21972. procedure Write(
  21973.     Text  : in STRING
  21974.     ) is
  21975.  
  21976. begin
  21977.  
  21978.     TEXT_IO.PUT_LINE(Text);
  21979.  
  21980. end Write;
  21981.  
  21982. ----------------------------------------------------------------
  21983.  
  21984. procedure New_Line(
  21985.     Count : in POSITIVE
  21986.     ) is
  21987.  
  21988. begin
  21989.  
  21990.     TEXT_IO.NEW_LINE(TEXT_IO.POSITIVE_COUNT(Count));
  21991.  
  21992. end New_Line;
  21993.  
  21994. ----------------------------------------------------------------
  21995.  
  21996. procedure Write_List_Vertical(
  21997.     Header  : in STRING;
  21998.     List    : in SL.List
  21999.     ) is
  22000.  
  22001.     B_Str : SP.String_Type;
  22002.     Iter  : SL.ListIter;
  22003.     Done  : BOOLEAN := FALSE;
  22004.  
  22005. begin
  22006.  
  22007.     TEXT_IO.PUT("-- ");
  22008.     TEXT_IO.PUT(Header);
  22009.     Iter := SL.MakeListIter(List);
  22010.     while SL.More(Iter) loop
  22011.     SP.Mark;
  22012.     SL.Next(Iter, B_Str);
  22013.     if Done then
  22014.         TEXT_IO.PUT("-- ");
  22015.         declare
  22016.         Blanks : STRING (1 .. Header'length) := (others => ' ');
  22017.         begin
  22018.         TEXT_IO.PUT(Blanks);
  22019.         end;
  22020.     else
  22021.         Done := TRUE;
  22022.     end if;
  22023.     begin
  22024.         Write(SP.Value(B_Str));
  22025.         SP.Release;
  22026.     exception
  22027.         when others =>
  22028.         SP.Release;
  22029.         raise;
  22030.     end;
  22031.     end loop;
  22032.     if not Done then
  22033.     New_Line(1);
  22034.     end if;
  22035.  
  22036. end Write_List_Vertical;
  22037.  
  22038. ----------------------------------------------------------------
  22039.  
  22040. procedure Write_List_Horizontal(
  22041.     List    : in SL.List;
  22042.     Quoted  : in BOOLEAN := FALSE
  22043.     ) is
  22044.  
  22045.     B_Str : SP.String_Type;
  22046.     Iter  : SL.ListIter;
  22047.     First : BOOLEAN := TRUE;
  22048.  
  22049. begin
  22050.  
  22051.     Iter := SL.MakeListIter(List);
  22052.     while SL.More(Iter) loop
  22053.     if not First then
  22054.         TEXT_IO.PUT(SP.Fetch(Delimiter, 1) & " ");
  22055.     else
  22056.         First := FALSE;
  22057.     end if;
  22058.     SP.Mark;
  22059.     SL.Next(Iter, B_Str);
  22060.     if Quoted then
  22061.         B_Str := SP."&"("""", B_Str);
  22062.         B_Str := SP."&"(B_STR, """");
  22063.     end if;
  22064.     TEXT_IO.PUT(SP.Value(B_Str));
  22065.     SP.Release;
  22066.     end loop;
  22067.  
  22068. end Write_List_Horizontal;
  22069.  
  22070. ----------------------------------------------------------------
  22071.  
  22072. function Find_Match(
  22073.     Proc : in Process_Handle;
  22074.     Name : in STRING
  22075.     ) return Argument_Handle is
  22076.  
  22077.     Iterator : AL.ListIter;
  22078.     Item     : Argument_Handle;
  22079.  
  22080. begin
  22081.  
  22082.     Iterator := AL.MakeListIter(Proc.args);
  22083.     while AL.More(Iterator) loop
  22084.     AL.Next(Iterator, Item);
  22085.     if SP.Equal(Item.name, SP.Upper(Name)) then
  22086.         return Item;
  22087.     end if;
  22088.     end loop;
  22089.     return null;
  22090.  
  22091. end Find_Match;
  22092.  
  22093. ----------------------------------------------------------------
  22094.  
  22095. function Get_Argument_Handle(
  22096.     Proc : in Process_Handle;
  22097.     Name : in STRING
  22098.     ) return Argument_Handle is
  22099.  
  22100.     Item     : Argument_Handle;
  22101.  
  22102. begin
  22103.  
  22104.     Check_Invalid_Name(Name);
  22105.     Check_Undefined_Name(Proc, Name);
  22106.     return Find_Match(Proc, Name);
  22107.  
  22108. end Get_Argument_Handle;
  22109.  
  22110. ----------------------------------------------------------------
  22111.  
  22112. procedure Destroy_Argument_Help(
  22113.     Proc : in Process_Handle;
  22114.     Name : in STRING
  22115.     ) is
  22116.  
  22117.     Iterator : AL.ListIter;
  22118.     Item     : Argument_Handle;
  22119.  
  22120. begin
  22121.  
  22122.     Check_Invalid_Name(Name);
  22123.     Check_Already_Parsed(Proc);
  22124.     Iterator := AL.MakeListIter(Proc.args);
  22125.     while AL.More(Iterator) loop
  22126.     AL.Next(Iterator, Item);
  22127.     if SP.Equal(Item.name, SP.Upper(Name)) then
  22128.         Destroy_String_List(Item.help);
  22129.         Item.help := SL.Create;
  22130.         return;
  22131.     end if;
  22132.     end loop;
  22133.     raise Undefined_Name;
  22134.  
  22135. end Destroy_Argument_Help;
  22136.  
  22137. ----------------------------------------------------------------
  22138.  
  22139. procedure Set_Argument_Help(
  22140.     Proc : in Process_Handle;
  22141.     Name : in STRING;
  22142.     Help : in STRING
  22143.     ) is
  22144.  
  22145.     Iterator : AL.ListIter;
  22146.     Item     : Argument_Handle;
  22147.  
  22148. begin
  22149.  
  22150.     Check_Invalid_Name(Name);
  22151.     Check_Already_Parsed(Proc);
  22152.     Iterator := AL.MakeListIter(Proc.args);
  22153.     while AL.More(Iterator) loop
  22154.     AL.Next(Iterator, Item);
  22155.     if SP.Equal(Item.name, SP.Upper(Name)) then
  22156.         SL.Attach(Item.help, SP.Make_Persistent(Help));
  22157.         return;
  22158.     end if;
  22159.     end loop;
  22160.     raise Undefined_Name;
  22161.  
  22162. end Set_Argument_Help;
  22163.  
  22164. ----------------------------------------------------------------
  22165.  
  22166. function Set_Argument(
  22167.     Proc     : in     Process_Handle;
  22168.     Name     : in     STRING;
  22169.     Kind     : in     Argument_Kind;
  22170.     Typename : in     STRING;
  22171.     Listname : in     STRING;
  22172.     Required : in     BOOLEAN
  22173.     ) return Argument_Handle is
  22174.  
  22175.     Argument : Argument_Handle;
  22176.  
  22177. begin
  22178.  
  22179.     Check_Duplicate_Name(Proc, Name);
  22180.     Check_Invalid_Name(Typename);
  22181.     if Listname /= "" then
  22182.     Check_Invalid_Name(Listname);
  22183.     end if;
  22184.     Check_Already_Parsed(Proc);
  22185.  
  22186.     Argument          := new Argument_Record;
  22187.     SP.Mark;
  22188.     Argument.name     := SP.Make_Persistent(SP.Upper(Name));
  22189.     Argument.typename := SP.Make_Persistent(SP.Upper(Typename));
  22190.     Argument.listname := SP.Make_Persistent(SP.Upper(Listname));
  22191.     Argument.required := Required;
  22192.     Argument.kind     := Kind;
  22193.     AL.Attach(Proc.args, Argument);
  22194.     SP.Release;
  22195.  
  22196.     if Proc.maxname < Name'length then
  22197.     Proc.maxname := Name'length;
  22198.     end if;
  22199.  
  22200.     if Proc.maxtypename < Typename'length then
  22201.     case Kind is
  22202.         when ENUM | ENUM_LIST =>
  22203.         if not SP.Equal(Argument.typename, "BOOLEAN") and
  22204.            not SP.Equal(Argument.typename, "CHARACTER") then
  22205.             Proc.maxtypename := Typename'length;
  22206.         end if;
  22207.         when INT  | INT_LIST =>
  22208.         if not SP.Equal(Argument.typename, "INTEGER") and
  22209.            not SP.Equal(Argument.typename, "POSITIVE") and
  22210.            not SP.Equal(Argument.typename, "NATURAL") then
  22211.             Proc.maxtypename := Typename'length;
  22212.         end if;
  22213.         when STR | STR_LIST =>
  22214.         if not SP.Equal(Argument.typename, "STRING") then
  22215.             Proc.maxtypename := Typename'length;
  22216.         end if;
  22217.     end case;
  22218.     end if;
  22219.  
  22220.     case Kind is
  22221.     when ENUM | INT | STR =>
  22222.         if Proc.maxtype < Typename'length then
  22223.            Proc.maxtype := Typename'length;
  22224.         end if;
  22225.     when ENUM_LIST | INT_LIST | STR_LIST =>
  22226.         if Proc.maxtype < Listname'length then
  22227.            Proc.maxtype := Listname'length;
  22228.         end if;
  22229.         if Proc.maxtypename < Listname'length then
  22230.         Proc.maxtypename := Listname'length;
  22231.         end if;
  22232.     end case;
  22233.  
  22234.     return Argument;
  22235.  
  22236. end Set_Argument;
  22237.  
  22238. ----------------------------------------------------------------
  22239.  
  22240. procedure Point_Next_Token(
  22241.     Scanner : in SU.Scanner
  22242.     ) is
  22243.  
  22244. begin
  22245.  
  22246.     SU.Skip_Space(Scanner);
  22247.     if SU.More(Scanner) and then SS.Is_Sequence(Delimiter, Scanner) then
  22248.     SU.Forward(Scanner);
  22249.     SU.Skip_Space(Scanner);
  22250.     end if;
  22251.  
  22252. end Point_Next_Token;
  22253.  
  22254. ----------------------------------------------------------------
  22255.  
  22256. procedure Get_Next_Token(
  22257.     Scanner : in     SU.Scanner;
  22258.     Kind    :    out Token_Kind;
  22259.     Token   : in out SP.String_Type
  22260.     ) is
  22261.  
  22262.     S_Str    : SP.String_Type;
  22263.     Scan_Arg : SU.Scanner;
  22264.     Found    : BOOLEAN;
  22265.     Inx1     : POSITIVE;
  22266.     Inx2     : POSITIVE;
  22267.  
  22268. begin
  22269.  
  22270.     if not SU.More(Scanner) then
  22271.     Kind := DONE;
  22272.     return;
  22273.     end if;
  22274.  
  22275.     if SU.Is_Quoted(Scanner) or SU.Is_Enclosed(Left_Enclosure, Right_Enclosure, Scanner) then
  22276.     Inx1 := SU.Position(Scanner);
  22277.     SU.Mark(Scanner);
  22278.     SS.Scan_Quoted(Scanner, Found, S_Str);
  22279.     if not Found then
  22280.         SS.Scan_Enclosed(Left_Enclosure, Right_Enclosure, Scanner, Found, S_Str);
  22281.     end if;
  22282.     if not SS.Is_Sequence(Delimiter, Scanner) and not SS.Is_Literal(Assignment, Scanner) then
  22283.         SU.Skip_Space(Scanner);
  22284.     end if;
  22285.     if not SS.Is_Sequence(Delimiter, Scanner) and not SS.Is_Literal(Assignment, Scanner) then
  22286.         while not SS.Is_Sequence(Delimiter, Scanner) and
  22287.           not SS.Is_Literal(Assignment, Scanner) loop
  22288.         SU.Forward(Scanner);
  22289.         end loop;
  22290.         SU.Unmark(Scanner);
  22291.         Inx2 := SU.Position(Scanner);
  22292.         S_Str := SS.Get_String(Scanner);
  22293.         Token := SP.Make_Persistent(SP.Substr(S_Str, Inx1, Inx2 - Inx1));
  22294.         SP.Flush(S_Str);
  22295.         if SS.Is_Literal(Assignment, Scanner) then
  22296.         Kind := NAME;
  22297.         else
  22298.         Kind := VALUE;
  22299.         end if;
  22300.         return;
  22301.     end if;
  22302.     SU.Restore(Scanner);
  22303.     end if;
  22304.  
  22305.  
  22306.     SP.Mark;
  22307.     if SU.Is_Quoted(Scanner) then
  22308.     SS.Scan_Quoted(Scanner, Found, Token);
  22309.     Kind := QUOTED;
  22310.     elsif SU.Is_Enclosed(Left_Enclosure, Right_Enclosure, Scanner) then
  22311.     SS.Scan_Enclosed(Left_Enclosure, Right_Enclosure, Scanner, Found, S_Str);
  22312.     Token := SP.Make_Persistent(STRING'(SS.Strip(S_Str)));
  22313.     Kind := LIST;
  22314.     SP.Flush(S_Str);
  22315.     elsif SS.Is_Not_Sequence(Delimiter, Scanner) then
  22316.     SU.Mark(Scanner);
  22317.     SS.Scan_Not_Sequence(Delimiter, Scanner, Found, S_Str);
  22318.     Scan_Arg := SS.Make_Scanner(S_Str);        
  22319.     SP.Flush(S_Str);
  22320.     SU.Restore(Scanner);
  22321.     if SS.Is_Literal(Assignment, Scan_Arg) then
  22322.         SS.Scan_Literal(Assignment, Scanner, Found);
  22323.         Kind := BIND;
  22324.     elsif SS.Is_Not_Literal(Assignment, Scan_Arg) then
  22325.         SS.Scan_Not_Literal(Assignment, Scanner, Found, S_Str);
  22326.         Kind := NAME;
  22327.         Token := SP.Make_Persistent(STRING'(SS.Strip_Trailing(S_Str)));
  22328.         SP.Flush(S_Str);
  22329.     else
  22330.         SS.Scan_Not_Sequence(Delimiter, Scanner, Found, S_Str);
  22331.         SU.Skip_Space(Scanner);
  22332.         if SS.Is_Literal(Assignment, Scanner) then
  22333.         Kind := NAME;
  22334.         else
  22335.         Kind := VALUE;
  22336.         end if;
  22337.         Token := SP.Make_Persistent(STRING'(SS.Strip_Trailing(S_Str)));
  22338.         SP.Flush(S_Str);
  22339.     end if;
  22340.     SU.Destroy_Scanner(Scan_Arg);
  22341.     else
  22342.     Kind := NONE;
  22343.     end if;
  22344.     Point_Next_Token(Scanner);
  22345.     SP.Release;
  22346.  
  22347. end Get_Next_Token;
  22348.  
  22349. ----------------------------------------------------------------
  22350.  
  22351. procedure Parse_Argument(
  22352.     Argument : in Argument_Handle;
  22353.     Item     : in SP.String_Type;
  22354.     Kind     : in Token_Kind
  22355.     ) is
  22356.  
  22357.     Iterator   : SL.ListIter;
  22358.     Num        : INTEGER;
  22359.     R_Str      : SP.String_Type;
  22360.     S_Str      : SP.String_Type;
  22361.     Element    : SP.String_Type;
  22362.     Scanner    : SU.Scanner;
  22363.     Found      : BOOLEAN;
  22364.     First      : BOOLEAN;
  22365.     List_Error : BOOLEAN := FALSE;
  22366.  
  22367. begin
  22368.  
  22369.     case Argument.kind is
  22370.  
  22371.     when ENUM =>
  22372.         if Kind = VALUE then
  22373.         Iterator := SL.MakeListIter(Argument.valid);
  22374.         while SL.More(Iterator) loop
  22375.             SL.Next(Iterator, R_Str);
  22376.             if SP.Equal(SP.Upper(Item), R_Str) then
  22377.             SL.Attach(Argument.value, SP.Make_Persistent(R_Str));
  22378.             Argument.supplied := TRUE;
  22379.             return;
  22380.             end if;
  22381.         end loop;
  22382.         end if;
  22383.  
  22384.     when INT => 
  22385.         if Kind = VALUE then
  22386.         begin
  22387.             Num := INTEGER'value(SP.Value(Item));
  22388.             if Argument.low <= Num and Num <= Argument.high then
  22389.             SL.Attach(Argument.value, SP.Make_Persistent(Item));
  22390.             Argument.supplied := TRUE;
  22391.             return;
  22392.             end if;
  22393.         exception
  22394.             when CONSTRAINT_ERROR =>
  22395.             null;
  22396.         end;
  22397.         end if;
  22398.  
  22399.     when STR =>
  22400.         if Kind = QUOTED or Parsing_Switches(Quote_Enclosure) = OFF then
  22401.         SL.Attach(Argument.value, SP.Make_Persistent(Item));
  22402.         Argument.supplied := TRUE;
  22403.         return;
  22404.         else
  22405.         Report_Error(Missing_Quotes, Value=>SP.Value(Item));
  22406.         end if;
  22407.  
  22408.     when ENUM_LIST =>
  22409.         if Kind = LIST or
  22410.           (Parsing_Switches(Argument_Enclosure) = OFF and Kind = VALUE) then
  22411.         Scanner := SS.Make_Scanner(SP."&"(Item, "" & SP.Fetch(Delimiter, 1)));
  22412.         First := TRUE;
  22413.         while SU.More(Scanner) loop
  22414.             SS.Scan_Not_Sequence(Delimiter, Scanner, Found, Element, Skip => TRUE);
  22415.             S_Str := SP.Upper(STRING'(SS.Strip_Trailing(Element)));
  22416.             Iterator := SL.MakeListIter(Argument.valid);
  22417.             Found := FALSE;
  22418.             while SL.More(Iterator) loop
  22419.             SL.Next(Iterator, R_Str);
  22420.             if SP.Equal(S_Str, R_Str) then
  22421.                 SL.Attach(Argument.value, SP.Make_Persistent(R_Str));
  22422.                 Found := TRUE;
  22423.                 exit;
  22424.             end if;
  22425.             end loop;
  22426.             if not Found then
  22427.             if not First then
  22428.                 if not SP.Is_Empty(S_Str) then
  22429.                 Report_Error(Invalid_Value, Value=>SP.Value(S_Str));
  22430.                 else
  22431.                 if not List_Error then
  22432.                     Report_Error(Invalid_List,
  22433.                          Value => Left_Enclosure &
  22434.                               SP.Value(Item) &
  22435.                               Right_Enclosure);
  22436.                     List_Error := TRUE;
  22437.                 end if;
  22438.                 end if;
  22439.             else
  22440.                 if not SP.Is_Empty(S_Str) then
  22441.                 Report_Error(Invalid_Value, Value=>SP.Value(S_Str));
  22442.                 else
  22443.                 Argument.supplied := TRUE;
  22444.                 end if;
  22445.             end if;
  22446.             else
  22447.             Argument.supplied := TRUE;
  22448.             end if;
  22449.             SP.Flush(Element);
  22450.             Point_Next_Token(Scanner);
  22451.             First := FALSE;
  22452.         end loop;
  22453.         return;
  22454.         end if;
  22455.  
  22456.     when INT_LIST =>
  22457.         if Kind = LIST or
  22458.           (Parsing_Switches(Argument_Enclosure) = OFF and Kind = VALUE) then
  22459.         Scanner := SS.Make_Scanner(SP."&"(Item, "" & SP.Fetch(Delimiter, 1)));
  22460.         First := TRUE;
  22461.         while SU.More(Scanner) loop
  22462.             SS.Scan_Not_Sequence(Delimiter, Scanner, Found, Element, Skip => TRUE);
  22463.             S_Str := SS.Strip_Trailing(Element);
  22464.             Found := FALSE;
  22465.             begin
  22466.             Num := INTEGER'value(SP.Value(S_Str));
  22467.             if Argument.low <= Num and Num <= Argument.high then
  22468.                 SL.Attach(Argument.value, SP.Make_Persistent(S_Str));
  22469.                 Found := TRUE;
  22470.             end if;
  22471.             exception
  22472.             when CONSTRAINT_ERROR =>
  22473.                 null;
  22474.             end;
  22475.             if not Found then
  22476.             if not First then
  22477.                 if not SP.Is_Empty(S_Str) then
  22478.                 Report_Error(Invalid_Value, Value=>SP.Value(S_Str));
  22479.                 else
  22480.                 if not List_Error then
  22481.                     Report_Error(Invalid_List,
  22482.                          Value => Left_Enclosure &
  22483.                               SP.Value(Item) &
  22484.                               Right_Enclosure);
  22485.                     List_Error := TRUE;
  22486.                 end if;
  22487.                 end if;
  22488.             else
  22489.                 if not SP.Is_Empty(S_Str) then
  22490.                 Report_Error(Invalid_Value, Value=>SP.Value(S_Str));
  22491.                 else
  22492.                 Argument.supplied := TRUE;
  22493.                 end if;
  22494.             end if;
  22495.             else
  22496.             Argument.supplied := TRUE;
  22497.             end if;
  22498.             SP.Flush(Element);
  22499.             Point_Next_Token(Scanner);
  22500.             First := FALSE;
  22501.         end loop;
  22502.         return;
  22503.         end if;
  22504.  
  22505.     when STR_LIST =>
  22506.         if Kind = LIST or
  22507.            Parsing_Switches(Argument_Enclosure) = OFF then
  22508.         Scanner := SS.Make_Scanner(SP."&"(Item, "" & SP.Fetch(Delimiter, 1)));
  22509.         First := TRUE;
  22510.         while SU.More(Scanner) loop
  22511.             if Kind = LIST then
  22512.             if SU.Is_Quoted(Scanner) then
  22513.                 SS.Scan_Quoted(Scanner, Found, Element);
  22514.             else
  22515.                 SS.Scan_Not_Sequence(Delimiter, Scanner, Found, Element, Skip => TRUE);
  22516.                 if Parsing_Switches(Quote_Enclosure) = ON and
  22517.                    not SP.Is_Empty(SS.Strip(Element)) then
  22518.                 Report_Error(Missing_Quotes, Value=>SP.Value(Element));
  22519.                 end if;
  22520.             end if;
  22521.             S_Str := SS.Strip_Trailing(Element);
  22522.             else
  22523.             S_Str := SS.Get_String(Scanner);
  22524.                 Element := SP.Make_Persistent(SP.Substr(S_Str, 1, SP.Length(S_Str) - 1));
  22525.                 SP.Flush(S_Str);
  22526.             if Kind /= QUOTED then
  22527.                 S_Str := SS.Strip(Element);
  22528.             else
  22529.                 S_Str := Element;
  22530.             end if;
  22531.             SU.Backward(Scanner);
  22532.             end if;
  22533.             if SP.Is_Empty(S_Str) then
  22534.             if not First then
  22535.                 if not List_Error then
  22536.                 Report_Error(Invalid_List,
  22537.                          Value => Left_Enclosure &
  22538.                               SP.Value(Item) &
  22539.                               Right_Enclosure);
  22540.                 List_Error := TRUE;
  22541.                 end if;
  22542.             else
  22543.                 Argument.supplied := TRUE;
  22544.             end if;
  22545.             else
  22546.             Argument.supplied := TRUE;
  22547.             SL.Attach(Argument.value, SP.Make_Persistent(S_Str));
  22548.             end if;
  22549.             SP.Flush(Element);
  22550.             Point_Next_Token(Scanner);
  22551.             First := FALSE;
  22552.         end loop;
  22553.         return;
  22554.         end if;
  22555.     end case;
  22556.  
  22557.     case Kind is
  22558.     when LIST =>
  22559.         Report_Error(Invalid_List,
  22560.              Value => Left_Enclosure &
  22561.                   SP.Value(S_Str) &
  22562.                   Right_Enclosure);
  22563.         Report_Error(Invalid_List, Value=>SP.Value(S_Str));
  22564.     when QUOTED =>
  22565.         S_Str := SP.Create('"' & SP.Value(Item) & '"');
  22566.         Report_Error(Invalid_Value, Value=>SP.Value(S_Str));
  22567.     when others =>
  22568.         Report_Error(Invalid_Value, Value=>SP.Value(Item));
  22569.     end case;
  22570.  
  22571. end Parse_Argument;
  22572.  
  22573. ----------------------------------------------------------------
  22574.  
  22575. procedure Report_Error(
  22576.     Kind     : in Error_Types;
  22577.     Argument : in STRING := "";
  22578.     Name     : in STRING := "";
  22579.     Value    : in STRING := ""
  22580.     ) is
  22581.  
  22582.     S_Str : SP.String_Type;
  22583.     Num   : NATURAL;
  22584.  
  22585. begin
  22586.  
  22587.     if Errors(Kind).flag = CONTINUE then
  22588.     Status := ERROR;
  22589.     else
  22590.     Status := SEVERE;
  22591.     end if;
  22592.     if Action_Switches(Show_Error) = OFF then
  22593.     return;
  22594.     end if;
  22595.     SP.Mark;
  22596.     S_Str := Errors(Kind).msg;
  22597.     loop
  22598.     Num := SP.Match_S(S_Str, "~A");
  22599.     exit when Num = 0;
  22600.     S_Str := SP.Splice(S_Str, Num, 2);
  22601.     S_Str := SP.Insert(S_Str, Argument, Num);
  22602.     end loop;
  22603.     loop
  22604.     Num := SP.Match_S(S_Str, "~N");
  22605.     exit when Num = 0;
  22606.     S_Str := SP.Splice(S_Str, Num, 2);
  22607.     S_Str := SP.Insert(S_Str, Name, Num);
  22608.     end loop;
  22609.     loop
  22610.     Num := SP.Match_S(S_Str, "~V");
  22611.     exit when Num = 0;
  22612.     S_Str := SP.Splice(S_Str, Num, 2);
  22613.     S_Str := SP.Insert(S_Str, Value, Num);
  22614.     end loop;
  22615.     HL.Put_Error(SP.Value(S_Str));
  22616.     SP.Release;
  22617.  
  22618. end Report_Error;
  22619.  
  22620. ----------------------------------------------------------------
  22621.  
  22622. end Standard_Interface;
  22623.                                                                     pragma Page;
  22624. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  22625. --RELEASE.SUB
  22626. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  22627.  
  22628. separate (Standard_Interface)
  22629.  
  22630. function Release return STRING is
  22631.  
  22632. begin
  22633.  
  22634.     return "3.01";
  22635.  
  22636.     -- The executable's header line will contain the return string
  22637.     -- as it appears above.
  22638.  
  22639. end Release;
  22640.  
  22641.