home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / metric / sinstrtm.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  190.9 KB  |  6,119 lines

  1. -----------------------------------
  2. package Implementation_Dependencies is --| Ada Compiler dependencies
  3. -----------------------------------
  4.  
  5. --| Overview
  6. --| This package contains Ada Compiler Implementation dependencies.
  7. --| The purpose of this package is to isolate compiler dependencies
  8. --| to a single package to simplify rehosting of the Ada Testing
  9. --| and Evaluation Tools Set (ATETS).
  10.  
  11. --| This version of Implementation_Dependencies is configured for:
  12. --|
  13. --|   - DEC VAX Ada Compiler
  14. --|
  15. --|   - TeleSoft Ada Compiler ( VAX VMS Version 2.5 )
  16.  
  17.  
  18. -- Jeff England  04/30/85 (TeleSoft Ada)
  19. --               05/09/85 (DEC VAX Ada)
  20.  
  21. --------------------------------------
  22.  
  23.  
  24.     type Long_Integer  is new integer;  --| Not implemented in TeleSoft Ada
  25.  
  26. --    type Long_Float    is new float;    --| Not implemented in TeleSoft Ada
  27.  
  28. --    type Short_Integer is new integer;  --| Not implemented in TeleSoft Ada
  29.  
  30.     type Short_Float   is new float;    --| Not implemented in TeleSoft Ada
  31.  
  32.     Line_length : constant := 256;
  33.  
  34. end Implementation_Dependencies;
  35.  
  36. package File_Manager is
  37.  
  38. --| Overview
  39. --| This package provides some host independent file functions.  The provided 
  40. --| functions are: Copy, Rename, and Append.  Each of these works on text
  41. --| files only and with a maximun line length of 255 (constant declared in
  42. --| the body which can be changed).  Due to Ada's limitations each file
  43. --| ends up with a form feed inserted as the last character.
  44.  
  45. --| Requires
  46. --| Each procedure is passed two strings which are the file names to be used.
  47.  
  48.   procedure Copy(In_File_Name : in string;
  49.                  Out_File_Name: in string);
  50.  
  51. --| Effects
  52. --| This procedure will take the file specified as In_file_name and make a
  53. --| second copy of the file in the file specified in Out_file_name.
  54. --| The copy of the file in Out_file_name will have a form feed inserted
  55. --| as the last character of the file.
  56.  
  57. --| Requires
  58. --| The parameter In_file_name must specify a valid file name of an existing
  59. --| file.  The parameter Out_file_name must specify a valid file name for a
  60. --| file that currently does not exist
  61.  
  62. --| Raises
  63. --| status_error, name_error, use_error
  64.  
  65.   procedure Rename(In_File_Name : in string;
  66.                    Out_File_Name: in string);
  67.  
  68. --| Effects
  69. --| This procedure will take the file specified in In_file_name and rename
  70. --| it as the file specified as Out_file_name.  The original file will no
  71. --| longer exist.  The new file will have a form feed inserted as the last
  72. --| character of the file.
  73.  
  74. --| Requires
  75. --| The parameter In_file_name must specify a valid file name of an existing
  76. --| file.  The parameter Out_file_name must specify a valid file name for a
  77. --| file that currently does not exist
  78.  
  79. --| Raises
  80. --| status_error, use_error, name_error
  81.  
  82.   procedure Append(Append_File_Name : in string;
  83.                    To_File_Name     : in string);
  84.  
  85. --| Effects
  86. --| This procedure will Append one file onto the end of another file.  The 
  87. --| First file specified will be added onto the end of the second file 
  88. --| specified.  
  89.  
  90. --| Requires
  91. --| Both parameters must be valid file names and must specify files that 
  92. --| currently exist.
  93.  
  94. --| Raises
  95. --| status_error, name_error, use_error
  96.  
  97. end File_Manager;
  98. with Text_Io; use Text_Io;
  99. package body File_Manager is
  100.  
  101. --| Overview
  102. --| This package provides some host independent file functions.  These
  103. --| functions work on text files.  The maximun line lengths of the 
  104. --| files is specified in the parameter Maximun_Line_Size which can be
  105. --| changed.
  106.  
  107.   Maximum_Line_Size: constant := 255;
  108.  
  109.   procedure Copy(In_File_Name : in string;
  110.                  Out_File_Name: in string) is
  111.     Input_Buffer: string(1..Maximum_Line_Size);
  112.     Input_File: File_Type;
  113.     Output_File: File_Type;
  114.     Line_Length: natural;
  115.   begin
  116.     Open(Input_File,In_File, In_File_Name);
  117.     Create(Output_File,Out_File, Out_File_Name);
  118.     
  119.     while not End_Of_File(Input_File) loop
  120.       Get_Line(Input_File, Input_Buffer, Line_Length);
  121.       Put_Line(Output_File, Input_Buffer(1..Line_Length));
  122.       end loop;
  123.  
  124.     Close(Input_File);
  125.     Close(Output_File);
  126.   exception
  127.     when
  128.       status_error =>
  129.         put_line("status_error - trying to open a file that is already open");
  130.     when
  131.       name_error =>
  132.         put_line("name_error - trying to open a file that does not exist");
  133.     when 
  134.       use_error =>
  135.         put_line("use_error - incorrect form of file name"); 
  136.   end Copy;
  137.  
  138.   procedure Rename(In_File_Name : in string;
  139.                    Out_File_Name: in string) is
  140.     Input_File: File_Type;
  141.   begin
  142.     Copy(In_File_Name,Out_File_Name);
  143.     Open(Input_File,In_File,In_File_Name);
  144.     Delete(Input_File);
  145.   exception
  146.     when
  147.       status_error =>
  148.         put_line("status_error - trying to open/close file");
  149.     when
  150.       name_error =>
  151.         put_line("name_error - trying to open a file that does not exist");
  152.     when
  153.       use_error =>
  154.         put_line("use_error - delete access not allowed");
  155.   end Rename;
  156.  
  157.   procedure Append(Append_File_Name : in string;
  158.                    To_File_Name     : in string) is
  159.     Append_File: File_Type;
  160.     To_File: File_Type;
  161.     Input_Buffer: string(1..Maximum_Line_Size);
  162.     Line_Length: natural;
  163.   begin
  164.     Rename(To_File_Name,"temp0097.rlr");
  165.     Open(Append_File,In_File, "temp0097.rlr");
  166.     Create(To_File,Out_File, To_File_Name);
  167.     
  168.     while not End_Of_File(Append_File) loop
  169.       Get_Line(Append_File, Input_Buffer, Line_Length);
  170.       Put_Line(To_File, Input_Buffer(1..Line_Length));
  171.       end loop;
  172.  
  173.     Delete(Append_File);
  174.     Open(Append_File,In_File, Append_File_Name);
  175.  
  176.     while not End_Of_File(Append_File) loop
  177.       Get_Line(Append_File, Input_Buffer, Line_Length);
  178.       Put_Line(To_File, Input_Buffer(1..Line_Length));
  179.       end loop;
  180.  
  181.     Close(Append_File);
  182.     Close(To_File);
  183.   exception
  184.     when
  185.       status_error =>
  186.         put_line("status_error - trying to open/close file");
  187.     when
  188.       name_error =>
  189.         put_line("name_error - trying to open a file that does not exist");
  190.     when
  191.       use_error =>
  192.         put_line("use_error - delete access not allowed");
  193.   end Append;
  194.  
  195. end File_Manager;
  196.  
  197. package STRING_PKG is 
  198.  
  199. --| Overview:
  200. --| Package string_pkg exports an abstract data type, string_type.  A
  201. --| string_type value is a sequence of characters.  The values have arbitrary
  202. --| length.  For a value, s, with length, l, the individual characters are
  203. --| numbered from 1 to l.  These values are immutable; characters cannot be
  204. --| replaced or appended in a destructive fashion.  
  205. --|
  206. --| In the documentation for this package, we are careful to distinguish 
  207. --| between string_type objects, which are Ada objects in the usual sense, 
  208. --| and string_type values, the members of this data abstraction as described
  209. --| above.  A string_type value is said to be associated with, or bound to,
  210. --| a string_type object after an assignment (:=) operation.  
  211. --| 
  212. --| The operations provided in this package fall into three categories: 
  213. --|
  214. --| 1. Constructors:  These functions typically take one or more string_type
  215. --|      objects as arguments.  They work with the values associated with 
  216. --|      these objects, and return new string_type values according to 
  217. --|      specification.  By a slight abuse of language, we will sometimes 
  218. --|      coerce from string_type objects to values for ease in description.
  219. --|
  220. --| 2. Heap Management:   
  221. --|      These operations (make_persistent, flush, mark, release) control the
  222. --|      management of heap space.  Because string_type values are
  223. --|      allocated on the heap, and the type is not limited, it is necessary
  224. --|      for a user to assume some responsibility for garbage collection.  
  225. --|      String_type is not limited because of the convenience of
  226. --|      the assignment operation, and the usefulness of being able to 
  227. --|      instantiate generic units that contain private type formals.  
  228. --|      ** Important: To use this package properly, it is necessary to read
  229. --|      the descriptions of the operations in this section.
  230. --|
  231. --| 3. Queries:  These functions return information about the values 
  232. --|      that are associated with the argument objects.  The same conventions 
  233. --|      for description of operations used in (1) is adopted.
  234. --| 
  235. --| A note about design decisions...  The decision to not make the type 
  236. --| limited causes two operations to be carried over from the representation.
  237. --| These are the assignment operation, :=, and the "equality" operator, "=".
  238. --| See the discussion at the beginning of the Heap Management section for a 
  239. --| discussion of :=.
  240. --| See the spec for the first of the equal functions for a discussion of "=".
  241. --| 
  242. --| The following is a complete list of operations, written in the order
  243. --| in which they appear in the spec.  Overloaded subprograms are followed
  244. --| by (n), where n is the number of subprograms of that name.
  245. --|
  246. --| 1. Constructors:
  247. --|        create
  248. --|        "&" (3)
  249. --|        substr
  250. --|        splice
  251. --|        insert (3)
  252. --|        lower (2) 
  253. --|        upper (2)
  254. --| 2. Heap Management:
  255. --|        make_persistent (2)
  256. --|        flush
  257. --|        mark, release
  258. --| 3. Queries:
  259. --|        is_empty
  260. --|        length
  261. --|        value
  262. --|        fetch
  263. --|        equal (3)
  264. --|        "<" (3), 
  265. --|       "<=" (3)
  266. --|        match_c
  267. --|        match_not_c
  268. --|        match_s (2)
  269. --|        match_any (2)
  270. --|        match_none (2)
  271.  
  272. --| Notes:
  273. --| Programmer: Ron Kownacki
  274.  
  275.   type STRING_TYPE is private; 
  276.  
  277.   BOUNDS          : exception;  --| Raised on index out of bounds.
  278.   ANY_EMPTY       : exception;  --| Raised on incorrect use of match_any.
  279.   ILLEGAL_ALLOC   : exception;  --| Raised by value creating operations.
  280.   ILLEGAL_DEALLOC : exception;  --| Raised by release.
  281.  
  282.  
  283.   -- Constructors:
  284.  
  285.   function CREATE(S : in STRING) return STRING_TYPE; 
  286.  
  287.   --| Raises: illegal_alloc
  288.   --| Effects:
  289.   --| Return a value consisting of the sequence of characters in s.
  290.   --| Sometimes useful for array or record aggregates.
  291.   --| Raises illegal_alloc if string space has been improperly
  292.   --| released.  (See procedures mark/release.)
  293.  
  294.   function "&"(S1, S2 : in STRING_TYPE) return STRING_TYPE; 
  295.  
  296.   --| Raises: illegal_alloc
  297.   --| Effects:
  298.   --| Return the concatenation of s1 and s2.
  299.   --| Raises illegal_alloc if string space has been improperly
  300.   --| released.  (See procedures mark/release.)
  301.  
  302.   function "&"(S1 : in STRING_TYPE; 
  303.                S2 : in STRING) return STRING_TYPE; 
  304.  
  305.   --| Raises: illegal_alloc
  306.   --| Effects:
  307.   --| Return the concatenation of s1 and create(s2).
  308.   --| Raises illegal_alloc if string space has been improperly
  309.   --| released.  (See procedures mark/release.)
  310.  
  311.   function "&"(S1 : in STRING; 
  312.                S2 : in STRING_TYPE) return STRING_TYPE; 
  313.  
  314.   --| Raises: illegal_alloc
  315.   --| Effects:
  316.   --| Return the concatenation of create(s1) and s2.
  317.   --| Raises illegal_alloc if string space has been improperly
  318.   --| released.  (See procedures mark/release.)
  319.  
  320.   function SUBSTR(S   : in STRING_TYPE; 
  321.                   I   : in POSITIVE; 
  322.                   LEN : in NATURAL) return STRING_TYPE; 
  323.  
  324.   --| Raises: bounds, illegal_alloc
  325.   --| Effects:
  326.   --| Return the substring, of specified length, that occurs in s at
  327.   --| position i.  If len = 0, then returns the empty value.  
  328.   --| Otherwise, raises bounds if either i or (i + len - 1)
  329.   --| is not in 1..length(s).
  330.   --| Raises illegal_alloc if string space has been improperly
  331.   --| released.  (See procedures mark/release.)
  332.  
  333.   function SPLICE(S   : in STRING_TYPE; 
  334.                   I   : in POSITIVE; 
  335.                   LEN : in NATURAL) return STRING_TYPE; 
  336.  
  337.   --| Raises: bounds, illegal_alloc
  338.   --| Effects:
  339.   --| Let s be the string, abc, where a, b and c are substrings.  If
  340.   --| substr(s, i, length(b)) = b, for some i in 1..length(s), then
  341.   --| splice(s, i, length(b)) = ac.  
  342.   --| Returns a value equal to s if len = 0.  Otherwise, raises bounds if
  343.   --| either i or (i + len - 1) is not in 1..length(s).
  344.   --| Raises illegal_alloc if string space has been improperly
  345.   --| released.  (See procedures mark/release.)
  346.  
  347.   function INSERT(S1, S2 : in STRING_TYPE; 
  348.                   I      : in POSITIVE) return STRING_TYPE; 
  349.  
  350.   --| Raises: bounds, illegal_alloc
  351.   --| Effects:
  352.   --| Return substr(s1, 1, i - 1) & s2 &
  353.   --|        substr(s1, i, length(s1) - i + 1).
  354.   --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  355.   --| exception is raised by insert.
  356.   --| Raises bounds if is_empty(s1) or else i is not in 1..length(s1).
  357.   --| Raises illegal_alloc if string space has been improperly
  358.   --| released.  (See procedures mark/release.)
  359.  
  360.   function INSERT(S1 : in STRING_TYPE; 
  361.                   S2 : in STRING; 
  362.                   I  : in POSITIVE) return STRING_TYPE; 
  363.  
  364.   --| Raises: bounds, illegal_alloc
  365.   --| Effects:
  366.   --| Return substr(s1, 1, i - 1) & s2 &
  367.   --|        substr(s1, i, length(s1) - i + 1).
  368.   --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  369.   --| exception is raised by insert.
  370.   --| Raises bounds if is_empty(s1) or else i is not in 1..length(s1).
  371.   --| Raises illegal_alloc if string space has been improperly
  372.   --| released.  (See procedures mark/release.)
  373.  
  374.   function INSERT(S1 : in STRING; 
  375.                   S2 : in STRING_TYPE; 
  376.                   I  : in POSITIVE) return STRING_TYPE; 
  377.  
  378.   --| Raises: bounds, illegal_alloc
  379.   --| Effects:
  380.   --| Return s1(s1'first..i - 1) & s2 &
  381.   --|        s1(i..length(s1) - i + 1).
  382.   --| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
  383.   --| exception is raised by insert.
  384.   --| Raises bounds if i is not in s'range.
  385.   --| Raises illegal_alloc if string space has been improperly
  386.   --| released.  (See procedures mark/release.)
  387.  
  388.   function LOWER(S : in STRING) return STRING_TYPE; 
  389.  
  390.   --| Raises: illegal_alloc
  391.   --| Effects:
  392.   --| Return a value that contains exactly those characters in s with
  393.   --| the exception that all upper case characters are replaced by their 
  394.   --| lower case counterparts.
  395.   --| Raises illegal_alloc if string space has been improperly
  396.   --| released.  (See procedures mark/release.)
  397.  
  398.   function LOWER(S : in STRING_TYPE) return STRING_TYPE; 
  399.  
  400.   --| Raises: illegal_alloc
  401.   --| Effects:
  402.   --| Return a value that is a copy of s with the exception that all
  403.   --| upper case characters are replaced by their lower case counterparts.
  404.   --| Raises illegal_alloc if string space has been improperly
  405.   --| released.  (See procedures mark/release.)
  406.  
  407.   function UPPER(S : in STRING) return STRING_TYPE; 
  408.  
  409.   --| Raises: illegal_alloc
  410.   --| Effects:
  411.   --| Return a value that contains exactly those characters in s with
  412.   --| the exception that all lower case characters are replaced by their 
  413.   --| upper case counterparts.
  414.   --| Raises illegal_alloc if string space has been improperly
  415.   --| released.  (See procedures mark/release.)
  416.  
  417.   function UPPER(S : in STRING_TYPE) return STRING_TYPE; 
  418.  
  419.   --| Raises: illegal_alloc
  420.   --| Effects:
  421.   --| Return a value that is a copy of s with the exception that all
  422.   --| lower case characters are replaced by their upper case counterparts.
  423.   --| Raises illegal_alloc if string space has been improperly
  424.   --| released.  (See procedures mark/release.)
  425.  
  426.  
  427.   -- Heap Management (including object/value binding):
  428.   --
  429. -- Two forms of heap management are provided.  The general scheme is to "mark"
  430.   -- the current state of heap usage, and to "release" in order to reclaim all
  431.   -- space that has been used since the last mark.  However, this alone is 
  432.   -- insufficient because it is frequently desirable for objects to remain 
  433.   -- associated with values for longer periods of time, and this may come into 
  434.   -- conflict with the need to clean up after a period of "string hacking."
  435.   -- To deal with this problem, we introduce the notions of "persistent" and
  436.   -- "nonpersistent" values.
  437.   --
  438.   -- The nonpersistent values are those that are generated by the constructors 
  439.   -- in the previous section.  These are claimed by the release procedure.
  440.   -- Persistent values are generated by the two make_persistent functions
  441. -- described below.  These values must be disposed of individually by means of
  442.   -- the flush procedure.  
  443.   --
  444.   -- This allows a description of the meaning of the ":=" operation.  For a 
  445.   -- statement of the form, s := expr, where expr is a string_type expression, 
  446.   -- the result is that the value denoted/created by expr becomes bound to the
  447.   -- the object, s.  Assignment in no way affects the persistence of the value.
  448. -- If expr happens to be an object, then the value associated  with it will be
  449.   -- shared.  Ideally, this sharing would not be visible, since values are
  450.   -- immutable.  However, the sharing may be visible because of the memory
  451. -- management, as described below.  Programs which depend on such sharing are 
  452.   -- erroneous.
  453.  
  454.   function MAKE_PERSISTENT(S : in STRING_TYPE) return STRING_TYPE; 
  455.  
  456.   --| Effects: 
  457.   --| Returns a persistent value, v, containing exactly those characters in
  458.   --| value(s).  The value v will not be claimed by any subsequent release.
  459.   --| Only an invocation of flush will claim v.  After such a claiming
  460.   --| invocation of flush, the use (other than :=) of any other object to 
  461.   --| which v was bound is erroneous, and program_error may be raised for
  462.   --| such a use.
  463.  
  464.   function MAKE_PERSISTENT(S : in STRING) return STRING_TYPE; 
  465.  
  466.   --| Effects: 
  467.   --| Returns a persistent value, v, containing exactly those chars in s.
  468.   --| The value v will not be claimed by any subsequent release.
  469.   --| Only an invocation of flush will reclaim v.  After such a claiming
  470.   --| invocation of flush, the use (other than :=) of any other object to 
  471.   --| which v was bound is erroneous, and program_error may be raised for
  472.   --| such a use.
  473.  
  474.   procedure FLUSH(S : in out STRING_TYPE); 
  475.  
  476.   --| Effects:
  477.   --| Return heap space used by the value associated with s, if any, to 
  478.   --| the heap.  s becomes associated with the empty value.  After an
  479.   --| invocation of flush claims the value, v, then any use (other than :=)
  480.   --| of an object to which v was bound is erroneous, and program_error 
  481.   --| may be raised for such a use.
  482.   --| 
  483.   --| This operation should be used only for persistent values.  The mark 
  484.   --| and release operations are used to deallocate space consumed by other
  485.   --| values.  For example, flushing a nonpersistent value implies that a
  486.   --| release that tries to claim this value will be erroneous, and
  487.   --| program_error may be raised for such a use.
  488.  
  489.   procedure MARK; 
  490.  
  491.   --| Effects:
  492.   --| Marks the current state of heap usage for use by release.  
  493.   --| An implicit mark is performed at the beginning of program execution.
  494.  
  495.   procedure RELEASE; 
  496.  
  497.   --| Raises: illegal_dealloc
  498.   --| Effects:
  499.   --| Releases all heap space used by nonpersistent values that have been
  500.   --| allocated since the last mark.  The values that are claimed include
  501.   --| those bound to objects as well as those produced and discarded during
  502.   --| the course of general "string hacking."  If an invocation of release
  503.   --| claims a value, v, then any subsequent use (other than :=) of any 
  504.   --| other object to which v is bound is erroneous, and program_error may
  505.   --| be raised for such a use.
  506.   --|
  507.   --| Raises illegal_dealloc if the invocation of release does not balance
  508.   --| an invocation of mark.  It is permissible to match the implicit
  509.   --| initial invocation of mark.  However, subsequent invocations of 
  510.   --| constructors will raise the illegal_alloc exception until an 
  511.   --| additional mark is performed.  (Anyway, there is no good reason to 
  512.   --| do this.)  In any case, a number of releases matching the number of
  513.   --| currently active marks is implicitly performed at the end of program
  514.   --| execution.
  515.   --|
  516.   --| Good citizens generally perform their own marks and releases
  517.   --| explicitly.  Extensive string hacking without cleaning up will 
  518.   --| cause your program to run very slowly, since the heap manager will
  519.   --| be forced to look hard for chunks of space to allocate.
  520.  
  521.   -- Queries:
  522.  
  523.   function IS_EMPTY(S : in STRING_TYPE) return BOOLEAN; 
  524.  
  525.   --| Effects:
  526.   --| Return true iff s is the empty sequence of characters.
  527.  
  528.   function LENGTH(S : in STRING_TYPE) return NATURAL; 
  529.  
  530.   --| Effects:
  531.   --| Return number of characters in s.
  532.  
  533.   function VALUE(S : in STRING_TYPE) return STRING; 
  534.  
  535.   --| Effects:
  536.   --| Return a string, s2, that contains the same characters that s
  537.   --| contains.  The properties, s2'first = 1 and s2'last = length(s),
  538.   --| are satisfied.  This implies that, for a given string, s3,
  539.   --| value(create(s3))'first may not equal s3'first, even though
  540.   --| value(create(s3)) = s3 holds.  Thus, "content equality" applies
  541.   --| although the string objects may be distinguished by the use of
  542.   --| the array attributes.
  543.  
  544.   function FETCH(S : in STRING_TYPE; 
  545.                  I : in POSITIVE) return CHARACTER; 
  546.  
  547.   --| Raises: bounds
  548.   --| Effects:
  549.   --| Return the ith character in s.  Characters are numbered from
  550.   --| 1 to length(s).  Raises bounds if i not in 1..length(s).
  551.  
  552.   function EQUAL(S1, S2 : in STRING_TYPE) return BOOLEAN; 
  553.  
  554.   --| Effects:
  555.   --| Value equality relation; return true iff length(s1) = length(s2) 
  556.   --| and, for all i in 1..length(s1), fetch(s1, i) = fetch(s2, i).
  557.   --| The "=" operation is carried over from the representation.
  558.   --| It allows one to distinguish among the heap addresses of
  559.   --| string_type values.  Even "equal" values may not be "=", although
  560.   --| s1 = s2 implies equal(s1, s2).  
  561.   --| There is no reason to use "=".
  562.  
  563.   function EQUAL(S1 : in STRING_TYPE; 
  564.                  S2 : in STRING) return BOOLEAN; 
  565.  
  566.   --| Effects:
  567.   --| Return equal(s1, create(s2)).
  568.  
  569.   function EQUAL(S1 : in STRING; 
  570.                  S2 : in STRING_TYPE) return BOOLEAN; 
  571.  
  572.   --| Effects:
  573.   --| Return equal(create(s1), s2).
  574.  
  575.   function "<"(S1 : in STRING_TYPE; 
  576.                S2 : in STRING_TYPE) return BOOLEAN; 
  577.  
  578.   --| Effects: 
  579.   --| Lexicographic comparison; return value(s1) < value(s2).
  580.  
  581.   function "<"(S1 : in STRING_TYPE; 
  582.                S2 : in STRING) return BOOLEAN; 
  583.  
  584.   --| Effects: 
  585.   --| Lexicographic comparison; return value(s1) < s2.
  586.  
  587.   function "<"(S1 : in STRING; 
  588.                S2 : in STRING_TYPE) return BOOLEAN; 
  589.  
  590.   --| Effects: 
  591.   --| Lexicographic comparison; return s1 < value(s2).
  592.  
  593.   function "<="(S1 : in STRING_TYPE; 
  594.                 S2 : in STRING_TYPE) return BOOLEAN; 
  595.  
  596.   --| Effects: 
  597.   --| Lexicographic comparison; return value(s1) <= value(s2).
  598.  
  599.   function "<="(S1 : in STRING_TYPE; 
  600.                 S2 : in STRING) return BOOLEAN; 
  601.  
  602.   --| Effects: 
  603.   --| Lexicographic comparison; return value(s1) <= s2.
  604.  
  605.   function "<="(S1 : in STRING; 
  606.                 S2 : in STRING_TYPE) return BOOLEAN; 
  607.  
  608.   --| Effects: 
  609.   --| Lexicographic comparison; return s1 <= value(s2).
  610.  
  611.   function MATCH_C(S     : in STRING_TYPE; 
  612.                    C     : in CHARACTER; 
  613.                    START : in POSITIVE := 1) return NATURAL; 
  614.  
  615.   --| Raises: no_match
  616.   --| Effects:
  617.   --| Return the minimum index, i in start..length(s), such that
  618.   --| fetch(s, i) = c.  Returns 0 if no such i exists, 
  619.   --| including the case where is_empty(s).
  620.  
  621.   function MATCH_NOT_C(S     : in STRING_TYPE; 
  622.                        C     : in CHARACTER; 
  623.                        START : in POSITIVE := 1) return NATURAL; 
  624.  
  625.   --| Raises: no_match
  626.   --| Effects:
  627.   --| Return the minimum index, i in start..length(s), such that
  628.   --| fetch(s, i) /= c.  Returns 0 if no such i exists,
  629.   --| including the case where is_empty(s).
  630.  
  631.   function MATCH_S(S1, S2 : in STRING_TYPE; 
  632.                    START  : in POSITIVE := 1) return NATURAL; 
  633.  
  634.   --| Raises: no_match.
  635.   --| Effects:
  636.   --| Return the minimum index, i, in start..length(s1), such that,
  637.   --| for all j in 1..length(s2), fetch(s2, j) = fetch(s1, i + j - 1).
  638.   --| This is the position of the substring, s2, in s1.
  639.   --| Returns 0 if no such i exists, including the cases
  640.   --| where is_empty(s1) or is_empty(s2).
  641.   --| Note that equal(substr(s1, match_s(s1, s2, i), length(s2)), s2)
  642.   --| holds, providing that match_s does not raise an exception.
  643.  
  644.   function MATCH_S(S1    : in STRING_TYPE; 
  645.                    S2    : in STRING; 
  646.                    START : in POSITIVE := 1) return NATURAL; 
  647.  
  648.   --| Raises: no_match.
  649.   --| Effects:
  650.   --| Return the minimum index, i, in start..length(s1), such that,
  651.   --| for all j in s2'range, s2(j) = fetch(s1, i + j - 1).
  652.   --| This is the position of the substring, s2, in s1.
  653.   --| Returns 0 if no such i exists, including the cases
  654.   --| where is_empty(s1) or s2 = "".
  655.   --| Note that equal(substr(s1, match_s(s1, s2, i), s2'length), s2)
  656.   --| holds, providing that match_s does not raise an exception.
  657.  
  658.   function MATCH_ANY(S, ANY : in STRING_TYPE; 
  659.                      START  : in POSITIVE := 1) return NATURAL; 
  660.  
  661.   --| Raises: no_match, any_empty
  662.   --| Effects:
  663.   --| Return the minimum index, i in start..length(s), such that
  664.   --| fetch(s, i) = fetch(any, j), for some j in 1..length(any).
  665.   --| Raises any_empty if is_empty(any).
  666.   --| Otherwise, returns 0 if no such i exists, including the case
  667.   --| where is_empty(s).
  668.  
  669.  
  670.   function MATCH_ANY(S     : in STRING_TYPE; 
  671.                      ANY   : in STRING; 
  672.                      START : in POSITIVE := 1) return NATURAL; 
  673.  
  674.   --| Raises: no_match, any_empty
  675.   --| Effects:
  676.   --| Return the minimum index, i, in start..length(s), such that
  677.   --| fetch(s, i) = any(j), for some j in any'range.
  678.   --| Raises any_empty if any = "".
  679.   --| Otherwise, returns 0 if no such i exists, including the case
  680.   --| where is_empty(s).
  681.  
  682.   function MATCH_NONE(S, NONE : in STRING_TYPE; 
  683.                       START   : in POSITIVE := 1) return NATURAL; 
  684.  
  685.   --| Raises: no_match
  686.   --| Effects:
  687.   --| Return the minimum index, i in start..length(s), such that
  688.   --| fetch(s, i) /= fetch(none, j) for each j in 1..length(none).
  689.   --| If (not is_empty(s)) and is_empty(none), then i is 1.
  690.   --| Returns 0 if no such i exists, including the case
  691.   --| where is_empty(s).
  692.  
  693.   function MATCH_NONE(S     : in STRING_TYPE; 
  694.                       NONE  : in STRING; 
  695.                       START : in POSITIVE := 1) return NATURAL; 
  696.  
  697.   --| Raises: no_match.
  698.   --| Effects:
  699.   --| Return the minimum index, i in start..length(s), such that
  700.   --| fetch(s, i) /= none(j) for each j in none'range.
  701.   --| If not is_empty(s) and none = "", then i is 1.
  702.   --| Returns 0 if no such i exists, including the case
  703.   --| where is_empty(s).
  704.  
  705.  
  706. private
  707.  
  708.   type STRING_TYPE is access STRING; 
  709.  
  710.   --| Abstract data type, string_type, is a constant sequence of chars
  711.   --| of arbitrary length.  Representation type is access string.
  712.   --| It is important to distinguish between an object of the rep type
  713.   --| and its value; for an object, r, val(r) denotes the value.
  714.   --|
  715.   --| Representation Invariant:  I: rep --> boolean
  716.   --| I(r: rep) = (val(r) = null) or else
  717.   --|             (val(r).all'first = 1 &
  718.   --|              val(r).all'last >= 0 &
  719.   --|              (for all r2, val(r) = val(r2) /= null => r is r2))
  720.   --|
  721.   --| Abstraction Function:  A: rep --> string_type
  722.   --| A(r: rep) = if r = null then
  723.   --|                 the empty sequence
  724.   --|             elsif r'last = 0 then  
  725.   --|                 the empty sequence
  726.   --|             else
  727.   --|                 the sequence consisting of r(1),...,r(r'last).
  728.  
  729. end STRING_PKG; 
  730. with STRING_PKG; use STRING_PKG;    --| for String_Types
  731.  
  732. ------------------------
  733. package TYPE_DEFINITIONS is 
  734. ------------------------
  735.  
  736. --| Overview
  737. --| TypeDefs contains global type declarations used by all of the Ada
  738. --| Testing and Analysis Tools.  Its purpose is to provide consistency and
  739. --| uniformity of type declarations for objects common to all of the tools.
  740.  
  741. --| N/A: Errors, Raises, Modifies, Requires
  742.  
  743. --  Last Modified: 05/10/85 JEE Converted all records with string lengths
  744. --                              as discriminants to String_Type
  745.  
  746.   type TOOL_NAMES is ( --| The names of the Testing and Analysis Tools
  747.   PATH_TOOL,           --| Path Analyzer
  748.   AUTOPATH_TOOL,       --| Automatic Path Analyzer
  749.   SMART_TOOL,          --| Self Metric Analysis and Reporting Tool
  750.   PROFILE_TOOL,        --| Performance Analyzer
  751.   DEBUG_TOOL           --| Symbolic Debugger
  752.   ); 
  753.  
  754.   type LOGFILE_KEYS is ( --| A unique key for each log file record type
  755.                          --| defines the format of each log file record
  756.   PROGRAM, TOOL, TEST_TIME, TEST_ID,        --| Logfile configuration
  757.   COMPILATION_UNIT_DEFINITION,              --| Unit definitions
  758.   PROGRAM_UNIT_DEFINITION,                  --| Unit definitions
  759.   UNIT_START, UNIT_STOP,                    --| Unit starts and stops
  760.   LOOP_BREAKPOINT, OTHER_BREAKPOINT,        --| All other breakpoints
  761.   AUTOPATH_CALL,                            --| AutoPath procedure call
  762.   INTEGER_VARIABLE,                         --| Variable data types
  763.   LONG_INTEGER_VARIABLE,                    --| Variable data types
  764.   FLOAT_VARIABLE,
  765.   LONG_FLOAT_VARIABLE,
  766.   FIXED_POINT_VARIABLE,
  767.   STRING_VARIABLE, 
  768.   DELAY_TIME,                               --| For delays of program units
  769.   TIMING_OVERHEAD                           --| For Unit_Start and Unit_Stop
  770.   ); 
  771.  
  772.   subtype FILENAME is STRING_TYPE;   --| filenames are string_types
  773.  
  774.   subtype USER_INPUT_STRING is STRING_TYPE;  --| for strings read from the kbd
  775.  
  776.   subtype TEST_IDENTIFIER is STRING_TYPE; 
  777.  
  778.   subtype BREAKPOINT_TYPES is
  779.     LOGFILE_KEYS range LOOP_BREAKPOINT .. OTHER_BREAKPOINT; 
  780.     --| The type of each breakpoint is assigned by the source instrumenter
  781.  
  782.  
  783.   --| Numeric Type Definitions
  784.  
  785.   subtype PROGRAM_UNIT_NUMBER_RANGE is NATURAL; 
  786.   --| The source instrumenter assigns a unique number to each
  787.   --| program unit within a compilation unit.
  788.  
  789.   subtype TASK_TYPE_ACTIVATION_NUMBER_RANGE is NATURAL; 
  790.   --| Each activation of a task type is assigned a unique number.
  791.  
  792.   subtype BREAKPOINT_NUMBER_RANGE is NATURAL; 
  793.   --| The source instrumenter assigns a unique number to each
  794.   --| breakpoint in the compilation unit.
  795.  
  796.   subtype COUNT_RANGE is NATURAL; 
  797.   --| A count is a non-negative number in the range 0 .. MAX_INT;
  798.  
  799.   type LONG_COUNT is 
  800.     record
  801.       OVERFLOW_COUNT : COUNT_RANGE; 
  802.       CURRENT_COUNT  : COUNT_RANGE; 
  803.     end record; 
  804.     --| A Long_Count record provides a "long integer" type of count
  805.     --| consisting of the current count and a count of the number of
  806.     --| times the current count has overflowed.
  807.  
  808.  
  809.   --| Program Unit Type definitions
  810.  
  811.   type PROGRAM_UNIT_TYPE is ( --| Ada program units can be
  812.     PROCEDURE_TYPE,           --| procedures
  813.     FUNCTION_TYPE,            --| functions
  814.     TASK_TYPE,                --| tasks
  815.     GENERIC_TYPE,             --| generics
  816.     PACKAGE_TYPE              --| and packages
  817.   ); 
  818.  
  819.   subtype ADA_NAME is STRING_TYPE; 
  820.   --| An Ada name is a string type of variable length
  821.  
  822.   subtype STRING_VARIABLES is STRING_TYPE; 
  823.   --| String Variables are string types of variable length
  824.  
  825.   type PROGRAM_UNIT_NAME is 
  826.     record
  827.       UNIT_IDENTIFIER : ADA_NAME; 
  828.       UNIT_TYPE       : PROGRAM_UNIT_TYPE; 
  829.     end record; 
  830.   --| A table of the names and program unit types of all of the
  831.   --| program units contained within a compilation unit.
  832.  
  833.   type PROCEDURE_LIST is array(POSITIVE range <>) of PROGRAM_UNIT_NAME; 
  834.   --| A table of the names and program unit types of all of the
  835.   --| program units contained within a compilation unit.
  836.  
  837.   type PROGRAM_UNIT_UNIQUE_IDENTIFIER is 
  838.     record
  839.       ENCLOSING_UNIT_IDENTIFIER   : ADA_NAME; 
  840.       PROGRAM_UNIT_NUMBER         : PROGRAM_UNIT_NUMBER_RANGE := 0; 
  841.       UNIT_TYPE                   : PROGRAM_UNIT_TYPE; 
  842.       TASK_TYPE_ACTIVATION_NUMBER : TASK_TYPE_ACTIVATION_NUMBER_RANGE := 1; 
  843.     end record; 
  844.     --| A Program_Unit_Unique_Identifier record consists of the identifier
  845.     --| of the enclosing unit, a unique number for the current program unit,
  846.     --| and for task types, a unique activation number.
  847.  
  848.   subtype INPUT_PARAMETER_LIST is STRING_TYPE; 
  849.  
  850.  
  851.   subtype CURRENT_UNIT_NAME is STRING_TYPE; 
  852.   --| The name of the current unit
  853.  
  854. end TYPE_DEFINITIONS; 
  855. with Calendar, Text_IO;
  856.  
  857. ----------------------
  858. package Time_Library_1 is
  859. ----------------------
  860.  
  861. --| Overview
  862. --| TimeLib contains procedures and functions for getting, putting,
  863. --| and calculating times, and dates. It augments the
  864. --| predefined library package Calendar to simplify IO and provide
  865. --| additional time routines common to all Ada Test and Evaluation
  866. --| Tool Set (ATETS) tools.
  867.  
  868. --| Requires
  869. --| All procedures and functions that perform IO use the
  870. --| predefined library package Text_IO and require that the
  871. --| specified file be opened by the calling program prior to use.
  872. --| All times and durations must be of types declared in the
  873. --| predefined library package Calendar.
  874.  
  875. --| Errors
  876. --| No error messages or exceptions are raised by any of the TimeLib
  877. --| procedures and functions. However, any Text_IO and Calendar
  878. --| exceptions that may be raised are allowed to pass, unhandled,
  879. --| back to the calling program.
  880.  
  881. --| N/A:  Raises, Modifies
  882.  
  883. --  Version         : 1.0
  884. --  Author          : Jeff England
  885. --  Initial Release : 05/19/85
  886. --  Last Modified   : 05/19/85
  887.  
  888.  
  889.  
  890. type Timing_Type is ( Raw, Wall_Clock );
  891.  
  892.  
  893. ----------------
  894. function Date_of ( --| Convert the date to a string
  895.     Date : Calendar.Time    --| The date to be converted
  896.     ) return string;
  897.  
  898.   --| Effects
  899.   --| Converts the date to a string in the format MM/DD/YYYY
  900.  
  901.   --| N/A:  Raises, Requires, Modifies, Errors
  902.  
  903.  
  904. ----------------------
  905. function Wall_Clock_of ( --| Convert seconds to wall clock time
  906.     Seconds : Calendar.Day_Duration  --| The time to be converted
  907.     ) return string;
  908.  
  909.   --| Effects
  910.   --| Converts the time of day or elapsed time, in seconds,
  911.   --| to a string in the format HH:MM:SS.FF.
  912.  
  913.   --| N/A:  Raises, Requires, Modifies, Errors
  914.  
  915.  
  916. -------------------------
  917. procedure Put_Time_of_Day ( --| Put the time of day to the file
  918.     Fyle    : in Text_IO.File_Type;    --| The output file
  919.     Seconds : in Calendar.Day_Duration --| The time to be output
  920.     );
  921.  
  922.   --| Effects
  923.   --| If Timing = WALL_CLOCK then the time is put to the file in the
  924.   --| format HH:MM:SS.FF. If Timing = RAW then the time of
  925.   --| day is put to the file using new Fixed_IO( Day_Duration ).
  926.   --|
  927.   --| Requires
  928.   --| Fyle must have been previously opened by the calling program.
  929.  
  930.   --| N/A:  Raises, Modifies, Errors
  931.  
  932.  
  933. ------------------
  934. procedure Put_Time ( --| Put the time to the file
  935.     Fyle : in Text_IO.File_Type;  --| The output file
  936.     Date : in Calendar.Time       --| The time to be output
  937.     );
  938.  
  939.   --| Effects
  940.   --| If Timing = WALL_CLOCK then the time is put to the file in the
  941.   --| format MM/DD/YYYY HH:MM:SS.FF. If Timing = RAW then the time of
  942.   --| day is put to the file using new Fixed_IO( Day_Duration ).
  943.   --|
  944.   --| Requires
  945.   --| Fyle must have been previously opened by the calling program.
  946.  
  947.   --| N/A:  Raises, Modifies, Errors
  948.  
  949.  
  950. --------------------
  951. procedure Set_Timing ( --| Set the method of recording timing data
  952.  
  953.     Timing : Timing_Type  --| The type of timing data to be recorded
  954.  
  955.     );
  956.  
  957.   --| Effects
  958.   --| Sets th method of recording timing data to either RAW or Wall_Clock.
  959.   --| If Timing = WALL_CLOCK then the time is put to the file in the
  960.   --| format MM/DD/YYYY HH:MM:SS.FF. If Timing = RAW then the time of
  961.   --| day is put to the file using new Fixed_IO( Day_Duration ).
  962.   --| Overhead for either method may vary from system to system.
  963.  
  964.   --| N/A:  Raises, Requires, Modifies, Errors
  965.  
  966.  
  967. end Time_Library_1;
  968. with TYPE_DEFINITIONS, IMPLEMENTATION_DEPENDENCIES, TIME_LIBRARY_1;
  969. with CALENDAR;
  970. -----------------
  971. package WRITE_LOG is
  972. -----------------
  973.  
  974. --| Overview
  975. --| Write_Log is an output package used by the Run Time Monitor (RTM)
  976. --| for the Ada Testing and Evaluation Tools. It performs all output
  977. --| to the Execution Log File (ELF) that is used to dynamically record
  978. --| information about programs written in the Ada language. The ELF is
  979. --| used for output by the Run Time Monitor (RTM) to record runtime
  980. --| information about the execution of the Ada program being
  981. --| tested. It is used as input by various report generators which
  982. --| summarize the information and present it in a meaningful format.
  983.  
  984. --| N/A: Errors, Raises, Modifies, Requires
  985.  
  986. --  Version         : 5.0
  987. --  Author          : Jeff England
  988. --  Last Modified   : 05/13/85
  989.  
  990.   use TYPE_DEFINITIONS;            --| Global type declarations for all of
  991.                                    --| the Ada Testing and Analysis Tools.
  992.  
  993.   use IMPLEMENTATION_DEPENDENCIES; --| Ada Compiler dependencies
  994.  
  995.   use TIME_LIBRARY_1;              --| For Timing_Type ( Wall_Clock, Raw )
  996.  
  997.   LOGFILE_ACCESS_ERROR : exception;--| Raised if attempt to:
  998.                                    --|   - open already open file
  999.                                    --|   - put to unopened file
  1000.                                    --|   - close unopened file
  1001.  
  1002.   --------------------
  1003.   procedure CREATE_LOG(--| Creates and opens the ELF for output
  1004.  
  1005.     LOGFILE_NAME  : in FILENAME;      --| Name of logfile to be created
  1006.  
  1007.     TIMING_METHOD : in TIME_LIBRARY_1.TIMING_TYPE := RAW;
  1008.                 --| The method of recording timing data
  1009.  
  1010.     START_TIME    : in CALENDAR.TIME  --| Program start time
  1011.  
  1012.       );
  1013.  
  1014.     --| Raises: Logfile_Access_Error
  1015.  
  1016.     --| Effects
  1017.     --| Creates and opens the ELF for output by the Run Time Monitor.
  1018.     --| If the logfile already exists it will be overwritten.
  1019.     --| The date and time of the test are written
  1020.     --| to the logfile. If the logfile is already open then a
  1021.     --| Logfile_Access_Error exception is raised. Any other
  1022.     --| Text_IO exceptions that may be raised are allowed to pass
  1023.     --| unhandled back to the calling program.
  1024.  
  1025.     --| Requires
  1026.     --| Logfile_Name must conform to the file naming conventions for
  1027.     --| the host computer operating system.
  1028.  
  1029.     --| N/A:  Modifies, Errors
  1030.  
  1031.  
  1032.   --------------------------------
  1033.   procedure PUT_CONFIGURATION_DATA(--| Records configuration info in the ELF
  1034.  
  1035.     TOOL_NAME    : in TOOL_NAMES;     --| Name of the tool
  1036.  
  1037.     PROGRAM_NAME : in ADA_NAME;       --| Program being tested
  1038.  
  1039.     TEST_IDENT   : in TEST_IDENTIFIER --| A unique identifier specified
  1040.                                       --| by the user
  1041.  
  1042.       );
  1043.  
  1044.     --| Raises: Logfile_Access_Error
  1045.  
  1046.     --| Effects
  1047.     --| Records test configuration information in the logfile. The purpose of
  1048.     --| recording this information in the logfile is to internally uniquely
  1049.     --| identify the logfile for later use by the report generators. If the
  1050.     --| logfile already exists it will be overwritten. If the logfile
  1051.     --| is already open then the exception Logfile_Access_Error is raised.
  1052.     --| Any other Text_IO exceptions that may  be raised are allowed to
  1053.     --| pass unhandled back to the calling program.
  1054.  
  1055.     --| Requires
  1056.     --| The logfile must have been previously opened via a call to the
  1057.     --| procedure Create_Log.
  1058.  
  1059.     --| N/A:  Modifies, Errors
  1060.  
  1061.  
  1062.   --------------------------
  1063.   procedure DEFINE_COMPILATION_UNIT(--| Define a new compilation unit
  1064.  
  1065.     COMPILATION_UNIT      : in ADA_NAME; --| Name of the compilation unit
  1066.  
  1067.     NUMBER_OF_BREAKPOINTS : in BREAKPOINT_NUMBER_RANGE;
  1068.       --| Number of breakpoints in the compilation unit
  1069.  
  1070.     LIST_OF_PROCEDURES    : in PROCEDURE_LIST --| Array of names and unit
  1071.                                               --| types of all program units
  1072.                                               --| in this compilation unit
  1073.       );
  1074.  
  1075.     --| Raises: Logfile_Access_Error
  1076.  
  1077.     --| Effects
  1078.     --| Defines a new Compilation Unit and all of its program units
  1079.     --| to the execution log file. Subsequent references by the calling
  1080.     --| program to program units in the current compilation unit will
  1081.     --| be by a unit ID of type Program_Unit where:
  1082.     --|
  1083.     --|   Unit_Identifier.Program_Unit_Number = offset into List_of_Procedures
  1084.     --|
  1085.     --| If the logfile has not been previously opened via a call to
  1086.     --| the procedure Create_Log then the exception Logfile_Access_Error
  1087.     --| is raised.
  1088.  
  1089.     --| Requires
  1090.     --| The log file must have been previously opened by the calling
  1091.     --| program via a call to Create_Log.
  1092.  
  1093.     --| N/A:  Modifies, Errors
  1094.  
  1095.  
  1096.   --------------------
  1097.   procedure START_UNIT(--| starts the current unit in the ELF
  1098.  
  1099.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1100.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1101.  
  1102.     START_TIME    : in out CALENDAR.TIME  --| Program unit start time
  1103.  
  1104.       );
  1105.  
  1106.     --| Effects
  1107.     --| Puts the program unit and start time to the execution log file.
  1108.  
  1109.     --| Requires
  1110.     --| The log file must have been previously opened by the calling
  1111.     --| program via a call to Create_Log.
  1112.  
  1113.     --| N/A:  Raises, Modifies, Errors
  1114.  
  1115.  
  1116.   -------------------
  1117.   procedure STOP_UNIT(--| Stops the current unit in the ELF
  1118.  
  1119.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1120.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1121.  
  1122.     STOP_TIME       : in out CALENDAR.TIME  --| Program unit stop time
  1123.  
  1124.       );
  1125.  
  1126.     --| Effects
  1127.     --| Puts the program unit and stop time to the execution log file.
  1128.  
  1129.     --| Requires
  1130.     --| The log file must have been previously opened by the calling
  1131.     --| program via a call to Create_Log.
  1132.     --| The program unit must have been previously defined to the log file by
  1133.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1134.  
  1135.     --| N/A:  Raises, Modifies, Errors
  1136.  
  1137.  
  1138.   -----------------------
  1139.   function STARTING_DELAY(--| Records a delay for the specified unit and
  1140.                           --| duration in the ELF
  1141.  
  1142.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1143.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1144.  
  1145.     SECONDS         : in DURATION
  1146.  
  1147.       ) return DURATION;
  1148.  
  1149.     --| Effects
  1150.     --| Records a delay for the specified unit and duration in the
  1151.     --| Execution Log File. The length of the Delay is returned to
  1152.     --| the calling unit.
  1153.  
  1154.     --| Requires
  1155.     --| The log file must have been previously opened by the calling
  1156.     --| program via a call to Create_Log.
  1157.     --| The program unit must have been previously defined to the log file by
  1158.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1159.  
  1160.     --| N/A:  Raises, Modifies, Errors
  1161.  
  1162.  
  1163.  ------------------------
  1164.   procedure PUT_BREAKPOINT(--| Puts info about the current breakpont to ELF
  1165.  
  1166.     BREAKPOINT_TYPE    : in BREAKPOINT_TYPES; --| The type of breakpoint
  1167.  
  1168.     UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1169.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1170.  
  1171.     CURRENT_BREAKPOINT : in BREAKPOINT_NUMBER_RANGE
  1172.     --| The breakpoint number assigned by the Source Instrumenter
  1173.       );
  1174.  
  1175.     --| Effects
  1176.     --| Puts the program unit, statement type, and current breakpoint
  1177.     --| number to the execution log file.
  1178.  
  1179.     --| Requires
  1180.     --| The log file must have been previously opened by the calling
  1181.     --| program via a call to Create_Log.
  1182.     --| The program unit must have been previously defined to the log file by
  1183.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1184.  
  1185.     --| N/A:  Raises, Modifies, Errors
  1186.  
  1187.  
  1188.   -----------------------------
  1189.   procedure PUT_CALL_PARAMETERS(--| Log AutoPath input parameter list to ELF
  1190.  
  1191.     CALL_PARAMETERS : in INPUT_PARAMETER_LIST
  1192.     --| The user specified input parameter list
  1193.  
  1194.       );
  1195.  
  1196.     --| Effects
  1197.     --| Logs the calling parameter list for a single execution of the
  1198.     --| unit under test by the AutoPath shell.
  1199.  
  1200.     --| Requires
  1201.     --| The log file must have been previously opened by the calling
  1202.     --| program via a call to Create_Log.
  1203.  
  1204.     --| N/A:  Raises, Modifies, Errors
  1205.  
  1206.  
  1207.   -------------------
  1208.   procedure PUT_VALUE(--| Logs value of integer variable to the ELF
  1209.  
  1210.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1211.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1212.  
  1213.     VARIABLE_NAME   : in STRING;  --| The name of the variable
  1214.  
  1215.     INTEGER_VALUE   : in INTEGER  --| The variable's value
  1216.  
  1217.       );
  1218.  
  1219.     --| Effects
  1220.     --| Logs integer values to the execution log file.
  1221.     --| Puts the program unit, variable name, and current value.
  1222.  
  1223.     --| Requires
  1224.     --| The log file must have been previously opened by the calling
  1225.     --| program via a call to Create_Log.
  1226.     --| The program unit must have been previously defined to the log file by
  1227.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1228.  
  1229.     --| N/A:  Raises, Modifies, Errors
  1230.  
  1231.  
  1232.   -------------------
  1233.   procedure PUT_VALUE(--| Logs value of Long_Integer variable to the ELF
  1234.  
  1235.     UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1236.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1237.  
  1238.     VARIABLE_NAME      : in STRING;      --| The name of the variable
  1239.  
  1240.     LONG_INTEGER_VALUE : in LONG_INTEGER --| The variable's value
  1241.  
  1242.       );
  1243.  
  1244.  
  1245.     --| Effects
  1246.     --| Logs long_integer values to the execution log file.
  1247.     --| Puts the program unit, variable name, and current value.
  1248.  
  1249.     --| Requires
  1250.     --| The log file must have been previously opened by the calling
  1251.     --| program via a call to Create_Log.
  1252.     --| The program unit must have been previously defined to the log file by
  1253.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1254.  
  1255.     --| N/A:  Raises, Modifies, Errors
  1256.  
  1257.  
  1258.   -------------------
  1259.   procedure PUT_VALUE(--| Logs value of FLOAT variable to the ELF
  1260.  
  1261.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1262.       --| A unique ID assigned by the Source Instrumenter for the current unit
  1263.  
  1264.     VARIABLE_NAME   : in STRING; --| The name of the variable
  1265.  
  1266.     FLOAT_VALUE     : in FLOAT   --| The variable's value
  1267.  
  1268.       );
  1269.  
  1270.     --| Effects
  1271.     --| Logs floating point values to the execution log file
  1272.     --| Puts the program unit, variable name, and current value
  1273.  
  1274.     --| Requires
  1275.     --| The log file must have been previously opened by the calling
  1276.     --| program via a call to Create_Log.
  1277.     --| The program unit must have been previously defined to the log file by
  1278.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1279.  
  1280.     --| N/A:  Modifies, Errors
  1281.  
  1282.  
  1283.   -------------------
  1284.   procedure PUT_VALUE(--| Logs value of Long_Float variable to the ELF
  1285.  
  1286.     UNIT_IDENTIFIER  : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1287.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1288.  
  1289.     VARIABLE_NAME    : in STRING;     --| The name of the variable
  1290.  
  1291.     LONG_FLOAT_VALUE : in LONG_FLOAT  --| The variable's value
  1292.  
  1293.       );
  1294.  
  1295.     --| Effects
  1296.     --| Logs long_float values to the execution log file.
  1297.     --| Puts the program unit, variable name, and current value.
  1298.  
  1299.     --| Requires
  1300.     --| The log file must have been previously opened by the calling
  1301.     --| program via a call to Create_Log.
  1302.     --| The program unit must have been previously defined to the log file by
  1303.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1304.  
  1305.     --| N/A:  Raises, Modifies, Errors
  1306.  
  1307.  
  1308.   -------------------
  1309.   procedure PUT_VALUE(--| Logs value of string variable to the ELF
  1310.  
  1311.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1312.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1313.  
  1314.     VARIABLE_NAME   : in STRING; --| The name of the variable
  1315.  
  1316.     STRING_VALUE    : in STRING  --| The variable's value
  1317.  
  1318.       );
  1319.  
  1320.     --| Effects
  1321.     --| Logs string values to the execution log file
  1322.     --| Puts the program unit, variable name, and current value
  1323.     --| This procedure used to log the value of
  1324.     --|        strings
  1325.     --|        characters
  1326.     --|        enumerated data types (including booleans)
  1327.  
  1328.     --| Requires
  1329.     --| The log file must have been previously opened by the calling
  1330.     --| program via a call to Create_Log.
  1331.     --| The program unit must have been previously defined to the log file by
  1332.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  1333.  
  1334.     --| N/A:  Raises, Modifies, Errors
  1335.  
  1336.  
  1337.   -------------------
  1338.   procedure CLOSE_LOG(  --| Closes the execution log file
  1339.  
  1340.     ACCUMULATED_OVERHEAD : in DURATION  --| Total accumulated tool overhead
  1341.  
  1342.       );
  1343.  
  1344.     --| Raises:  Logfile_Access_Error
  1345.  
  1346.     --| Effects
  1347.     --| Closes the execution log file.
  1348.     --| If the logfile has not been previously opened via a call to
  1349.     --| the procedure Create_Log then the exception Logfile_Access_Error
  1350.     --| is raised.
  1351.  
  1352.     --| Requires
  1353.     --| The log file must have been previously opened by the calling
  1354.     --| program via a call to Create_Log.
  1355.  
  1356.     --| N/A:  Modifies, Errors
  1357.  
  1358. end WRITE_LOG;
  1359. with TYPE_DEFINITIONS; use TYPE_DEFINITIONS; 
  1360. with STRING_PKG; use STRING_PKG; 
  1361. with TEXT_IO; use TEXT_IO; 
  1362.  
  1363.  
  1364. package RTM_LIST_PACKAGE is 
  1365.  
  1366. --| Overview
  1367. --|      The RTM_List_Package is a subset of the Lists package from Inter-
  1368. --| metrics in Cambridge.  It is tailored explicitly for the Run_Time_Monitor.
  1369. --| The type of the list objects is Program_Unit_Unique_Identifier, which is 
  1370. --| declared in Type_Definitions.
  1371. --| The procedures and functions allow the RTM to create a list, add to a 
  1372. --| list, delete an item from the list, read and replace an item after 
  1373. --| incrementing the Task_Type_Activation_Number, and check for an empty 
  1374. --| list.
  1375.  
  1376. --| N/A: Effects, Requires, Modifies, Raises
  1377.  
  1378.  
  1379. --  Mary Koppes  Intermetrics Inc, Huntington Beach,Ca  11-June-85
  1380.  
  1381.  
  1382. --   TYPES
  1383.  
  1384.  
  1385.   type LIST is private; 
  1386.  
  1387.  
  1388.  
  1389. -------------------------------------------------------------------------------
  1390.  
  1391.   function CREATE --| Return an empty list
  1392.  
  1393.   return LIST; 
  1394.  
  1395.  
  1396. -------------------------------------------------------------------------------
  1397.  
  1398.  
  1399.   procedure ADD( --| Add an element to the list
  1400.  
  1401.     ELEMENT : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1402.     --| The Unit_ID being added to the list
  1403.  
  1404.     TO_LIST : in out LIST --| List being added to
  1405.  
  1406.     ); 
  1407.  
  1408.   --| Effects    
  1409.   --| Adds  an element onto to the end of the list, To_List.  If
  1410.   --| To_List is empty then this may change the value of Element.
  1411.  
  1412.   --| Modifies
  1413.   --| The "NEXT" field of To_List;
  1414.  
  1415.  
  1416. -------------------------------------------------------------------------------
  1417.  
  1418.  
  1419.   procedure DELETE_HEAD( --|  Remove the Head element
  1420.  
  1421.     THE_LIST : in out LIST --|  The list whose head is being removed
  1422.  
  1423.     ); 
  1424.  
  1425.   --| Raises
  1426.   --| Empty_List
  1427.  
  1428.   --| Effects
  1429.   --| This will return the space occupied by the first element in the list
  1430.   --| to the heap.  If sharing exists between lists, this procedure could
  1431.   --| leave a dangling reference.  If The_List is empty, EmptyList is 
  1432.   --| raised.
  1433.  
  1434.  
  1435. -------------------------------------------------------------------------------
  1436.  
  1437.  
  1438.  
  1439.   procedure DELETE( --| Delete an element from the list
  1440.  
  1441.     ELEMENT   : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;  --| Elt to be deleted
  1442.  
  1443.     FROM_LIST : in out LIST --| List to delete from
  1444.  
  1445.     ); 
  1446.  
  1447.   --| Raises
  1448.   --| Item_Not_Present
  1449.  
  1450.   --| Effects
  1451.   --| This procedure walks down the list, From_List, and removes the first 
  1452.   --| element equal to Element.  If there is not an element equal to
  1453.   --| Element, ItemNotPresent is raised.
  1454.  
  1455.   --| Modifies
  1456.   --| Returns the storage being occupied by the deleted element.
  1457.  
  1458.  
  1459. -------------------------------------------------------------------------------
  1460.  
  1461.  
  1462.   procedure REPLACE_VALUE( --| Finds element and increments the Task number
  1463.  
  1464.     NEW_ELEMENT : in out PROGRAM_UNIT_UNIQUE_IDENTIFIER; 
  1465.  
  1466.     NEW_LIST    : in out LIST); 
  1467.  
  1468.  
  1469.   --| Effects
  1470.   --| Replace_Value walks through New_List searching for New_Element. 
  1471.   --| If New_Element is found, the Task_Type_Activation_Number is incremented
  1472.   --| in the list element and New_Element is assigned this number too.
  1473.   --| The Element is replaced in the list.
  1474.  
  1475.   --| Modifies
  1476.   --| The specified element.Task_Type_Activation_Number is incremented
  1477.  
  1478. -------------------------------------------------------------------------------
  1479.  
  1480.  
  1481.  
  1482.   function IS_IN_LIST( --| Checks for the presence of Element in The_List.
  1483.  
  1484.     THE_LIST : in LIST; 
  1485.  
  1486.     ELEMENT  : in PROGRAM_UNIT_UNIQUE_IDENTIFIER
  1487.  
  1488.     ) return BOOLEAN; 
  1489.  
  1490.  
  1491.   --| Effects
  1492.   --| Walks down the list The_List looking for an element whose value is
  1493.   --| Element.
  1494.  
  1495.  
  1496. -------------------------------------------------------------------------------
  1497.  
  1498.  
  1499.   function IS_EMPTY( --| Checks for an empty list
  1500.  
  1501.     THE_LIST : in LIST) return BOOLEAN; 
  1502.  
  1503.  
  1504.  
  1505. -------------------------------------------------------------------------------
  1506.  
  1507.  
  1508.   function EQUAL( --| Compares X to Y and returns TRUE if they are equal
  1509.  
  1510.     X, Y : in PROGRAM_UNIT_UNIQUE_IDENTIFIER) return BOOLEAN;
  1511.  
  1512.  
  1513. -------------------------------------------------------------------------------
  1514.  
  1515.  
  1516. private
  1517.   type LIST_ELEMENT; 
  1518.   type LIST is access LIST_ELEMENT; 
  1519.   type LIST_ELEMENT is 
  1520.     record
  1521.       INFO         : PROGRAM_UNIT_UNIQUE_IDENTIFIER; 
  1522.       NEXT_ELEMENT : LIST; 
  1523.     end record; 
  1524.  
  1525.  
  1526. end RTM_LIST_PACKAGE; 
  1527. with IMPLEMENTATION_DEPENDENCIES; use IMPLEMENTATION_DEPENDENCIES;
  1528. with TYPE_DEFINITIONS;            use TYPE_DEFINITIONS;
  1529. with STRING_PKG;                  use STRING_PKG;
  1530.  
  1531. ------------------------
  1532. package RUN_TIME_MONITOR is
  1533. ------------------------
  1534.  
  1535.  
  1536. --| Overview
  1537. --|     This is the Run Time Monitor package for the Ada Test and
  1538. --| Analysis Tool Set (ATETS). Its purpose is to dynamically record
  1539. --| information about the execution of programs written in the
  1540. --| Ada language. The Run Time Monitor is common to the following
  1541. --| ATETS tools:
  1542. --|
  1543. --|   1) Path     - Path Analyzer
  1544. --|   2) AutoPath - Automatic Path Analyzer
  1545. --|   3) SMART    - Self Metric Analysis and Reporting Tool
  1546. --|   4) Profile  - Performance Analyzer
  1547. --|
  1548. --|     The Run Time Monitor is implemented as a package that is
  1549. --| WITHed and USEd by the Ada program being tested.  All WITHs,
  1550. --| USEs, and calls to the Run Time Monitor procedures are inserted
  1551. --| into the target Ada program by the ATETS Source Instrumenter.
  1552. --| The execution data about each Ada program unit that has been
  1553. --| instrumented is recorded at runtime in an Execution Log File (ELF).
  1554. --|
  1555. --|     The user must select the recording options to be used at
  1556. --| run time by specifying one of the above tools as a runtime
  1557. --| parameter. Additionally, the user may specify the name of the
  1558. --| log file to be generated during execution of the target Ada
  1559. --| program. If no log file name is specified by the user then the
  1560. --| default log file name will be <toolname>".LOG".  The Run Time
  1561. --| Monitor checks for the existance of the logfile and if it exists
  1562. --| the user must choose to write over it, append to it or select
  1563. --| a new filename.
  1564. --|
  1565. --| Requires
  1566. --| The Ada program to be tested must have been instrumented by
  1567. --| the Ada Source Instrumenter to insert "hooks", or calls, to the
  1568. --| the Runtime Monitor.  Information about each program unit in an
  1569. --| instrumented compilation unit must be recorded in the ELF via
  1570. --| a call to the procedure Unit_Information prior to execution of
  1571. --| the program unit. An Ada program unit is a procedure, function,
  1572. --| package, task, or generic.
  1573.  
  1574. --| N/A:  Errors, Raises, Modifies
  1575.  
  1576. --  Version         : 5.0
  1577. --  Author          : Mary Koppes  Intermetrcs, Inc.
  1578. --  Initial Release : 03/23/85
  1579. --  Last Modified   : 07/16/85
  1580.  
  1581.  
  1582.   task RTM is
  1583.  
  1584.     --| Overview
  1585.     --| The Run Time Monitor has been implemented as a task in order
  1586.     --| to synchronize calls from the instrumented program and prevent
  1587.     --| interleaving of output to th log file.
  1588.  
  1589.  
  1590.     ----------------------
  1591.     entry UNIT_INFORMATION( --| Defines a compilation unit to the RTM
  1592.  
  1593.       COMPILATION_UNIT   : in ADA_NAME;
  1594.       --| The name of the compilation unit
  1595.  
  1596.       BREAKPOINT_NUMBER  : in BREAKPOINT_NUMBER_RANGE;
  1597.       --| Total number of break points in the compilation unit
  1598.       --| assigned by the Source Instrumenter
  1599.  
  1600.       LIST_OF_PROCEDURES : in PROCEDURE_LIST
  1601.       --| A list of the names of all of the program units in
  1602.       --| the compilation unit
  1603.  
  1604.         );
  1605.  
  1606.     --| Effects
  1607.     --| Unit_Information is the procedure used to define information about
  1608.     --| each program unit in a compilation unit.  If the program unit is
  1609.     --| the first program unit to be defined by a call to Unit_Information
  1610.     --| the user is asked to enter the Tool_Name, Logfile Name and a
  1611.     --| unique test identification string, if desired.  The logfile is
  1612.     --| opened.  The rest of the information is not recorded to the logfile
  1613.     --| at this time.  A unique identifier is created by the Source
  1614.     --| Instrumenter for each program unit which provides a mechanism for
  1615.     --| handling overloading of unit names. This procedure defines the
  1616.     --| correlation between program unit names and program unit ID's
  1617.     --| assigned by the Source Instrumenter. The information is recorded
  1618.     --| in the execution log file for later use by the report generators.
  1619.  
  1620.     --| Requires
  1621.     --| Each program unit must be previously defined to the Runtime Monitor
  1622.     --| by a call to this procedure prior to being "entered" or "exited."
  1623.  
  1624.     --| Raises
  1625.     --| User_Input_Error
  1626.  
  1627.     --| N/A:  Errors, Modifies
  1628.  
  1629.  
  1630.     -------------------
  1631.     entry ENTERING_UNIT( --| Logs program unit and start time to ELF
  1632.  
  1633.       ENCLOSING_UNIT : in STRING_TYPE;
  1634.       --| The name of the compilation unit
  1635.  
  1636.       UNIT_NUMBER    : in PROGRAM_UNIT_NUMBER_RANGE;
  1637.       --| The Program Unit Number
  1638.  
  1639.       UNIT_TYPE      : in PROGRAM_UNIT_TYPE;
  1640.       --| The type of unit ( procedure, function task generic or package )
  1641.  
  1642.       TASK_NUMBER    : in out TASK_TYPE_ACTIVATION_NUMBER_RANGE
  1643.       --| A unique number assigned by the Runtime Monitor
  1644.  
  1645.       );
  1646.  
  1647.     --| Effects
  1648.     --| Entering_Unit first creates a Unit_Identifier from the
  1649.     --| four procedure parameters.  If the program unit is
  1650.     --| the first program unit to be entered outside of Package
  1651.     --| initialization and its UNIT_TYPE is PROCEDURE_TYPE, then
  1652.     --| it is assumed to be the main program unit.
  1653.     --| When the main procedure is entered, the Tool_Name, Test ID and
  1654.     --| the Main procedure name are written to the logfile.
  1655.     --| For each program unit entered, the Logfile_Key "Unit_START"
  1656.     --| and the unit ID assigned by the Source Instrumenter (Unit_Identifier)
  1657.     --| are recorded in the log file by calling the Start_Unit procedure
  1658.     --| which is part of the Write_Log package.
  1659.     --| If the unit being entered is a task then if the Task_List has not
  1660.     --| been created it is and the ID is added to the list.  The purpose of
  1661.     --| this list is to maintain the Task_Type_Activation_Number. This
  1662.     --| number is initially 1 and each time a task of the same type is
  1663.     --| added to the Task_List, the activation number is incremented.
  1664.     --| The Task_Type_Activation_Number is written to the logfile and is
  1665.     --| used by the ATETS report generators to determine which copy of a
  1666.     --| task is executing.  The IN OUT parameter, Task_Number is also
  1667.     --| updated to pass back to the calling program.
  1668.  
  1669.     --| Requires
  1670.     --| A program unit must be previously defined to the Runtime Monitor
  1671.     --| via a call to the procedure Unit_Information prior to being "entered."
  1672.  
  1673.     --| N/A:  Raises, Errors, Modifies
  1674.  
  1675.  
  1676.     ------------------
  1677.     entry EXITING_UNIT( --| Logs program unit and stop time to ELF
  1678.  
  1679.       UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER
  1680.       --| A unique ID assigned by the Source Instrumenter
  1681.  
  1682.       );
  1683.  
  1684.     --| Effects
  1685.     --| Exiting_Unit records to the logfile the Logfile_Key "UNIT_STOP"
  1686.     --| and the Unit_Identifier assigned by the Source Instrumenter.
  1687.     --| If Package Initialization is not in progress, then the
  1688.     --| Unit_Identifier is deleted from the Entered_Unit_List.
  1689.     --| The main program unit is "held" from exiting until all
  1690.     --| other program units have terminated. If the unit being is
  1691.     --| the main program unit then the logfile is closed and if
  1692.     --| the user has chosen to append to an existing logfile
  1693.     --| it is done at this time.
  1694.  
  1695.     --| Requires
  1696.     --| The program unit must be previously defined to the RTM via a call
  1697.     --| to the procedure Unit_Information.
  1698.     --| The program unit must have been previously "entered" via a call to
  1699.     --| the procedure Entering_Unit prior to being "exited."
  1700.  
  1701.     --| Raises
  1702.     --| Unit_Exit_Error
  1703.  
  1704.     --| N/A:  Errors, Modifies
  1705.  
  1706.  
  1707.     -------------------
  1708.     entry BREAKPOINT_AT( --| Process program breakpoint
  1709.  
  1710.       UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1711.       --| A unique ID assigned by the Source Instrumenter
  1712.  
  1713.       BREAKPOINT_TYPE    : in BREAKPOINT_TYPES;
  1714.       --| The type of breakpoint
  1715.  
  1716.       CURRENT_BREAKPOINT : in BREAKPOINT_NUMBER_RANGE
  1717.       --| Breakpoint number assigned by Source Instrumenter
  1718.  
  1719.       );
  1720.  
  1721.     --| Effects
  1722.     --| case TOOL_NAME
  1723.     --|   when PATH_TOOL | AUTOPATH_TOOL | SMART_TOOL =>
  1724.     --|        log program unit ID (Unit_ID)
  1725.     --|        log type of breakpoint (Breakpoint_Type)
  1726.     --|        log the current breakpoint number (Current_Breakpoint)
  1727.     --|   when PROFILE_TOOL => null;  -- no action for PROFILE
  1728.     --|   when others  => null;
  1729.     --| end case;
  1730.  
  1731.     --| Requires
  1732.     --| The program unit must be previously defined to the RTM via a call
  1733.     --| to the procedure Unit_Information.
  1734.     --| The program unit must have been previously "entered" via a call to
  1735.     --| the procedure Entering_Unit.
  1736.  
  1737.     --| N/A:  Raises, Errors, Modifies
  1738.  
  1739.  
  1740.     -------------------------
  1741.     entry PUT_CALL_PARAMETERS(--| Log AutoPath input parameter list to ELF
  1742.  
  1743.       CALL_PARAMETERS : in INPUT_PARAMETER_LIST
  1744.       --| The user specified input parameter list
  1745.  
  1746.       );
  1747.  
  1748.     --| Effects
  1749.     --| Logs the calling parameter list for a single execution of the
  1750.     --| unit under test by the AutoPath shell.
  1751.  
  1752.     --| N/A:  Raises, Requires, Modifies, Errors
  1753.  
  1754.  
  1755.     ---------------
  1756.     entry PUT_VALUE(--| Logs value of integer variable to the ELF
  1757.  
  1758.       UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1759.       --| A unique ID assigned by the Source Instrumenter for the current unit
  1760.  
  1761.       VARIABLE_NAME   : in STRING;  --| The name of the variable
  1762.  
  1763.       INTEGER_VALUE   : in INTEGER  --| The variable's value
  1764.  
  1765.       );
  1766.  
  1767.     --| Effects
  1768.     --| Logs integer values to the execution log file.
  1769.     --| Puts the program unit, variable name, and current value.
  1770.  
  1771.     --| N/A:  Raises, Requires, Modifies, Errors
  1772.  
  1773.  
  1774.     ---------------
  1775.     entry PUT_VALUE(--| Logs value of Long_Integer variable to the ELF
  1776.  
  1777.       UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1778.       --| A unique ID assigned by the Source Instrumenter for the current unit
  1779.  
  1780.       VARIABLE_NAME      : in STRING;      --| The name of the variable
  1781.  
  1782.       LONG_INTEGER_VALUE : in LONG_INTEGER --| The variable's value
  1783.  
  1784.       );
  1785.  
  1786.     --| Effects
  1787.     --| Logs long_integer values to the execution log file.
  1788.     --| Puts the program unit, variable name, and current value.
  1789.  
  1790.     --| N/A:  Raises, Requires, Modifies, Errors
  1791.  
  1792.  
  1793.     ---------------
  1794.     entry PUT_VALUE(--| Logs value of FLOAT variable to the ELF
  1795.  
  1796.       UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1797.       --| A unique ID assigned by the Source Instrumenter for the current unit
  1798.  
  1799.       VARIABLE_NAME   : in STRING; --| The name of the variable
  1800.  
  1801.       FLOAT_VALUE     : in FLOAT   --| The variable's value
  1802.  
  1803.       );
  1804.  
  1805.     --| Effects
  1806.     --| Logs floating point values to the execution log file
  1807.     --| Puts the program unit, variable name, and current value
  1808.  
  1809.     --| N/A:  Raises, Requires, Modifies, Errors
  1810.  
  1811.  
  1812.     ---------------
  1813.     entry PUT_VALUE(--| Logs value of Long_Float variable to the ELF
  1814.  
  1815.       UNIT_IDENTIFIER  : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1816.       --| A unique ID assigned by the Source Instrumenter for the current unit
  1817.  
  1818.       VARIABLE_NAME    : in STRING;     --| The name of the variable
  1819.  
  1820.       LONG_FLOAT_VALUE : in LONG_FLOAT  --| The variable's value
  1821.  
  1822.       );
  1823.  
  1824.     --| Effects
  1825.     --| Logs long_float values to the execution log file.
  1826.     --| Puts the program unit, variable name, and current value.
  1827.  
  1828.     --| N/A:  Raises, Requires, Modifies, Errors
  1829.  
  1830.  
  1831.     ---------------
  1832.     entry PUT_VALUE(--| Logs value of string variable to the ELF
  1833.  
  1834.       UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1835.       --| A unique ID assigned by the Source Instrumenter for the current unit
  1836.  
  1837.       VARIABLE_NAME   : in STRING; --| The name of the variable
  1838.  
  1839.       STRING_VALUE    : in STRING  --| The variable's value
  1840.  
  1841.       );
  1842.  
  1843.     --| Effects
  1844.     --| Logs string values to the execution log file
  1845.     --| Puts the program unit, variable name, and current value
  1846.     --| This procedure used to log the value of
  1847.     --|        strings
  1848.     --|        characters
  1849.     --|        enumerated data types (including booleans)
  1850.  
  1851.     --| N/A:  Raises, Requires, Modifies, Errors
  1852.  
  1853.  
  1854.   -----------------
  1855.   entry START_DELAY(--| Records a delay for the specified unit and
  1856.                           --| duration in the ELF
  1857.  
  1858.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1859.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1860.  
  1861.     SECONDS         : in DURATION
  1862.     --| The length of the delay in seconds
  1863.  
  1864.       );
  1865.  
  1866.     --| Effects
  1867.     --| Records a delay for the specified unit and duration in the
  1868.     --| Execution Log File. This entry is not called directly by the
  1869.     --| the instrumented program. It is called by the function
  1870.     --| Starting_Delay.
  1871.  
  1872.     --| N/A:  Raises, Requires, Modifies, Errors
  1873.  
  1874.  
  1875.   end RTM;
  1876.  
  1877.  
  1878.   -----------------------
  1879.   function STARTING_DELAY(--| Records a delay for the specified unit and
  1880.                           --| duration in the ELF
  1881.  
  1882.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  1883.     --| A unique ID assigned by the Source Instrumenter for the current unit
  1884.  
  1885.     SECONDS         : in DURATION
  1886.  
  1887.       ) return DURATION;
  1888.  
  1889.     --| Effects
  1890.     --| Records a delay for the specified unit and duration in the
  1891.     --| Execution Log File. The length of the Delay is returned to
  1892.     --| the calling unit. This unit is implemented as a function
  1893.     --| to enable trapping of delay times in timed entry statements.
  1894.  
  1895.     --| N/A:  Raises, Requires, Modifies, Errors
  1896.  
  1897.  
  1898. end RUN_TIME_MONITOR;
  1899. with IMPLEMENTATION_DEPENDENCIES; use IMPLEMENTATION_DEPENDENCIES;
  1900.  
  1901. with TYPE_DEFINITIONS; use TYPE_DEFINITIONS;
  1902.  
  1903. with STRING_PKG; use STRING_PKG;
  1904.  
  1905. with WRITE_LOG; use WRITE_LOG;
  1906.  
  1907. with RTM_LIST_PACKAGE; use RTM_LIST_PACKAGE;
  1908.  
  1909. with TEXT_IO; use TEXT_IO;
  1910.  
  1911. with TIME_LIBRARY_1; use TIME_LIBRARY_1;
  1912.  
  1913. with FILE_MANAGER; use FILE_MANAGER;
  1914.  
  1915. with Calendar;
  1916.  
  1917. -----------------------------
  1918. package body RUN_TIME_MONITOR is
  1919. -----------------------------
  1920.  
  1921.  
  1922. -- Version         : 5.0
  1923. -- Author          : Mary Koppes  Intermetrics, Inc.
  1924. -- Initial release : 05/01/85
  1925. -- Last modified   : 07/18/85
  1926.  
  1927.  
  1928. -----------------------------------------------------------------------
  1929.  
  1930. -- Variables to be used by the RTM procedures
  1931.  
  1932.  
  1933.   TASK_LIST : LIST;
  1934.   --| To keep track of the tasks of task type which have been entered.
  1935.   --| This list is used to maintain the Task_Type_Activation_Number,
  1936.   --| which is incremented each time the task type is "Entered" via
  1937.   --| Entering_Unit.
  1938.  
  1939.   LOGFILE_OPEN : BOOLEAN := FALSE;
  1940.   --| To flag whether the logfile has been opened for this execution of RTM
  1941.  
  1942.   PACKAGE_INITIALIZATION_IN_PROGRESS : BOOLEAN := FALSE;
  1943.   --| To flag whether a package is running.
  1944.  
  1945.   MAIN_PROCEDURE_ENTERED : BOOLEAN := FALSE;
  1946.   --| Flags whether main procedure has been entered
  1947.  
  1948.   FIRST_TASK_ENTERED     : BOOLEAN := FALSE;
  1949.   --| Flags whether a task has been entered.
  1950.  
  1951.   LOGFILE_NAME        : FILENAME;  --| Logfile for this execution
  1952.   APPEND_LOGFILE_NAME : FILENAME;  --| Name of the logfile to append to
  1953.  
  1954.   APPEND_LOGFILE : BOOLEAN := FALSE;
  1955.   --| Flags if the user decided to append. If TRUE then the
  1956.   --| logfile is given a temp name and then appended to
  1957.   --| Append_Logfile_Name when the program is finished
  1958.   --| executing.
  1959.  
  1960.   TOOL_IN_USE : TOOL_NAMES; --| The tool being used during this execution
  1961.  
  1962.   USER_INPUT_ERROR   : exception;
  1963.   --| Raised when user input is bad, not handled by the RTM so it will
  1964.   --| propagate back to the instrumented program and cause the program
  1965.   --| to end.
  1966.  
  1967.   TEST_IDENTIFICATION  : TEST_IDENTIFIER;
  1968.   STOP_WATCH           : CALENDAR.TIME;
  1969.   ACCUMULATED_OVERHEAD : DURATION := 0.00;
  1970.  
  1971.   package TOOL_IO is
  1972.     new ENUMERATION_IO(TOOL_NAMES);
  1973.   use TOOL_IO;
  1974.  
  1975.   --------------------
  1976.   procedure QUERY_USER(
  1977.   --| Asks the user for the Tool_Name, Logfile_Name, and Test ID
  1978.  
  1979.     TOOL_NAME        : in out TOOL_NAMES;
  1980.     --| The tool being used during this execution
  1981.  
  1982.     LOGFILE_NAME     : in out FILENAME;
  1983.     --| The name of the log file
  1984.  
  1985.     TEST_DESCRIPTION : out TEST_IDENTIFIER;
  1986.     --| User may may enter a brief description of test
  1987.  
  1988.     RETURN_ERROR     : out BOOLEAN
  1989.     --| Flags a User Input Error
  1990.  
  1991.     ) is
  1992.  
  1993.   --| Algorithm
  1994.   --| Query_User prompts the user for the Tool he wishes to run.  The user must
  1995.   --| enter a valid toolname or he will continue to be asked for the toolname.
  1996.   --| Next he is prompted for the logfile name. If no logfile name is entered,
  1997.   --| the default "Toolname.LOG" is used.  Query_User checks for the existence
  1998.   --| of the logfile and if it does exist, the user is asked whether he wishes
  1999.   --| to Overwrite the file, Append to the file, or Enter a new filename.
  2000.   --| Finally, the user is asked to enter a unique test identification, which
  2001.   --| is an Ada string that describes the test being run.  The default is
  2002.   --| "Toolname Report".
  2003.  
  2004.  
  2005.     MAX_STRING_SIZE : constant NATURAL := 80;
  2006.     INPUT_STRING    : STRING(1 .. MAX_STRING_SIZE);
  2007.     --| Variable to hold user input from a Get_Line.
  2008.  
  2009.     STRING_LENGTH   : NATURAL := 0;
  2010.     --| Last char in string (length of string) returned by Get_Line.
  2011.  
  2012.     ZERO_LENGTH     : constant NATURAL := 0;
  2013.  
  2014.  
  2015.     --  Default Logfile names
  2016.  
  2017.     PATH_LOGFILE_NAME      : constant STRING := "Path.Log";
  2018.     AUTOPATH_LOGFILE_NAME  : constant STRING := "Autopath.log";
  2019.     SMART_LOGFILE_NAME     : constant STRING := "Smart.Log";
  2020.     PROFILE_LOGFILE_NAME   : constant STRING := "Profile.Log";
  2021.  
  2022.     TEMPORARY_LOGFILE_NAME : constant STRING := "MRKZZZ.LOG";
  2023.     --| Temporary name for logfile if it is to be appended to existing file
  2024.  
  2025.     -- The following are the defaults for the Test Id
  2026.     DEFAULT_IDENTIFICATION : constant array
  2027.       (TOOL_NAMES range PATH_TOOL .. PROFILE_TOOL) of STRING(1 .. 30) :=
  2028.       ("Path Analysis Report          ", "Automatic Path Analysis Report",
  2029.        "Self Metric Analysis Report   ", "Performance Analysis Report   ");
  2030.  
  2031.     BAD_USER_INPUT : BOOLEAN := TRUE;  --| General loop flag
  2032.  
  2033.     TEST_FILE      : FILE_TYPE;
  2034.  
  2035.     type USER_FILE_OPTIONS is (E, O, A);
  2036.  
  2037.     FILE_OPTION    : USER_FILE_OPTIONS;
  2038.  
  2039.     ENTER_NEW_NAME : constant USER_FILE_OPTIONS := E;
  2040.     OVERWRITE_FILE : constant USER_FILE_OPTIONS := O;
  2041.     APPEND_TO_FILE : constant USER_FILE_OPTIONS := A;
  2042.  
  2043.     package INT_IO is
  2044.       new INTEGER_IO(INTEGER);  -- debug
  2045.     use INT_IO;
  2046.  
  2047.     ------------------------
  2048.     function GET_USER_OPTION
  2049.     --| Get the user's option if the specified logfile exists.
  2050.  
  2051.     return USER_FILE_OPTIONS is
  2052.  
  2053.     --| Algorithm
  2054.     --| Get_User_Option is one loop which asks the user whether he wishes
  2055.     --| to Overwrite an existing logfile, Append to an existing logfile,
  2056.     --| or Enter a new filename.  This option is returned to the caller.
  2057.  
  2058.  
  2059.       CHOSEN_OPTION : USER_FILE_OPTIONS;
  2060.  
  2061.       package OPTION_IO is
  2062.         new ENUMERATION_IO(USER_FILE_OPTIONS);
  2063.       use OPTION_IO;
  2064.  
  2065.     begin
  2066.       loop
  2067.  
  2068.         -- infinite loop until function return
  2069.         begin
  2070.  
  2071.           NEW_LINE;
  2072.           PUT_LINE("File already exists!!! Do you wish to:");
  2073.           PUT_LINE("     E = Enter a New Filename");
  2074.           PUT_LINE("     O = Overwrite existing file");
  2075.           PUT_LINE("     A = Append to the existing file");
  2076.           NEW_LINE;
  2077.           PUT("Enter Option ===> ");
  2078.           GET(CHOSEN_OPTION);
  2079.  
  2080.           --  Get_Line to get rid of the carriage return
  2081.           GET_LINE(INPUT_STRING, STRING_LENGTH);
  2082.           return CHOSEN_OPTION;
  2083.  
  2084.         exception
  2085.           when DATA_ERROR =>
  2086.             PUT_LINE("Data_Error!! Illegal Option, Try again.");
  2087.             --  Get_Line to flush the bad input
  2088.             GET_LINE(INPUT_STRING, STRING_LENGTH);
  2089.  
  2090.           when others =>
  2091.             raise USER_INPUT_ERROR;
  2092.         end;
  2093.       end loop;
  2094.  
  2095.     end GET_USER_OPTION;
  2096.  
  2097.  
  2098.  
  2099.   begin
  2100.  
  2101.     STRING_PKG.MARK;  --  For Heap Management
  2102.  
  2103.     -- First get the Tool_Name, loop until input is correct
  2104.     while BAD_USER_INPUT loop
  2105.       begin
  2106.  
  2107.         NEW_LINE;
  2108.         NEW_LINE;
  2109.  
  2110.         PUT_LINE("Enter Tool Type : PATH_TOOL, AUTOPATH_TOOL,");
  2111.         PUT_LINE("                  SMART_TOOL, or PROFILE_TOOL)");
  2112.         PUT("-----> ");
  2113.         GET(TOOL_NAME);
  2114.  
  2115.         -- Get_Line to flush out the Carriage Return
  2116.         GET_LINE(INPUT_STRING, STRING_LENGTH);
  2117.         BAD_USER_INPUT := FALSE;
  2118.  
  2119.       exception
  2120.         when DATA_ERROR =>
  2121.           PUT_LINE(" Data_Error !! Illegal Tool Name, try again");
  2122.  
  2123.         when others =>
  2124.           raise USER_INPUT_ERROR;
  2125.  
  2126.       end;
  2127.     end loop;
  2128.  
  2129.  
  2130.     NEW_LINE;
  2131.     NEW_LINE;
  2132.     BAD_USER_INPUT := TRUE;
  2133.  
  2134.     while BAD_USER_INPUT loop
  2135.       begin
  2136.         NEW_LINE;
  2137.         PUT_LINE("Enter Logfile Name, Null for Default");
  2138.         PUT("-----> ");
  2139.         GET_LINE(INPUT_STRING, STRING_LENGTH);
  2140.  
  2141.         if STRING_LENGTH > ZERO_LENGTH then
  2142.           LOGFILE_NAME := MAKE_PERSISTENT(INPUT_STRING(1 .. STRING_LENGTH));
  2143.  
  2144.         else  -- length is zero therefore use the default name
  2145.  
  2146.           case TOOL_NAME is
  2147.  
  2148.             when PATH_TOOL =>
  2149.               STRING_LENGTH := PATH_LOGFILE_NAME'LAST;
  2150.               INPUT_STRING(1 .. STRING_LENGTH) := PATH_LOGFILE_NAME;
  2151.               LOGFILE_NAME := MAKE_PERSISTENT(PATH_LOGFILE_NAME);
  2152.  
  2153.             when AUTOPATH_TOOL =>
  2154.               STRING_LENGTH := AUTOPATH_LOGFILE_NAME'LAST;
  2155.               INPUT_STRING(1 .. STRING_LENGTH) := AUTOPATH_LOGFILE_NAME;
  2156.               LOGFILE_NAME := MAKE_PERSISTENT(AUTOPATH_LOGFILE_NAME);
  2157.  
  2158.             when SMART_TOOL =>
  2159.               STRING_LENGTH := SMART_LOGFILE_NAME'LAST;
  2160.               INPUT_STRING(1 .. STRING_LENGTH) := SMART_LOGFILE_NAME;
  2161.               LOGFILE_NAME := MAKE_PERSISTENT(SMART_LOGFILE_NAME);
  2162.  
  2163.             when PROFILE_TOOL =>
  2164.               STRING_LENGTH := PROFILE_LOGFILE_NAME'LAST;
  2165.               INPUT_STRING(1 .. STRING_LENGTH) := PROFILE_LOGFILE_NAME;
  2166.               LOGFILE_NAME := MAKE_PERSISTENT(PROFILE_LOGFILE_NAME);
  2167.  
  2168.             when others =>
  2169.               PUT_LINE("Logfile_Name Case Statement: User Input Error!!");
  2170.               raise USER_INPUT_ERROR;
  2171.  
  2172.           end case;
  2173.  
  2174.         end if;
  2175.  
  2176.         --  Need begin-end block for exception handling
  2177.         --  must check to see if a logfile with the specified name exists
  2178.  
  2179.         declare
  2180.           TEMPORARY_FILENAME : STRING(1 .. STRING_LENGTH) := INPUT_STRING(1 ..
  2181.             STRING_LENGTH);
  2182.  
  2183.         begin
  2184.           -- Open the file, if Name_Error is raised then the file
  2185.           -- does not exist,  If no exception raised must ask
  2186.           -- the user what he wishes to do...
  2187.           OPEN(TEST_FILE, OUT_FILE, TEMPORARY_FILENAME);
  2188.           CLOSE(TEST_FILE);
  2189.           FILE_OPTION := GET_USER_OPTION;
  2190.  
  2191.           case FILE_OPTION is
  2192.             when ENTER_NEW_NAME =>
  2193.               null;  -- do nothing so the loop will work
  2194.  
  2195.             when OVERWRITE_FILE =>
  2196.               -- Set Bad_User_Input to TRUE to make the loop exit
  2197.               BAD_USER_INPUT := FALSE;
  2198.  
  2199.             when APPEND_TO_FILE =>
  2200.               APPEND_LOGFILE_NAME := LOGFILE_NAME;
  2201.               LOGFILE_NAME := MAKE_PERSISTENT(TEMPORARY_LOGFILE_NAME);
  2202.               APPEND_LOGFILE := TRUE;
  2203.               BAD_USER_INPUT := FALSE;
  2204.  
  2205.             when others =>
  2206.               raise USER_INPUT_ERROR;
  2207.  
  2208.           end case;
  2209.  
  2210.         exception
  2211.           when NAME_ERROR =>
  2212.             -- File does not exist so it's ok to create it
  2213.             BAD_USER_INPUT := FALSE;
  2214.  
  2215.         end;
  2216.  
  2217.       end;
  2218.     end loop;
  2219.  
  2220.     -- Get the Test Identification string from the user.
  2221.     -- The default will be  TOOLNAME & " Report"
  2222.  
  2223.     PUT_LINE("Enter a unique Test Identification, Null for default.");
  2224.     GET_LINE(INPUT_STRING, STRING_LENGTH);
  2225.  
  2226.     if STRING_LENGTH > ZERO_LENGTH then
  2227.       TEST_DESCRIPTION := MAKE_PERSISTENT(INPUT_STRING(1 .. STRING_LENGTH));
  2228.  
  2229.     else
  2230.       TEST_DESCRIPTION := MAKE_PERSISTENT(DEFAULT_IDENTIFICATION(TOOL_NAME));
  2231.  
  2232.     end if;
  2233.  
  2234.     STRING_PKG.RELEASE;  -- Release the Heap space
  2235.  
  2236.   end QUERY_USER;
  2237.  
  2238.  
  2239.   --------------------------
  2240.   procedure OPEN_THE_LOGFILE --| Opens the log file for output
  2241.  
  2242.       is
  2243.  
  2244.   --| Algorithm
  2245.   --| The Query_User procedure is
  2246.   --| called to prompt the user for the Toolname, Logfile name and a
  2247.   --| unique Test Identification string and the logfile is opened.
  2248.  
  2249.     QUERY_ERROR     : BOOLEAN := FALSE; --| Flags bad user input
  2250.     TIMING_METHOD   : TIME_LIBRARY_1.TIMING_TYPE := RAW;
  2251.  
  2252.   begin
  2253.  
  2254.     QUERY_USER(TOOL_IN_USE, LOGFILE_NAME, TEST_IDENTIFICATION, QUERY_ERROR);
  2255.  
  2256.     if QUERY_ERROR then
  2257.       raise USER_INPUT_ERROR;
  2258.     end if;
  2259.  
  2260.     -- The arguments have been decoded, now open the logfile.
  2261.     CREATE_LOG(LOGFILE_NAME, TIMING_METHOD, STOP_WATCH);
  2262.  
  2263.     LOGFILE_OPEN := TRUE;
  2264.  
  2265.   end OPEN_THE_LOGFILE;
  2266.  
  2267.  
  2268.   -------------
  2269.   task body RTM is
  2270.  
  2271.   --| Effects
  2272.   --| The external interface to the Run Time Monitor has been
  2273.   --| implemented as a task in order to synchronize calls from
  2274.   --| the instrumented program and prevent interleaving of
  2275.   --| output to the log file
  2276.  
  2277.     use CALENDAR;
  2278.  
  2279.     UNIT_IDENTIFIER : PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2280.     MAIN_PROGRAM    : PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2281.  
  2282.     OK_TO_TERMINATE : BOOLEAN := FALSE; --| Goes TRUE when no more active units
  2283.     SECS            : DURATION;         --| The length of a delay in seconds
  2284.     ACTIVE_UNITS    : NATURAL := 0;     --| The number of active program units
  2285.     ENTRY_TIME      : CALENDAR.TIME;    --| Unit entry time adjusted for ovhd
  2286.     Exit_TIME       : CALENDAR.TIME;    --| Unit exit time adjusted for ovhd
  2287.  
  2288.     UNIT_EXIT_ERROR : exception;
  2289.  
  2290.   begin
  2291.  
  2292.     loop
  2293.  
  2294.       select
  2295.  
  2296.         -----------------------
  2297.         accept UNIT_INFORMATION( --| Defines a compilation unit to the RTM
  2298.  
  2299.           COMPILATION_UNIT   : in ADA_NAME;
  2300.           --| The name of the compilation unit
  2301.  
  2302.           BREAKPOINT_NUMBER  : in BREAKPOINT_NUMBER_RANGE;
  2303.           --| Total number of break points in the compilation unit
  2304.           --| assigned by the Source Instrumenter
  2305.  
  2306.           LIST_OF_PROCEDURES : in PROCEDURE_LIST
  2307.           --| A list of the names of all of the program units in
  2308.           --| the compilation unit
  2309.  
  2310.             ) do
  2311.  
  2312.           --| Algorithm
  2313.           --| If the logfile is not open then the Query_User procedure is
  2314.           --| called to prompt the user for the Toolname, Logfile name and a
  2315.           --| unique Test Identification string and the logfile is opened.
  2316.           --| Define_Compilation_Unit is invoked to define the program unit
  2317.           --| for the current execution.
  2318.  
  2319.           -- Stop the clock immediately
  2320.           STOP_WATCH := CLOCK;
  2321.  
  2322.           if not LOGFILE_OPEN then
  2323.  
  2324.             OPEN_THE_LOGFILE;
  2325.  
  2326.           end if;
  2327.  
  2328.           -- Write the information to the Logfile
  2329.  
  2330.           DEFINE_COMPILATION_UNIT(COMPILATION_UNIT, BREAKPOINT_NUMBER,
  2331.               LIST_OF_PROCEDURES);
  2332.  
  2333.           -- Calculate the amount of time required to execute the
  2334.           -- rendezvous and add it to the accumulated tool overhead
  2335.           ACCUMULATED_OVERHEAD := ACCUMULATED_OVERHEAD + (CLOCK - STOP_WATCH);
  2336.  
  2337.         end UNIT_INFORMATION;
  2338.  
  2339.       or
  2340.         --------------------
  2341.         accept ENTERING_UNIT( --| Logs program unit and start time to ELF
  2342.  
  2343.           ENCLOSING_UNIT : in STRING_TYPE;
  2344.           --| The name of the compilation unit
  2345.  
  2346.           UNIT_NUMBER    : in PROGRAM_UNIT_NUMBER_RANGE;
  2347.           --| The Program Unit Number
  2348.  
  2349.           UNIT_TYPE      : in PROGRAM_UNIT_TYPE;
  2350.           --| The type of unit ( procedure, function task generic or package )
  2351.  
  2352.           TASK_NUMBER    : in out TASK_TYPE_ACTIVATION_NUMBER_RANGE
  2353.           --| A unique number assigned by the Runtime Monitor
  2354.  
  2355.             ) do
  2356.  
  2357.           --| Algorithm
  2358.           --| First, the number of active units is incremented by 1.
  2359.           --| A Unit_Identifier record is formed by joining all input
  2360.           --| parameters. If Unit_Type = Package or Generic then
  2361.           --| Package_Initialization_In_Progress is set to TRUE.
  2362.           --| If Unit_Type = Task, then if the Task_List has not already
  2363.           --| been created it is created.  Unit_Identifier is added to the
  2364.           --| task list. If Task_List exists, it is checked to see if the
  2365.           --| Unit_Identifier is contained in the list and if it is in the
  2366.           --| list, Replace_Value is invoked to increment the
  2367.           --| Task_Type_Activation_Number.  If it is not in the list, it
  2368.           --| is added. Next, if the main procedure has not been entered
  2369.           --| and the unit being entered is the main procedure, then the
  2370.           --| Unit_Identifier is saved and Main_Procedure_Entered is set TRUE.
  2371.           --| Put_Configuration_Data is invoked to write the Test information
  2372.           --| to the logfile. Start_Unit is invoked to enter the Unit_Id
  2373.           --| into the logfile.
  2374.  
  2375.           -- Stop the clock immediately and calculate the adjusted
  2376.           -- entry time for this program unit
  2377.           STOP_WATCH := CLOCK;
  2378.           ENTRY_TIME := STOP_WATCH - ACCUMULATED_OVERHEAD;
  2379.  
  2380.           UNIT_IDENTIFIER := (ENCLOSING_UNIT, UNIT_NUMBER,
  2381.                               UNIT_TYPE, TASK_NUMBER);
  2382.  
  2383.           ACTIVE_UNITS := ACTIVE_UNITS + 1;
  2384.  
  2385.           if not LOGFILE_OPEN then
  2386.             OPEN_THE_LOGFILE;
  2387.           end if;
  2388.  
  2389.  
  2390.           case UNIT_TYPE is
  2391.  
  2392.             when TASK_TYPE =>
  2393.               --  Must set the Task_Type_Activation_Number.  First check to
  2394.               --  See if the Task_List has been created.  If not create it.
  2395.               if not FIRST_TASK_ENTERED then
  2396.  
  2397.                 TASK_LIST := CREATE;         -- Create the list
  2398.                 FIRST_TASK_ENTERED := TRUE;  -- Flag that it has been created
  2399.  
  2400.                 ADD(UNIT_IDENTIFIER, TASK_LIST);
  2401.  
  2402.               elsif IS_IN_LIST(TASK_LIST, UNIT_IDENTIFIER) then
  2403.                 -- If the Task is already in the list then increment the
  2404.                 -- Task_Activation number to indicate a new copy.
  2405.                 -- This number is passed back to the instrumented code
  2406.                 -- via the IN OUT parm Unit_Identifier.
  2407.  
  2408.                 REPLACE_VALUE(UNIT_IDENTIFIER, TASK_LIST);
  2409.                 -- Set Task_Number to send it back to the caller
  2410.                 TASK_NUMBER := UNIT_IDENTIFIER.TASK_TYPE_ACTIVATION_NUMBER;
  2411.  
  2412.               else
  2413.                 -- There is not another copy in the list so the
  2414.                 -- activation number = 1;
  2415.                 ADD(UNIT_IDENTIFIER, TASK_LIST);
  2416.  
  2417.               end if;
  2418.  
  2419.             when PROCEDURE_TYPE | FUNCTION_TYPE =>
  2420.  
  2421.               if not MAIN_PROCEDURE_ENTERED and
  2422.                  not PACKAGE_INITIALIZATION_IN_PROGRESS and
  2423.                  UNIT_IDENTIFIER.PROGRAM_UNIT_NUMBER = 1 then
  2424.  
  2425.                 -- This must be the main procedure
  2426.                 MAIN_PROCEDURE_ENTERED := TRUE;
  2427.                 MAIN_PROGRAM := UNIT_IDENTIFIER;
  2428.  
  2429.                 --  Write the Configuration data to the log
  2430.                 PUT_CONFIGURATION_DATA(
  2431.                   TOOL_IN_USE,
  2432.                   UNIT_IDENTIFIER.ENCLOSING_UNIT_IDENTIFIER,
  2433.                   TEST_IDENTIFICATION);
  2434.  
  2435.               end if;
  2436.  
  2437.             when others =>
  2438.               PACKAGE_INITIALIZATION_IN_PROGRESS := TRUE;
  2439.  
  2440.           end case;
  2441.  
  2442.           -- Record the starting unit in the log file. The starting
  2443.           -- time must be adjusted for accumulated tool overhead
  2444.           START_UNIT(UNIT_IDENTIFIER, ENTRY_TIME);
  2445.  
  2446.           -- Calculate the amount of time required to execute this
  2447.           -- rendezvous and add it to the accumulated tool overhead
  2448.           ACCUMULATED_OVERHEAD := ACCUMULATED_OVERHEAD + (CLOCK - STOP_WATCH);
  2449.  
  2450.         end ENTERING_UNIT;
  2451.  
  2452.       or
  2453.         ------------------
  2454.         accept EXITING_UNIT( --| Logs program unit and stop time to ELF
  2455.  
  2456.           UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER
  2457.           --| A unique ID assigned by the Source Instrumenter
  2458.  
  2459.             ) do
  2460.  
  2461.           --| Algorithm
  2462.           --| If Package_Initialization_In_Progress := FALSE and
  2463.           --| Main_Procedure_Entered = TRUE, then the Unit_ID is deleted
  2464.           --| from Entered_List.  If the list is empty, the logfile is closed.
  2465.           --| If Unit_Type = Package, Package_Initialization_In_Progress is
  2466.           --| set to FALSE.
  2467.  
  2468.           -- Stop the clock immediately and calculate the adjusted
  2469.           -- exit time for this program unit
  2470.           STOP_WATCH := CLOCK;
  2471.           EXIT_TIME  := STOP_WATCH - ACCUMULATED_OVERHEAD;
  2472.  
  2473.           ACTIVE_UNITS := ACTIVE_UNITS - 1;
  2474.  
  2475.           if UNIT_IDENTIFIER.UNIT_TYPE = PACKAGE_TYPE then
  2476.             PACKAGE_INITIALIZATION_IN_PROGRESS := FALSE;
  2477.           end if;
  2478.  
  2479.           if MAIN_PROCEDURE_ENTERED then
  2480.  
  2481.             -- Do not stop the main procedure until all other
  2482.             -- units have completed execution
  2483.             if not EQUAL(UNIT_IDENTIFIER, MAIN_PROGRAM) then
  2484.  
  2485.               -- The main procedure has been entered but this isn't it.
  2486.               -- It's OK to terminate it.
  2487.               -- Record the exiting unit in the log file. The exit
  2488.               -- time must be adjusted for accumulated tool overhead
  2489.               STOP_UNIT(UNIT_IDENTIFIER, EXIT_TIME);
  2490.             end if;
  2491.  
  2492.  
  2493.             -- When all units have been terminated, stop the main
  2494.             -- program unit, close the log file, and signal the
  2495.             -- RTM task that it is OK to terminate execution
  2496.  
  2497.             if ACTIVE_UNITS = 0 then
  2498.               -- Record the exiting unit in the log file. The exit
  2499.               -- time must be adjusted for accumulated tool overhead
  2500.               STOP_UNIT(MAIN_PROGRAM, EXIT_TIME);
  2501.               CLOSE_LOG(ACCUMULATED_OVERHEAD);
  2502.  
  2503.               -- If this log file was supposed to be appended to another
  2504.               -- log file then do so
  2505.               if APPEND_LOGFILE then
  2506.                 APPEND(VALUE(LOGFILE_NAME), VALUE(APPEND_LOGFILE_NAME));
  2507.               end if;
  2508.  
  2509.               OK_TO_TERMINATE := TRUE;
  2510.  
  2511.             end if;
  2512.  
  2513.           else
  2514.  
  2515.             -- The main procedure has not been entered yet
  2516.             -- Record the exiting unit in the log file. The exit
  2517.             -- time must be adjusted for accumulated tool overhead
  2518.             STOP_UNIT(UNIT_IDENTIFIER, EXIT_TIME);
  2519.  
  2520.           end if;
  2521.  
  2522.           -- Calculate the amount of time required to execute the
  2523.           -- rendezvous and add it to the accumulated tool overhead
  2524.           ACCUMULATED_OVERHEAD := ACCUMULATED_OVERHEAD + (CLOCK - STOP_WATCH);
  2525.  
  2526.         end EXITING_UNIT;
  2527.  
  2528.       or
  2529.         --------------------
  2530.         accept BREAKPOINT_AT( --| Process program breakpoint
  2531.  
  2532.           UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2533.           --| A unique ID assigned by the Source Instrumenter
  2534.  
  2535.           BREAKPOINT_TYPE    : in BREAKPOINT_TYPES;
  2536.           --| The type of breakpoint
  2537.  
  2538.           CURRENT_BREAKPOINT : in BREAKPOINT_NUMBER_RANGE
  2539.           --| Breakpoint number assigned by Source Instrumenter
  2540.  
  2541.             ) do
  2542.  
  2543.           --| Algorithm
  2544.           --| The Put_Breakpoint procedure is called for all tools except
  2545.           --| Profile_Tool.
  2546.  
  2547.           case TOOL_IN_USE is
  2548.             when PATH_TOOL .. SMART_TOOL =>
  2549.               PUT_BREAKPOINT(BREAKPOINT_TYPE, UNIT_IDENTIFIER,
  2550.                              CURRENT_BREAKPOINT);
  2551.  
  2552.             when others =>
  2553.               null;
  2554.  
  2555.           end case;
  2556.  
  2557.         end BREAKPOINT_AT;
  2558.  
  2559.       or
  2560.         --------------------------
  2561.         accept PUT_CALL_PARAMETERS(--| Log AutoPath input parameter list to ELF
  2562.  
  2563.           CALL_PARAMETERS : in INPUT_PARAMETER_LIST
  2564.           --| The user specified input parameter list
  2565.  
  2566.             ) do
  2567.  
  2568.           --| Effects
  2569.           --| Logs the calling parameter list for a single execution of the
  2570.           --| unit under test by the AutoPath shell.
  2571.  
  2572.           --| N/A:  Raises, Requires, Modifies, Errors
  2573.  
  2574.           if TOOL_IN_USE = AUTOPATH_TOOL then
  2575.             WRITE_LOG.PUT_CALL_PARAMETERS(CALL_PARAMETERS);
  2576.           end if;
  2577.         end PUT_CALL_PARAMETERS;
  2578.  
  2579.       or
  2580.         ----------------
  2581.         accept PUT_VALUE(--| Logs value of integer variable to the ELF
  2582.  
  2583.           UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2584.           --| A unique ID assigned by the Source Instrumenter for
  2585.           --| the current unit
  2586.  
  2587.           VARIABLE_NAME   : in STRING;  --| The name of the variable
  2588.  
  2589.           INTEGER_VALUE   : in INTEGER  --| The variable's value
  2590.  
  2591.             ) do
  2592.  
  2593.           --| Effects
  2594.           --| Logs integer values to the execution log file.
  2595.           --| Puts the program unit, variable name, and current value.
  2596.  
  2597.           --| N/A:  Raises, Requires, Modifies, Errors
  2598.  
  2599.           if TOOL_IN_USE = SMART_TOOL then
  2600.             WRITE_LOG.PUT_VALUE(UNIT_IDENTIFIER, VARIABLE_NAME, INTEGER_VALUE);
  2601.           end if;
  2602.  
  2603.         end PUT_VALUE;
  2604.  
  2605.       or
  2606.         ----------------
  2607.         accept PUT_VALUE(--| Logs value of Long_Integer variable to the ELF
  2608.  
  2609.           UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2610.           --| A unique ID assigned by the Source Instrumenter for
  2611.           --| the current unit
  2612.  
  2613.           VARIABLE_NAME      : in STRING;      --| The name of the variable
  2614.  
  2615.           LONG_INTEGER_VALUE : in LONG_INTEGER --| The variable's value
  2616.  
  2617.             ) do
  2618.  
  2619.           --| Effects
  2620.           --| Logs long_integer values to the execution log file.
  2621.           --| Puts the program unit, variable name, and current value.
  2622.  
  2623.           --| N/A:  Raises, Requires, Modifies, Errors
  2624.  
  2625.           if TOOL_IN_USE = SMART_TOOL then
  2626.             WRITE_LOG.PUT_VALUE(UNIT_IDENTIFIER, VARIABLE_NAME,
  2627.                                 LONG_INTEGER_VALUE);
  2628.           end if;
  2629.  
  2630.         end PUT_VALUE;
  2631.  
  2632.       or
  2633.         ----------------
  2634.         accept PUT_VALUE(--| Logs value of FLOAT variable to the ELF
  2635.  
  2636.           UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2637.           --| A unique ID assigned by the Source Instrumenter for
  2638.           --| the current unit
  2639.  
  2640.           VARIABLE_NAME   : in STRING; --| The name of the variable
  2641.  
  2642.           FLOAT_VALUE     : in FLOAT   --| The variable's value
  2643.  
  2644.             ) do
  2645.  
  2646.           --| Effects
  2647.           --| Logs floating point values to the execution log file
  2648.           --| Puts the program unit, variable name, and current value
  2649.  
  2650.           --| N/A:  Raises, Requires, Modifies, Errors
  2651.  
  2652.           if TOOL_IN_USE = SMART_TOOL then
  2653.             WRITE_LOG.PUT_VALUE(UNIT_IDENTIFIER, VARIABLE_NAME, FLOAT_VALUE);
  2654.           end if;
  2655.  
  2656.         end PUT_VALUE;
  2657.  
  2658.       or
  2659.         ----------------
  2660.         accept PUT_VALUE(--| Logs value of Long_Float variable to the ELF
  2661.  
  2662.           UNIT_IDENTIFIER  : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2663.           --| A unique ID assigned by the Source Instrumenter for
  2664.           --| the current unit
  2665.  
  2666.           VARIABLE_NAME    : in STRING;     --| The name of the variable
  2667.  
  2668.           LONG_FLOAT_VALUE : in LONG_FLOAT  --| The variable's value
  2669.  
  2670.             ) do
  2671.  
  2672.           --| Effects
  2673.           --| Logs long_float values to the execution log file.
  2674.           --| Puts the program unit, variable name, and current value.
  2675.  
  2676.           --| N/A:  Raises, Requires, Modifies, Errors
  2677.  
  2678.           if TOOL_IN_USE = SMART_TOOL then
  2679.             WRITE_LOG.PUT_VALUE(UNIT_IDENTIFIER, VARIABLE_NAME,
  2680.                                 LONG_FLOAT_VALUE);
  2681.           end if;
  2682.  
  2683.         end PUT_VALUE;
  2684.  
  2685.       or
  2686.         ----------------
  2687.         accept PUT_VALUE(--| Logs value of string variable to the ELF
  2688.  
  2689.           UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2690.           --| A unique ID assigned by the Source Instrumenter for
  2691.           --| the current unit
  2692.  
  2693.           VARIABLE_NAME   : in STRING; --| The name of the variable
  2694.  
  2695.           STRING_VALUE    : in STRING  --| The variable's value
  2696.  
  2697.           ) do
  2698.  
  2699.         --| Effects
  2700.         --| Logs string values to the execution log file
  2701.         --| Puts the program unit, variable name, and current value
  2702.         --| This procedure used to log the value of
  2703.         --|        strings
  2704.         --|        characters
  2705.         --|        enumerated data types (including booleans)
  2706.  
  2707.         --| N/A:  Raises, Requires, Modifies, Errors
  2708.  
  2709.           if TOOL_IN_USE = SMART_TOOL then
  2710.             WRITE_LOG.PUT_VALUE(UNIT_IDENTIFIER, VARIABLE_NAME, STRING_VALUE);
  2711.           end if;
  2712.  
  2713.         end PUT_VALUE;
  2714.  
  2715.       or
  2716.         ------------------
  2717.         accept START_DELAY(--| Records a delay for the specified unit and
  2718.                            --| duration in the ELF
  2719.  
  2720.           UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2721.           --| A unique ID assigned by the Source Instrumenter for
  2722.           --| the current unit
  2723.  
  2724.           SECONDS         : in DURATION
  2725.           --| The length of the delay in seconds
  2726.  
  2727.             ) do
  2728.  
  2729.           --| Effects
  2730.           --| Records a delay for the specified unit and duration in the
  2731.           --| Execution Log File. This entry is not called directly by the
  2732.           --| the instrumented program. It is called by the function
  2733.           --| Starting_Delay.
  2734.  
  2735.           --| N/A:  Raises, Requires, Modifies, Error
  2736.  
  2737.           -- Stop the clock immediately
  2738.           STOP_WATCH := CLOCK;
  2739.  
  2740.           SECS := WRITE_LOG.STARTING_DELAY(UNIT_IDENTIFIER, SECONDS);
  2741.  
  2742.           -- Calculate the amount of time required to execute the
  2743.           -- rendezvous and add it to the accumulated tool overhead
  2744.           ACCUMULATED_OVERHEAD := ACCUMULATED_OVERHEAD + (CLOCK - STOP_WATCH);
  2745.  
  2746.         end START_DELAY;
  2747.  
  2748.       or
  2749.  
  2750.         when OK_TO_TERMINATE =>
  2751.  
  2752.           terminate;
  2753.  
  2754.       end select;
  2755.  
  2756.     end loop;
  2757.  
  2758.   end RTM;
  2759.  
  2760.  
  2761.   -----------------------
  2762.   function STARTING_DELAY(--| Records a delay for the specified unit and
  2763.                           --| duration in the ELF
  2764.  
  2765.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  2766.     --| A unique ID assigned by the Source Instrumenter for the current unit
  2767.  
  2768.     SECONDS         : in DURATION
  2769.     --| The length of the delay in seconds
  2770.  
  2771.     ) return DURATION is
  2772.  
  2773.   --| Effects
  2774.   --| Records a delay for the specified unit and duration in the
  2775.   --| Execution Log File. The length of the Delay is returned to
  2776.   --| the calling unit. This unit is implemented as a function
  2777.   --| to enable trapping of delay times in timed entry statements.
  2778.  
  2779.   --| N/A:  Raises, Requires, Modifies, Errors
  2780.  
  2781.     begin
  2782.  
  2783.       if TOOL_IN_USE = PROFILE_TOOL then
  2784.         RTM.START_DELAY(UNIT_IDENTIFIER, SECONDS);
  2785.       end if;
  2786.  
  2787.       return SECONDS;
  2788.  
  2789.     end STARTING_DELAY;
  2790.  
  2791.  
  2792.   end RUN_TIME_MONITOR;
  2793.  
  2794.  
  2795. with TYPE_DEFINITIONS; use TYPE_DEFINITIONS; 
  2796. with STRING_PKG; use STRING_PKG; 
  2797. with TEXT_IO; use TEXT_IO; 
  2798.  
  2799. with UNCHECKED_DEALLOCATION; 
  2800.  
  2801. package body RTM_LIST_PACKAGE is 
  2802.  
  2803. --| Overview
  2804. --|      The RTM_List_Package is a subset of the Lists package from Inter-
  2805. --| metrics in Cambridge.  It is tailored explicitly for the Run_Time_Monitor.
  2806. --| The type of the list objects is Program_Unit_Unique_Identifier, which is 
  2807. --| declared in Type_Definitions.
  2808. --| The procedures and functions allow the RTM to create a list, add to a 
  2809. --| list, delete an item from the list, read and replace an item after 
  2810. --| incrementing the Task_Type_Activation_Number, and check for an empty 
  2811. --| list.
  2812.  
  2813.  
  2814. --  Mary Koppes  Intermetrics Inc, Huntington Beach,Ca  11-June-85
  2815.  
  2816.  
  2817. -------------------------------------------------------------------------------
  2818.  
  2819.  
  2820.   procedure FREE is 
  2821.     new UNCHECKED_DEALLOCATION(LIST_ELEMENT, LIST); 
  2822.  
  2823.  
  2824. -------------------------------------------------------------------------------
  2825.  
  2826.     -- Local Declarations for the RTM_ List_Package 
  2827.  
  2828.   ITEM_NOT_PRESENT : exception; 
  2829.   EMPTY_LIST       : exception; 
  2830.  
  2831. -------------------------------------------------------------------------------
  2832.  
  2833.  
  2834.   function EQUAL(X, Y : in PROGRAM_UNIT_UNIQUE_IDENTIFIER) return BOOLEAN is 
  2835.  
  2836.   begin
  2837.  
  2838.     if EQUAL(X.ENCLOSING_UNIT_IDENTIFIER, Y.ENCLOSING_UNIT_IDENTIFIER) and
  2839.       X.PROGRAM_UNIT_NUMBER = Y.PROGRAM_UNIT_NUMBER and
  2840.       X.UNIT_TYPE = Y.UNIT_TYPE then 
  2841.  
  2842.       return TRUE; 
  2843.  
  2844.     else 
  2845.  
  2846.       return FALSE; 
  2847.  
  2848.     end if; 
  2849.  
  2850.   end EQUAL; 
  2851.  
  2852.  
  2853. -------------------------------------------------------------------------------
  2854.  
  2855.  
  2856.   function CREATE --| Creates a null List
  2857.   return LIST
  2858.  
  2859.   is 
  2860.   begin
  2861.  
  2862.     return null; 
  2863.  
  2864.   end CREATE; 
  2865.  
  2866.  
  2867. -------------------------------------------------------------------------------
  2868.  
  2869.  
  2870.   procedure ADD(ELEMENT : in PROGRAM_UNIT_UNIQUE_IDENTIFIER; 
  2871.  
  2872.                 TO_LIST : in out LIST) is 
  2873.  
  2874.   --| Algorithm
  2875.   --| Allocates new storage for Element and links it to To_List.
  2876.  
  2877.   begin
  2878.     TO_LIST := new LIST_ELEMENT'(INFO => ELEMENT, NEXT_ELEMENT => TO_LIST); 
  2879.   end ADD; 
  2880.  
  2881.  
  2882. -------------------------------------------------------------------------------
  2883.  
  2884.  
  2885.  
  2886.   procedure DELETE_HEAD(THE_LIST : in out LIST)
  2887.  
  2888.   is 
  2889.  
  2890.   --| Algorithm
  2891.   --| Delete_Head first checks The_List and if it is null, Empty_List
  2892.   --| is raised.  If The_List is not null, the first element is freed.
  2893.  
  2894.  
  2895.     TEMPORARY_LIST : LIST; 
  2896.  
  2897.   begin
  2898.     if THE_LIST = null then 
  2899.  
  2900.       raise EMPTY_LIST; 
  2901.  
  2902.     else 
  2903.  
  2904.       TEMPORARY_LIST := THE_LIST.NEXT_ELEMENT; 
  2905.       FREE(THE_LIST); 
  2906.       THE_LIST := TEMPORARY_LIST; 
  2907.  
  2908.     end if; 
  2909.  
  2910.   end DELETE_HEAD; 
  2911.  
  2912.  
  2913. -------------------------------------------------------------------------------
  2914.  
  2915.   procedure DELETE(ELEMENT   : in PROGRAM_UNIT_UNIQUE_IDENTIFIER; 
  2916.                    FROM_LIST : in out LIST)
  2917.  
  2918.   is 
  2919.  
  2920.   --| Algorithm
  2921.   --| Delete is a recursive procedure which in effect walks through From_List
  2922.   --| looking for the first occurance of Element.  When it is found that
  2923.   --| element is deleted by a call to Delete_Head, which frees the element.
  2924.  
  2925.  
  2926.   begin
  2927.     if EQUAL(FROM_LIST.INFO, ELEMENT) then 
  2928.       DELETE_HEAD(FROM_LIST); 
  2929.  
  2930.     else 
  2931.       DELETE(ELEMENT, FROM_LIST.NEXT_ELEMENT); 
  2932.  
  2933.     end if; 
  2934.  
  2935.   exception
  2936.     when CONSTRAINT_ERROR => 
  2937.       raise ITEM_NOT_PRESENT; 
  2938.  
  2939.   end DELETE; 
  2940.  
  2941.  
  2942. -------------------------------------------------------------------------------
  2943.  
  2944.  
  2945.   procedure REPLACE_VALUE( --| Find element and increments the Task number
  2946.  
  2947.     NEW_ELEMENT : in out PROGRAM_UNIT_UNIQUE_IDENTIFIER; 
  2948.  
  2949.     NEW_LIST    : in out LIST)
  2950.  
  2951.   is 
  2952.  
  2953.   --| Algorithm 
  2954.   --| Replace value loops through the list until New_Element is found.  
  2955.   --| When it is found, the Task_Type_Activation_Number is incremented
  2956.   --| and the element is replaced.  New_Element is set to this new value 
  2957.   --| and returned via the IN OUT parameter.
  2958.  
  2959.     POINTER : LIST; 
  2960.  
  2961.   begin
  2962.     POINTER := NEW_LIST; 
  2963.     while POINTER /= null loop
  2964.       if EQUAL(POINTER.INFO, NEW_ELEMENT) then 
  2965.         POINTER.INFO.TASK_TYPE_ACTIVATION_NUMBER :=
  2966.            POINTER.INFO.TASK_TYPE_ACTIVATION_NUMBER + 1; 
  2967.         NEW_ELEMENT := POINTER.INFO; 
  2968.         exit; 
  2969.  
  2970.       else 
  2971.         POINTER := POINTER.NEXT_ELEMENT; 
  2972.       end if; 
  2973.  
  2974.     end loop; 
  2975.  
  2976.   end REPLACE_VALUE; 
  2977.  
  2978.  
  2979.  
  2980. -------------------------------------------------------------------------------
  2981.  
  2982.  
  2983.   function IS_IN_LIST( --| Checks for the presence of Element in The_List.
  2984.  
  2985.     THE_LIST : in LIST; 
  2986.  
  2987.     ELEMENT  : in PROGRAM_UNIT_UNIQUE_IDENTIFIER
  2988.  
  2989.     ) return BOOLEAN
  2990.   
  2991.       is 
  2992.  
  2993.   --| Algorithm
  2994.   --| Is_In_List loops through the list, searching fot Element.  It
  2995.   --| returns TRUE if it found and FALSE if it is not found.
  2996.  
  2997.     POINTER : LIST; 
  2998.  
  2999.   begin
  3000.     POINTER := THE_LIST; 
  3001.  
  3002.     while POINTER /= null loop
  3003.       if EQUAL(POINTER.INFO, ELEMENT) then 
  3004.         return TRUE; 
  3005.       end if; 
  3006.  
  3007.       POINTER := POINTER.NEXT_ELEMENT; 
  3008.  
  3009.     end loop; 
  3010.  
  3011.     return FALSE; 
  3012.  
  3013.   end IS_IN_LIST; 
  3014.  
  3015.  
  3016.  
  3017. -------------------------------------------------------------------------------
  3018.  
  3019.  
  3020.  
  3021.   function IS_EMPTY( --| Checks for an empty list
  3022.  
  3023.     THE_LIST : in LIST) return BOOLEAN
  3024.  
  3025.   is 
  3026.  
  3027.   --| Algorithm
  3028.   --| If The_List = NULL then return TRUE, else return FALSE.
  3029.  
  3030.  
  3031.   begin
  3032.     return (THE_LIST = null); 
  3033.  
  3034.   end IS_EMPTY; 
  3035.  
  3036.  
  3037. end RTM_LIST_PACKAGE; 
  3038.  
  3039. generic
  3040.   type ITEMTYPE is private;  --| This is the data being manipulated.
  3041.  
  3042.   with function EQUAL(X, Y : in ITEMTYPE) return BOOLEAN is "="; 
  3043.   --| This allows the user to define
  3044.   --| equality on ItemType.  For instance
  3045.   --| if ItemType is an abstract type
  3046.   --| then equality is defined in terms of
  3047.   --| the abstract type.  If this function
  3048.   --| is not provided equality defaults to
  3049.   --| =.
  3050. package LISTS is 
  3051.  
  3052. --| This package provides singly linked lists with elements of type
  3053. --| ItemType, where ItemType is specified by a generic parameter.
  3054.  
  3055. --| Overview
  3056. --| When this package is instantiated, it provides a linked list type for
  3057. --| lists of objects of type ItemType, which can be any desired type.  A
  3058. --| complete set of operations for manipulation, and releasing
  3059. --| those lists is also provided.  For instance, to make lists of strings,
  3060. --| all that is necessary is:
  3061. --|
  3062. --| type StringType is string(1..10);
  3063. --|
  3064. --| package Str_List is new Lists(StringType); use Str_List;
  3065. --| 
  3066. --|    L:List;
  3067. --|    S:StringType;
  3068. --|
  3069. --| Then to add a string S, to the list L, all that is necessary is
  3070. --|
  3071. --|    L := Create;
  3072. --|    Attach(S,L);
  3073. --| 
  3074. --| 
  3075. --| This package provides basic list operations.
  3076. --|
  3077. --| Attach          append an object to an object, an object to a list,
  3078. --|                 or a list to an object, or a list to a list.
  3079. --| Copy            copy a list using := on elements
  3080. --| CopyDeep        copy a list by copying the elements using a copy
  3081. --|                 operation provided by the user
  3082. --| Create          Creates an empty list
  3083. --| DeleteHead      removes the head of a list
  3084. --| DeleteItem      delete the first occurrence of an element from a list
  3085. --| DeleteItems     delete all occurrences of an element from a list
  3086. --| Destroy         remove a list
  3087. --| Equal           are two lists equal
  3088. --| FirstValue      get the information from the first element of a list
  3089. --| IsInList        determines whether a given element is in a given list
  3090. --| IsEmpty         returns true if the list is empty
  3091. --| LastValue       return the last value of a list
  3092. --| Length          Returns the length of a list 
  3093. --| MakeListIter    prepares for an iteration over a list
  3094. --| More            are there any more items in the list
  3095. --| Next            get the next item in a list
  3096. --| ReplaceHead     replace the information at the head of the list
  3097. --| ReplaceTail     replace the tail of a list with a new list
  3098. --| Tail            get the tail of a list
  3099. --|   
  3100.  
  3101. --| N/A: Effects, Requires, Modifies, and Raises.
  3102.  
  3103. --| Notes
  3104. --| Programmer Buddy Altus
  3105.  
  3106. --|                           Types
  3107. --|                           -----
  3108.  
  3109.   type LIST is private; 
  3110.   type LISTITER is private; 
  3111.  
  3112.  
  3113.   --|                           Exceptions
  3114.   --|                           ----------
  3115.  
  3116.   CIRCULARLIST   : exception;  --| Raised if an attemp is made to
  3117.   --| create a circular list.  This
  3118.   --| results when a list is attempted
  3119.   --| to be attached to itself.
  3120.  
  3121.   EMPTYLIST      : exception;  --| Raised if an attemp is made to
  3122.   --| manipulate an empty list.
  3123.  
  3124.   ITEMNOTPRESENT : exception;  --| Raised if an attempt is made to
  3125.   --| remove an element from a list in
  3126.   --| which it does not exist.
  3127.  
  3128.   NOMORE         : exception;  --| Raised if an attemp is made to
  3129.   --| get the next element from a list
  3130.   --| after iteration is complete.
  3131.  
  3132.  
  3133.  
  3134.   --|                           Operations
  3135.   --|                           ---------- 
  3136.  
  3137.   ----------------------------------------------------------------------------
  3138.  
  3139.   procedure ATTACH( --| appends List2 to List1
  3140.                    LIST1 : in out LIST;  --| The list being appended to.
  3141.                    LIST2 : in LIST --| The list being appended.
  3142.                    ); 
  3143.  
  3144.   --| Raises
  3145.   --| CircularList
  3146.  
  3147.   --| Effects
  3148.   --| Appends List1 to List2.  This makes the next field of the last element
  3149.   --| of List1 refer to List2.  This can possibly change the value of List1
  3150.   --| if List1 is an empty list.  This causes sharing of lists.  Thus if
  3151.   --| user Destroys List1 then List2 will be a dangling reference.
  3152.   --| This procedure raises CircularList if List1 equals List2.  If it is 
  3153.   --| necessary to Attach a list to itself first make a copy of the list and 
  3154.   --| attach the copy.
  3155.  
  3156.   --| Modifies
  3157.   --| Changes the next field of the last element in List1 to be List2.
  3158.  
  3159. -------------------------------------------------------------------------------
  3160.  
  3161.   function ATTACH( --| Creates a new list containing the two
  3162.   --| Elements.
  3163.                   ELEMENT1 : in ITEMTYPE; 
  3164.                                  --| This will be first element in list.
  3165.                   ELEMENT2 : in ITEMTYPE
  3166.                                  --| This will be second element in list.
  3167.                   ) return LIST; 
  3168.  
  3169.   --| Effects
  3170.   --| This creates a list containing the two elements in the order
  3171.   --| specified.
  3172.  
  3173. -------------------------------------------------------------------------------
  3174.   procedure ATTACH( --| List L is appended with Element.
  3175.                    L       : in out LIST;  --| List being appended to.
  3176.                    ELEMENT : in ITEMTYPE
  3177.                                     --| This will be last element in l    ist.
  3178.                    ); 
  3179.  
  3180.   --| Effects
  3181.   --| Appends Element onto the end of the list L.  If L is empty then this
  3182.   --| may change the value of L.
  3183.   --|
  3184.   --| Modifies
  3185.   --| This appends List L with Element by changing the next field in List.
  3186.  
  3187. --------------------------------------------------------------------------------
  3188.   procedure ATTACH( --| Makes Element first item in list L.
  3189.                    ELEMENT : in ITEMTYPE; 
  3190.                                     --| This will be the first element in list.
  3191.                    L       : in out LIST --| The List which Element is being
  3192.                    --| prepended to.
  3193.                    ); 
  3194.  
  3195.   --| Effects
  3196.   --| This prepends list L with Element.
  3197.   --|
  3198.   --| Modifies
  3199.   --| This modifies the list L.
  3200.  
  3201.   --------------------------------------------------------------------------
  3202.  
  3203.   function ATTACH( --| attaches two lists
  3204.                   LIST1 : in LIST;  --| first list
  3205.                   LIST2 : in LIST --| second list
  3206.                   ) return LIST; 
  3207.  
  3208.   --| Raises
  3209.   --| CircularList
  3210.  
  3211.   --| Effects
  3212.   --| This returns a list which is List1 attached to List2.  If it is desired
  3213.   --| to make List1 be the new attached list the following ada code should be
  3214.   --| used.
  3215.   --|  
  3216.   --| List1 := Attach (List1, List2);
  3217.   --| This procedure raises CircularList if List1 equals List2.  If it is 
  3218.   --| necessary to Attach a list to itself first make a copy of the list and 
  3219.   --| attach the copy.
  3220.  
  3221.   -------------------------------------------------------------------------
  3222.  
  3223.   function ATTACH( --| prepends an element onto a list
  3224.                   ELEMENT : in ITEMTYPE;  --| element being prepended to list
  3225.                   L       : in LIST --| List which element is being added
  3226.                   --| to
  3227.                   ) return LIST; 
  3228.  
  3229.   --| Effects
  3230.   --| Returns a new list which is headed by Element and followed by L.
  3231.  
  3232.   ------------------------------------------------------------------------
  3233.  
  3234.   function ATTACH( --| Adds an element to the end of a list
  3235.                   L       : in LIST; 
  3236.                                    --| The list which element is being added to.
  3237.                   ELEMENT : in ITEMTYPE
  3238.                                    --| The element being added to the end of
  3239.                   --| the list.
  3240.                   ) return LIST; 
  3241.  
  3242.   --| Effects
  3243.   --| Returns a new list which is L followed by Element.
  3244.  
  3245.   --------------------------------------------------------------------------  
  3246.  
  3247.  
  3248.   function COPY( --| returns a copy of list1 
  3249.                 L : in LIST --| list being copied
  3250.                 ) return LIST; 
  3251.  
  3252.   --| Effects
  3253.   --| Returns a copy of L.
  3254.  
  3255.   --------------------------------------------------------------------------
  3256.  
  3257.   generic
  3258.     with function COPY(I : in ITEMTYPE) return ITEMTYPE; 
  3259.  
  3260.  
  3261.   function COPYDEEP( --| returns a copy of list using a user supplied
  3262.   --| copy function.  This is helpful if the type
  3263.   --| of a list is an abstract data type.
  3264.                     L : in LIST --| List being copied.
  3265.                     ) return LIST; 
  3266.  
  3267.   --| Effects
  3268.   --| This produces a new list whose elements have been duplicated using
  3269.   --| the Copy function provided by the user.
  3270.  
  3271. ------------------------------------------------------------------------------
  3272.  
  3273.   function CREATE --| Returns an empty List
  3274.  
  3275.   return LIST; 
  3276.  
  3277. ------------------------------------------------------------------------------
  3278.  
  3279.   procedure DELETEHEAD( --| Remove the head element from a list.
  3280.                        L : in out LIST --| The list whose head is being removed.
  3281.                        ); 
  3282.  
  3283.   --| Raises
  3284.   --| EmptyList
  3285.   --|
  3286.   --| Effects
  3287.   --| This will return the space occupied by the first element in the list
  3288.   --| to the heap.  If sharing exists between lists this procedure
  3289.   --| could leave a dangling reference.  If L is empty EmptyList will be
  3290.   --| raised.
  3291.  
  3292. ------------------------------------------------------------------------------
  3293.  
  3294.   procedure DELETEITEM( --| remove the first occurrence of Element
  3295.   --| from L
  3296.                        L       : in out LIST; 
  3297.                                 --| list element is being  removed from
  3298.                        ELEMENT : in ITEMTYPE --| element being removed
  3299.                        ); 
  3300.  
  3301.   --| Raises
  3302.   --| ItemNotPresent
  3303.  
  3304.   --| Effects
  3305.   --| Removes the first element of the list equal to Element.  If there is
  3306.   --| not an element equal to Element than ItemNotPresent is raised.
  3307.  
  3308.   --| Modifies
  3309.   --| This operation is destructive, it returns the storage occupied by
  3310.   --| the elements being deleted.
  3311.  
  3312. ------------------------------------------------------------------------------
  3313.  
  3314.   procedure DELETEITEMS( --| remove all occurrences of Element
  3315.   --| from  L.
  3316.                         L       : in out LIST; 
  3317.                                 --| The List element is being removed from
  3318.                         ELEMENT : in ITEMTYPE --| element being removed
  3319.                         ); 
  3320.  
  3321.   --| Raises
  3322.   --| ItemNotPresent
  3323.   --|
  3324.   --| Effects
  3325.   --| This procedure walks down the list L and removes all elements of the
  3326.   --| list equal to Element.  If there are not any elements equal to Element
  3327.   --| then raise ItemNotPresent.
  3328.  
  3329.   --| Modifies
  3330.   --| This operation is destructive the storage occupied by the items
  3331.   --| removed is returned.
  3332.  
  3333. ------------------------------------------------------------------------------
  3334.  
  3335.   procedure DESTROY( --| removes the list
  3336.                     L : in out LIST --| the list being removed
  3337.                     ); 
  3338.  
  3339.   --| Effects
  3340.   --| This returns to the heap all the storage that a list occupies.  Keep in
  3341.   --| mind if there exists sharing between lists then this operation can leave
  3342.   --| dangling references.
  3343.  
  3344. ------------------------------------------------------------------------------
  3345.  
  3346.   function FIRSTVALUE( --| returns the contents of the first record of the 
  3347.   --| list
  3348.                       L : in LIST --| the list whose first element is being
  3349.                       --| returned
  3350.  
  3351.                       ) return ITEMTYPE; 
  3352.  
  3353.   --| Raises
  3354.   --| EmptyList
  3355.   --|
  3356.   --| Effects
  3357.   --| This returns the Item in the first position in the list.  If the list
  3358.   --| is empty EmptyList is raised.
  3359.  
  3360. -------------------------------------------------------------------------------
  3361.  
  3362.   function ISEMPTY( --| Checks if a list is empty.
  3363.                    L : in LIST --| List being checked.
  3364.                    ) return BOOLEAN; 
  3365.  
  3366.   --------------------------------------------------------------------------
  3367.  
  3368.   function ISINLIST( --| Checks if element is an element of
  3369.   --| list.
  3370.                     L       : in LIST;  --| list being scanned for element
  3371.                     ELEMENT : in ITEMTYPE --| element being searched for
  3372.                     ) return BOOLEAN; 
  3373.  
  3374.   --| Effects
  3375.   --| Walks down the list L looking for an element whose value is Element.
  3376.  
  3377. ------------------------------------------------------------------------------
  3378.  
  3379.   function LASTVALUE( --| Returns the contents of the last record of
  3380.   --| the list.
  3381.                      L : in LIST --| The list whose first element is being
  3382.                      --| returned.
  3383.                      ) return ITEMTYPE; 
  3384.  
  3385.   --| Raises
  3386.   --| EmptyList
  3387.   --|
  3388.   --| Effects
  3389.   --| Returns the last element in a list.  If the list is empty EmptyList is
  3390.   --| raised.
  3391.  
  3392.  
  3393. ------------------------------------------------------------------------------
  3394.  
  3395.   function LENGTH( --| count the number of elements on a list
  3396.                   L : in LIST --| list whose length is being computed
  3397.                   ) return INTEGER; 
  3398.  
  3399. ------------------------------------------------------------------------------
  3400.  
  3401.   function MAKELISTITER( --| Sets a variable to point to  the head
  3402.   --| of the list.  This will be used to
  3403.   --| prepare for iteration over a list.
  3404.                         L : in LIST --| The list being iterated over.
  3405.                         ) return LISTITER; 
  3406.  
  3407.  
  3408. --| This prepares a user for iteration operation over a list.  The iterater is
  3409.   --| an operation which returns successive elements of the list on successive
  3410.   --| calls to the iterator.  There needs to be a mechanism which marks the
  3411.   --| position in the list, so on successive calls to the Next operation the
  3412.   --| next item in the list can be returned.  This is the function of the
  3413.   --| MakeListIter and the type ListIter.  MakeIter just sets the Iter to the
  3414.   --| the beginning  of the list. On subsequent calls to Next the Iter
  3415.   --| is updated with each call.
  3416.  
  3417.   -----------------------------------------------------------------------------
  3418.  
  3419.   function MORE( --| Returns true if there are more elements in
  3420.   --| the and false if there aren't any more
  3421.   --| the in the list.
  3422.                 L : in LISTITER --| List being checked for elements.
  3423.                 ) return BOOLEAN; 
  3424.  
  3425. ------------------------------------------------------------------------------
  3426.  
  3427.   procedure NEXT( --| This is the iterator operation.  Given
  3428.   --| a ListIter in the list it returns the
  3429.   --| current item and updates the ListIter.
  3430.   --| If ListIter is at the end of the list,
  3431.   --| More returns false otherwise it
  3432.   --| returns true.
  3433.                  PLACE : in out LISTITER; 
  3434.                                 --| The Iter which marks the position in
  3435.                  --| the list.
  3436.                  INFO  : out ITEMTYPE --| The element being returned.
  3437.  
  3438.                  ); 
  3439.  
  3440.   --| The iterators subprograms MakeListIter, More, and Next should be used
  3441.   --| in the following way:
  3442.   --|
  3443.   --|         L:        List;
  3444.   --|         Place:    ListIter;
  3445.   --|         Info:     SomeType;
  3446.   --|
  3447.   --|     
  3448.   --|         Place := MakeListIter(L);
  3449.   --|
  3450.   --|         while ( More(Place) ) loop
  3451.   --|               Next(Place, Info);
  3452.   --|               process each element of list L;
  3453.   --|               end loop;
  3454.  
  3455.  
  3456.   ----------------------------------------------------------------------------
  3457.  
  3458.   procedure REPLACEHEAD( --| Replace the Item at the head of the list
  3459.   --| with the parameter Item.
  3460.                         L    : in out LIST;  --| The list being modified.
  3461.                         INFO : in ITEMTYPE --| The information being entered.
  3462.                         ); 
  3463.   --| Raises 
  3464.   --| EmptyList
  3465.  
  3466.   --| Effects
  3467.   --| Replaces the information in the first element in the list.  Raises
  3468.   --| EmptyList if the list is empty.
  3469.  
  3470. ------------------------------------------------------------------------------
  3471.  
  3472.   procedure REPLACETAIL( --| Replace the Tail of a list
  3473.   --| with a new list.
  3474.                         L       : in out LIST;  --| List whose Tail is replaced.
  3475.                         NEWTAIL : in LIST --| The list which will become the
  3476.                         --| tail of Oldlist.
  3477.                         ); 
  3478.   --| Raises
  3479.   --| EmptyList
  3480.   --|
  3481.   --| Effects
  3482.   --| Replaces the tail of a list with a new list.  If the list whose tail
  3483.   --| is being replaced is null EmptyList is raised.
  3484.  
  3485. -------------------------------------------------------------------------------
  3486.  
  3487.   function TAIL( --| returns the tail of a list L
  3488.                 L : in LIST --| the list whose tail is being returned
  3489.                 ) return LIST; 
  3490.  
  3491.   --| Raises
  3492.   --| EmptyList
  3493.   --|
  3494.   --| Effects
  3495.   --| Returns a list which is the tail of the list L.  Raises EmptyList if
  3496.   --| L is empty.  If L only has one element then Tail returns the Empty
  3497.   --| list.
  3498.  
  3499. ------------------------------------------------------------------------------
  3500.  
  3501.   function EQUAL( --| compares list1 and list2 for equality
  3502.                  LIST1 : in LIST;  --| first list
  3503.                  LIST2 : in LIST --| second list
  3504.                  ) return BOOLEAN; 
  3505.  
  3506.   --| Effects
  3507.   --| Returns true if for all elements of List1 the corresponding element
  3508.   --| of List2 has the same value.  This function uses the Equal operation
  3509.   --| provided by the user.  If one is not provided then = is used.
  3510.  
  3511. ------------------------------------------------------------------------------
  3512. private
  3513.   type CELL; 
  3514.  
  3515.   type LIST is access CELL;  --| pointer added by this package
  3516.   --| in order to make a list
  3517.  
  3518.  
  3519.   type CELL is  --| Cell for the lists being created
  3520.     record
  3521.       INFO : ITEMTYPE; 
  3522.       NEXT : LIST; 
  3523.     end record; 
  3524.  
  3525.  
  3526.   type LISTITER is new LIST;  --| This prevents Lists being assigned to
  3527.   --| iterators and vice versa
  3528.  
  3529. end LISTS; 
  3530.  
  3531. with UNCHECKED_DEALLOCATION; 
  3532.  
  3533. package body LISTS is 
  3534.  
  3535.   procedure FREE is 
  3536.     new UNCHECKED_DEALLOCATION(CELL, LIST); 
  3537.  
  3538.     --------------------------------------------------------------------------
  3539.  
  3540.   function LAST(L : in LIST) return LIST is 
  3541.  
  3542.     PLACE_IN_L      : LIST; 
  3543.     TEMP_PLACE_IN_L : LIST; 
  3544.  
  3545.     --|  Link down the list L and return the pointer to the last element
  3546.     --| of L.  If L is null raise the EmptyList exception.
  3547.  
  3548.   begin
  3549.     if L = null then 
  3550.       raise EMPTYLIST; 
  3551.     else 
  3552.  
  3553.       --|  Link down L saving the pointer to the previous element in 
  3554.       --|  Temp_Place_In_L.  After the last iteration Temp_Place_In_L
  3555.       --|  points to the last element in the list.
  3556.       PLACE_IN_L := L; 
  3557.       while PLACE_IN_L /= null loop
  3558.         TEMP_PLACE_IN_L := PLACE_IN_L; 
  3559.         PLACE_IN_L := PLACE_IN_L.NEXT; 
  3560.       end loop; 
  3561.       return TEMP_PLACE_IN_L; 
  3562.     end if; 
  3563.   end LAST; 
  3564.  
  3565.  
  3566.   --------------------------------------------------------------------------
  3567.  
  3568.   procedure ATTACH(LIST1 : in out LIST; 
  3569.                    LIST2 : in LIST) is 
  3570.     ENDOFLIST1 : LIST; 
  3571.  
  3572.     --| Attach List2 to List1. 
  3573.     --| If List1 is null return List2
  3574.     --| If List1 equals List2 then raise CircularList
  3575.     --| Otherwise get the pointer to the last element of List1 and change
  3576.     --| its Next field to be List2.
  3577.  
  3578.   begin
  3579.     if LIST1 = null then 
  3580.       LIST1 := LIST2; 
  3581.       return; 
  3582.     elsif LIST1 = LIST2 then 
  3583.       raise CIRCULARLIST; 
  3584.     else 
  3585.       ENDOFLIST1 := LAST(LIST1); 
  3586.       ENDOFLIST1.NEXT := LIST2; 
  3587.     end if; 
  3588.   end ATTACH; 
  3589.  
  3590.   --------------------------------------------------------------------------
  3591.  
  3592.   procedure ATTACH(L       : in out LIST; 
  3593.                    ELEMENT : in ITEMTYPE) is 
  3594.  
  3595.     NEWEND : LIST; 
  3596.  
  3597.     --| Create a list containing Element and attach it to the end of L
  3598.  
  3599.   begin
  3600.     NEWEND := new CELL'(INFO => ELEMENT, NEXT => null); 
  3601.     ATTACH(L, NEWEND); 
  3602.   end ATTACH; 
  3603.  
  3604.   --------------------------------------------------------------------------
  3605.  
  3606.   function ATTACH(ELEMENT1 : in ITEMTYPE; 
  3607.                   ELEMENT2 : in ITEMTYPE) return LIST is 
  3608.     NEWLIST : LIST; 
  3609.  
  3610.     --| Create a new list containing the information in Element1 and
  3611.     --| attach Element2 to that list.
  3612.  
  3613.   begin
  3614.     NEWLIST := new CELL'(INFO => ELEMENT1, NEXT => null); 
  3615.     ATTACH(NEWLIST, ELEMENT2); 
  3616.     return NEWLIST; 
  3617.   end ATTACH; 
  3618.  
  3619.   --------------------------------------------------------------------------
  3620.  
  3621.   procedure ATTACH(ELEMENT : in ITEMTYPE; 
  3622.                    L       : in out LIST) is 
  3623.  
  3624.   --|  Create a new cell whose information is Element and whose Next
  3625.   --|  field is the list L.  This prepends Element to the List L.
  3626.  
  3627.   begin
  3628.     L := new CELL'(INFO => ELEMENT, NEXT => L); 
  3629.   end ATTACH; 
  3630.  
  3631.   --------------------------------------------------------------------------
  3632.  
  3633.   function ATTACH(LIST1 : in LIST; 
  3634.                   LIST2 : in LIST) return LIST is 
  3635.  
  3636.     LAST_OF_LIST1 : LIST; 
  3637.  
  3638.   begin
  3639.     if LIST1 = null then 
  3640.       return LIST2; 
  3641.     elsif LIST1 = LIST2 then 
  3642.       raise CIRCULARLIST; 
  3643.     else 
  3644.       LAST_OF_LIST1 := LAST(LIST1); 
  3645.       LAST_OF_LIST1.NEXT := LIST2; 
  3646.       return LIST1; 
  3647.     end if; 
  3648.   end ATTACH; 
  3649.  
  3650.   -------------------------------------------------------------------------
  3651.  
  3652.   function ATTACH(L       : in LIST; 
  3653.                   ELEMENT : in ITEMTYPE) return LIST is 
  3654.  
  3655.     NEWEND    : LIST; 
  3656.     LAST_OF_L : LIST; 
  3657.  
  3658.     --| Create a list called NewEnd and attach it to the end of L.
  3659.     --| If L is null return NewEnd 
  3660.     --| Otherwise get the last element in L and make its Next field
  3661.     --| NewEnd.
  3662.  
  3663.   begin
  3664.     NEWEND := new CELL'(INFO => ELEMENT, NEXT => null); 
  3665.     if L = null then 
  3666.       return NEWEND; 
  3667.     else 
  3668.       LAST_OF_L := LAST(L); 
  3669.       LAST_OF_L.NEXT := NEWEND; 
  3670.       return L; 
  3671.     end if; 
  3672.   end ATTACH; 
  3673.  
  3674.   --------------------------------------------------------------------------
  3675.  
  3676.   function ATTACH(ELEMENT : in ITEMTYPE; 
  3677.                   L       : in LIST) return LIST is 
  3678.  
  3679.   begin
  3680.     return (new CELL'(INFO => ELEMENT, NEXT => L)); 
  3681.   end ATTACH; 
  3682.  
  3683.   --------------------------------------------------------------------------
  3684.  
  3685.   function COPY(L : in LIST) return LIST is 
  3686.  
  3687.   --| If L is null return null
  3688.   --| Otherwise recursively copy the list by first copying the information
  3689.   --| at the head of the list and then making the Next field point to 
  3690.   --| a copy of the tail of the list.
  3691.  
  3692.   begin
  3693.     if L = null then 
  3694.       return null; 
  3695.     else 
  3696.       return new CELL'(INFO => L.INFO, NEXT => COPY(L.NEXT)); 
  3697.     end if; 
  3698.   end COPY; 
  3699.  
  3700.  
  3701.   --------------------------------------------------------------------------
  3702.  
  3703.   function COPYDEEP(L : in LIST) return LIST is 
  3704.  
  3705.   --|  If L is null then return null.
  3706.   --|  Otherwise copy the first element of the list into the head of the
  3707.   --|  new list and copy the tail of the list recursively using CopyDeep.
  3708.  
  3709.   begin
  3710.     if L = null then 
  3711.       return null; 
  3712.     else 
  3713.       return new CELL'(INFO => COPY(L.INFO), NEXT => COPYDEEP(L.NEXT)); 
  3714.     end if; 
  3715.   end COPYDEEP; 
  3716.  
  3717.   --------------------------------------------------------------------------
  3718.  
  3719.   function CREATE return LIST is 
  3720.  
  3721.   --| Return the empty list.
  3722.  
  3723.   begin
  3724.     return null; 
  3725.   end CREATE; 
  3726.  
  3727.   --------------------------------------------------------------------------
  3728.   procedure DELETEHEAD(L : in out LIST) is 
  3729.  
  3730.     TEMPLIST : LIST; 
  3731.  
  3732.     --| Remove the element of the head of the list and return it to the heap.
  3733.     --| If L is null EmptyList.
  3734.     --| Otherwise save the Next field of the first element, remove the first
  3735.     --| element and then assign to L the Next field of the first element.
  3736.  
  3737.   begin
  3738.     if L = null then 
  3739.       raise EMPTYLIST; 
  3740.     else 
  3741.       TEMPLIST := L.NEXT; 
  3742.       FREE(L); 
  3743.       L := TEMPLIST; 
  3744.     end if; 
  3745.   end DELETEHEAD; 
  3746.  
  3747.   --------------------------------------------------------------------------
  3748.  
  3749.   procedure DELETEITEM(L       : in out LIST; 
  3750.                        ELEMENT : in ITEMTYPE) is 
  3751.  
  3752.     TEMP_L : LIST; 
  3753.  
  3754.     --| Remove the first element in the list with the value Element.
  3755.     --| If the first element of the list is equal to element then
  3756.     --| remove it.  Otherwise, recurse on the tail of the list.
  3757.  
  3758.   begin
  3759.     if EQUAL(L.INFO, ELEMENT) then 
  3760.       DELETEHEAD(L); 
  3761.     else 
  3762.       DELETEITEM(L.NEXT, ELEMENT); 
  3763.     end if; 
  3764.   exception
  3765.     when CONSTRAINT_ERROR => 
  3766.       raise ITEMNOTPRESENT; 
  3767.   end DELETEITEM; 
  3768.  
  3769.   --------------------------------------------------------------------------
  3770.  
  3771.   procedure DELETEITEMS(L       : in out LIST; 
  3772.                         ELEMENT : in ITEMTYPE) is 
  3773.  
  3774.     PLACE_IN_L      : LIST;  --| Current place in L.
  3775.     LAST_PLACE_IN_L : LIST;  --| Last place in L.
  3776.     TEMP_PLACE_IN_L : LIST;  --| Holds a place in L to be removed.
  3777.     FOUND           : BOOLEAN := FALSE;  --| Indicates if an element with
  3778.     --| the correct value was found. 
  3779.  
  3780.     --| Walk over the list removing all elements with the value Element.
  3781.  
  3782.   begin
  3783.     PLACE_IN_L := L; 
  3784.     LAST_PLACE_IN_L := null; 
  3785.     while (PLACE_IN_L /= null) loop
  3786.  
  3787.       --| Found an element equal to Element
  3788.       if EQUAL(PLACE_IN_L.INFO, ELEMENT) then 
  3789.         FOUND := TRUE; 
  3790.  
  3791.         --| If Last_Place_In_L is null then we are at first element
  3792.         --| in L.
  3793.         if LAST_PLACE_IN_L = null then 
  3794.           TEMP_PLACE_IN_L := PLACE_IN_L; 
  3795.           L := PLACE_IN_L.NEXT; 
  3796.         else 
  3797.           TEMP_PLACE_IN_L := PLACE_IN_L; 
  3798.  
  3799.           --| Relink the list Last's Next gets Place's Next
  3800.           LAST_PLACE_IN_L.NEXT := PLACE_IN_L.NEXT; 
  3801.         end if; 
  3802.  
  3803.         --| Move Place_In_L to the next position in the list.
  3804.         --| Free the element.
  3805.         --| Do not update the last element in the list it remains the
  3806.         --| same. 
  3807.         PLACE_IN_L := PLACE_IN_L.NEXT; 
  3808.         FREE(TEMP_PLACE_IN_L); 
  3809.       else 
  3810.  
  3811.         --| Update the last place in L and the place in L.
  3812.         LAST_PLACE_IN_L := PLACE_IN_L; 
  3813.         PLACE_IN_L := PLACE_IN_L.NEXT; 
  3814.       end if; 
  3815.     end loop; 
  3816.  
  3817.     --| If we have not found an element raise an exception.
  3818.     if not FOUND then 
  3819.       raise ITEMNOTPRESENT; 
  3820.     end if; 
  3821.  
  3822.   end DELETEITEMS; 
  3823.  
  3824.   --------------------------------------------------------------------------
  3825.  
  3826.   procedure DESTROY(L : in out LIST) is 
  3827.  
  3828.     PLACE_IN_L : LIST; 
  3829.     HOLDPLACE  : LIST; 
  3830.  
  3831.     --| Walk down the list removing all the elements and set the list to
  3832.     --| the empty list. 
  3833.  
  3834.   begin
  3835.     PLACE_IN_L := L; 
  3836.     while PLACE_IN_L /= null loop
  3837.       HOLDPLACE := PLACE_IN_L; 
  3838.       PLACE_IN_L := PLACE_IN_L.NEXT; 
  3839.       FREE(HOLDPLACE); 
  3840.     end loop; 
  3841.     L := null; 
  3842.   end DESTROY; 
  3843.  
  3844.   --------------------------------------------------------------------------
  3845.  
  3846.   function FIRSTVALUE(L : in LIST) return ITEMTYPE is 
  3847.  
  3848.   --| Return the first value in the list.
  3849.  
  3850.   begin
  3851.     if L = null then 
  3852.       raise EMPTYLIST; 
  3853.     else 
  3854.       return (L.INFO); 
  3855.     end if; 
  3856.   end FIRSTVALUE; 
  3857.  
  3858.   --------------------------------------------------------------------------
  3859.  
  3860.   procedure FORWORD(I : in out LISTITER) is 
  3861.  
  3862.   --| Return the pointer to the next member of the list.
  3863.  
  3864.   begin
  3865.     I := LISTITER(I.NEXT); 
  3866.   end FORWORD; 
  3867.  
  3868.   --------------------------------------------------------------------------
  3869.  
  3870.   function ISINLIST(L       : in LIST; 
  3871.                     ELEMENT : in ITEMTYPE) return BOOLEAN is 
  3872.  
  3873.     PLACE_IN_L : LIST; 
  3874.  
  3875.     --| Check if Element is in L.  If it is return true otherwise return false.
  3876.  
  3877.   begin
  3878.     PLACE_IN_L := L; 
  3879.     while PLACE_IN_L /= null loop
  3880.       if EQUAL(PLACE_IN_L.INFO, ELEMENT) then 
  3881.         return TRUE; 
  3882.       end if; 
  3883.       PLACE_IN_L := PLACE_IN_L.NEXT; 
  3884.     end loop; 
  3885.     return FALSE; 
  3886.   end ISINLIST; 
  3887.  
  3888.   --------------------------------------------------------------------------
  3889.  
  3890.   function ISEMPTY(L : in LIST) return BOOLEAN is 
  3891.  
  3892.   --| Is the list L empty.
  3893.  
  3894.   begin
  3895.     return (L = null); 
  3896.   end ISEMPTY; 
  3897.  
  3898.   --------------------------------------------------------------------------
  3899.  
  3900.   function LASTVALUE(L : in LIST) return ITEMTYPE is 
  3901.  
  3902.     LASTELEMENT : LIST; 
  3903.  
  3904.     --| Return the value of the last element of the list. Get the pointer
  3905.     --| to the last element of L and then return its information.
  3906.  
  3907.   begin
  3908.     LASTELEMENT := LAST(L); 
  3909.     return LASTELEMENT.INFO; 
  3910.   end LASTVALUE; 
  3911.  
  3912.   --------------------------------------------------------------------------
  3913.  
  3914.   function LENGTH(L : in LIST) return INTEGER is 
  3915.  
  3916.   --| Recursively compute the length of L.  The length of a list is
  3917.   --| 0 if it is null or  1 + the length of the tail.
  3918.  
  3919.   begin
  3920.     if L = null then 
  3921.       return (0); 
  3922.     else 
  3923.       return (1 + LENGTH(TAIL(L))); 
  3924.     end if; 
  3925.   end LENGTH; 
  3926.  
  3927.   --------------------------------------------------------------------------
  3928.  
  3929.   function MAKELISTITER(L : in LIST) return LISTITER is 
  3930.  
  3931.   --| Start an iteration operation on the list L.  Do a type conversion
  3932.   --| from List to ListIter.
  3933.  
  3934.   begin
  3935.     return LISTITER(L); 
  3936.   end MAKELISTITER; 
  3937.  
  3938.   --------------------------------------------------------------------------
  3939.  
  3940.   function MORE(L : in LISTITER) return BOOLEAN is 
  3941.  
  3942.   --| This is a test to see whether an iteration is complete.
  3943.  
  3944.   begin
  3945.     return L /= null; 
  3946.   end MORE; 
  3947.  
  3948.   --------------------------------------------------------------------------
  3949.  
  3950.   procedure NEXT(PLACE : in out LISTITER; 
  3951.                  INFO  : out ITEMTYPE) is 
  3952.     PLACEINLIST : LIST; 
  3953.  
  3954.     --| This procedure gets the information at the current place in the List
  3955.     --| and moves the ListIter to the next postion in the list.
  3956.     --| If we are at the end of a list then exception NoMore is raised.
  3957.  
  3958.   begin
  3959.     if PLACE = null then 
  3960.       raise NOMORE; 
  3961.     else 
  3962.       PLACEINLIST := LIST(PLACE); 
  3963.       INFO := PLACEINLIST.INFO; 
  3964.       PLACE := LISTITER(PLACEINLIST.NEXT); 
  3965.     end if; 
  3966.   end NEXT; 
  3967.  
  3968.   --------------------------------------------------------------------------
  3969.  
  3970.   procedure REPLACEHEAD(L    : in out LIST; 
  3971.                         INFO : in ITEMTYPE) is 
  3972.  
  3973.   --| This procedure replaces the information at the head of a list
  3974.   --| with the given information. If the list is empty the exception
  3975.   --| EmptyList is raised.
  3976.  
  3977.   begin
  3978.     if L = null then 
  3979.       raise EMPTYLIST; 
  3980.     else 
  3981.       L.INFO := INFO; 
  3982.     end if; 
  3983.   end REPLACEHEAD; 
  3984.  
  3985.   --------------------------------------------------------------------------
  3986.  
  3987.   procedure REPLACETAIL(L       : in out LIST; 
  3988.                         NEWTAIL : in LIST) is 
  3989.     TEMP_L : LIST; 
  3990.  
  3991.     --| This destroys the tail of a list and replaces the tail with
  3992.     --| NewTail.  If L is empty EmptyList is raised.
  3993.  
  3994.   begin
  3995.     DESTROY(L.NEXT); 
  3996.     L.NEXT := NEWTAIL; 
  3997.   exception
  3998.     when CONSTRAINT_ERROR => 
  3999.       raise EMPTYLIST; 
  4000.   end REPLACETAIL; 
  4001.  
  4002.   --------------------------------------------------------------------------
  4003.  
  4004.   function TAIL(L : in LIST) return LIST is 
  4005.  
  4006.   --| This returns the list which is the tail of L.  If L is null Empty
  4007.   --| List is raised.
  4008.  
  4009.   begin
  4010.     if L = null then 
  4011.       raise EMPTYLIST; 
  4012.     else 
  4013.       return L.NEXT; 
  4014.     end if; 
  4015.   end TAIL; 
  4016.  
  4017.   --------------------------------------------------------------------------
  4018.   function EQUAL(LIST1 : in LIST; 
  4019.                  LIST2 : in LIST) return BOOLEAN is 
  4020.  
  4021.     PLACEINLIST1 : LIST; 
  4022.     PLACEINLIST2 : LIST; 
  4023.     CONTENTS1    : ITEMTYPE; 
  4024.     CONTENTS2    : ITEMTYPE; 
  4025.  
  4026.     --| This function tests to see if two lists are equal.  Two lists
  4027.     --| are equal if for all the elements of List1 the corresponding
  4028.     --| element of List2 has the same value.  Thus if the 1st elements
  4029.     --| are equal and the second elements are equal and so up to n.
  4030.     --|  Thus a necessary condition for two lists to be equal is that
  4031.     --| they have the same number of elements.
  4032.  
  4033.     --| This function walks over the two list and checks that the
  4034.     --| corresponding elements are equal.  As soon as we reach 
  4035.     --| the end of a list (PlaceInList = null) we fall out of the loop.
  4036.     --| If both PlaceInList1 and PlaceInList2 are null after exiting the loop
  4037.     --| then the lists are equal.  If they both are not null the lists aren't 
  4038.     --| equal.  Note that equality on elements is based on a user supplied
  4039.     --| function Equal which is used to test for item equality.
  4040.  
  4041.   begin
  4042.     PLACEINLIST1 := LIST1; 
  4043.     PLACEINLIST2 := LIST2; 
  4044.     while (PLACEINLIST1 /= null) and (PLACEINLIST2 /= null) loop
  4045.       if not EQUAL(PLACEINLIST1.INFO, PLACEINLIST2.INFO) then 
  4046.         return FALSE; 
  4047.       end if; 
  4048.       PLACEINLIST1 := PLACEINLIST1.NEXT; 
  4049.       PLACEINLIST2 := PLACEINLIST2.NEXT; 
  4050.     end loop; 
  4051.     return ((PLACEINLIST1 = null) and (PLACEINLIST2 = null)); 
  4052.   end EQUAL; 
  4053. end LISTS; 
  4054.  
  4055. --------------------------------------------------------------------------
  4056.  
  4057. with LISTS;  --| Implementation uses lists.  (private)
  4058.  
  4059. generic
  4060.   type ELEM_TYPE is private;  --| Component element type.
  4061.  
  4062. package STACK_PKG is 
  4063.  
  4064. --| Overview:
  4065. --| This package provides the stack abstract data type.  Element type is
  4066. --| a generic formal parameter to the package.  There are no explicit
  4067. --| bounds on the number of objects that can be pushed onto a given stack.
  4068. --| All standard stack operations are provided.
  4069. --|
  4070. --| The following is a complete list of operations, written in the order
  4071. --| in which they appear in the spec.  Overloaded subprograms are followed
  4072. --| by (n), where n is the number of subprograms of that name.
  4073. --|
  4074. --| Constructors:
  4075. --|        create 
  4076. --|        push
  4077. --|        pop (2)
  4078. --|        copy
  4079. --| Query Operations:
  4080. --|        top
  4081. --|        size
  4082. --|        is_empty
  4083. --| Heap Management: 
  4084. --|        destroy
  4085.  
  4086.  
  4087. --| Notes:
  4088. --| Programmer: Ron Kownacki
  4089.  
  4090.   type STACK is private;  --| The stack abstract data type.
  4091.  
  4092.   -- Exceptions:
  4093.  
  4094.   UNINITIALIZED_STACK : exception; 
  4095.   --| Raised on attempt to manipulate an uninitialized stack object.
  4096.   --| The initialization operations are create and copy.
  4097.  
  4098.   EMPTY_STACK         : exception; 
  4099.   --| Raised by some operations when empty.
  4100.  
  4101.  
  4102.   -- Constructors:
  4103.  
  4104.   function CREATE return STACK; 
  4105.  
  4106.   --| Effects:
  4107.   --| Return the empty stack.
  4108.  
  4109.   procedure PUSH(S : in out STACK; 
  4110.                  E : in ELEM_TYPE); 
  4111.  
  4112.   --| Raises: uninitialized_stack
  4113.   --| Effects:
  4114.   --| Push e onto the top of s.
  4115.   --| Raises uninitialized_stack iff s has not been initialized.
  4116.  
  4117.   procedure POP(S : in out STACK); 
  4118.  
  4119.   --| Raises: empty_stack, uninitialized_stack
  4120.   --| Effects:
  4121.   --| Pops the top element from s, and throws it away.
  4122.   --| Raises empty_stack iff s is empty.
  4123.   --| Raises uninitialized_stack iff s has not been initialized.
  4124.  
  4125.   procedure POP(S : in out STACK; 
  4126.                 E : out ELEM_TYPE); 
  4127.  
  4128.   --| Raises: empty_stack, uninitialized_stack
  4129.   --| Effects:
  4130.   --| Pops the top element from s, returns it as the e parameter.
  4131.   --| Raises empty_stack iff s is empty.
  4132.   --| Raises uninitialized_stack iff s has not been initialized.
  4133.  
  4134.   function COPY(S : in STACK) return STACK; 
  4135.  
  4136.   --| Raises: uninitialized_stack
  4137.   --| Return a copy of s.
  4138.   --| Stack assignment and passing stacks as subprogram parameters
  4139.   --| result in the sharing of a single stack value by two stack
  4140.   --| objects; changes to one will be visible through the others.
  4141.   --| copy can be used to prevent this sharing.
  4142.   --| Raises uninitialized_stack iff s has not been initialized.
  4143.  
  4144.  
  4145.   -- Queries:
  4146.  
  4147.   function TOP(S : in STACK) return ELEM_TYPE; 
  4148.  
  4149.   --| Raises: empty_stack, uninitialized_stack
  4150.   --| Effects:
  4151.   --| Return the element on the top of s.  Raises empty_stack iff s is
  4152.   --| empty.
  4153.   --| Raises uninitialized_stack iff s has not been initialized.
  4154.  
  4155.   function SIZE(S : in STACK) return NATURAL; 
  4156.  
  4157.   --| Raises: uninitialized_stack
  4158.   --| Effects:
  4159.   --| Return the current number of elements in s.
  4160.   --| Raises uninitialized_stack iff s has not been initialized.
  4161.  
  4162.   function IS_EMPTY(S : in STACK) return BOOLEAN; 
  4163.  
  4164.   --| Raises: uninitialized_stack
  4165.   --| Effects:
  4166.   --| Return true iff s is empty.
  4167.   --| Raises uninitialized_stack iff s has not been initialized.
  4168.  
  4169.  
  4170.   -- Heap Management:
  4171.  
  4172.   procedure DESTROY(S : in out STACK); 
  4173.  
  4174.   --| Effects:
  4175.   --| Return the space consumed by s to the heap.  No effect if s is
  4176.   --| uninitialized.  In any case, leaves s in uninitialized state.
  4177.  
  4178.  
  4179. private
  4180.  
  4181.   package ELEM_LIST_PKG is 
  4182.     new LISTS(ELEM_TYPE); 
  4183.   subtype ELEM_LIST is ELEM_LIST_PKG.LIST; 
  4184.  
  4185.   type STACK_REC is 
  4186.     record
  4187.       SIZE : NATURAL := 0; 
  4188.       ELTS : ELEM_LIST := ELEM_LIST_PKG.CREATE; 
  4189.     end record; 
  4190.  
  4191.   type STACK is access STACK_REC; 
  4192.  
  4193.   --| Let an instance of the representation type, r, be denoted by the
  4194.   --| pair, <size, elts>.  Dot selection is used to refer to these
  4195.   --| components.
  4196.   --|
  4197.   --| Representation Invariants:
  4198.   --|     r /= null
  4199.   --|     elem_list_pkg.length(r.elts) = r.size.
  4200.   --|
  4201.   --| Abstraction Function:
  4202.   --|     A(<size, elem_list_pkg.create>) = stack_pkg.create.
  4203.   --|     A(<size, elem_list_pkg.attach(e, l)>) = push(A(<size, l>), e).
  4204.  
  4205. end STACK_PKG; 
  4206.  
  4207. with UNCHECKED_DEALLOCATION; 
  4208.  
  4209. package body STACK_PKG is 
  4210.  
  4211. --| Overview:
  4212. --| Implementation scheme is totally described by the statements of the
  4213. --| representation invariants and abstraction function that appears in
  4214. --| the package specification.  The implementation is so trivial that
  4215. --| further documentation is unnecessary.
  4216.  
  4217.   use ELEM_LIST_PKG; 
  4218.  
  4219.  
  4220.   -- Constructors:
  4221.  
  4222.   function CREATE return STACK is 
  4223.   begin
  4224.     return new STACK_REC'(SIZE => 0, ELTS => CREATE); 
  4225.   end CREATE; 
  4226.  
  4227.   procedure PUSH(S : in out STACK; 
  4228.                  E : in ELEM_TYPE) is 
  4229.   begin
  4230.     S.SIZE := S.SIZE + 1; 
  4231.     S.ELTS := ATTACH(E, S.ELTS); 
  4232.   exception
  4233.     when CONSTRAINT_ERROR => 
  4234.       raise UNINITIALIZED_STACK; 
  4235.   end PUSH; 
  4236.  
  4237.   procedure POP(S : in out STACK) is 
  4238.   begin
  4239.     DELETEHEAD(S.ELTS); 
  4240.     S.SIZE := S.SIZE - 1; 
  4241.   exception
  4242.     when EMPTYLIST => 
  4243.       raise EMPTY_STACK; 
  4244.     when CONSTRAINT_ERROR => 
  4245.       raise UNINITIALIZED_STACK; 
  4246.   end POP; 
  4247.  
  4248.   procedure POP(S : in out STACK; 
  4249.                 E : out ELEM_TYPE) is 
  4250.   begin
  4251.     E := FIRSTVALUE(S.ELTS); 
  4252.     DELETEHEAD(S.ELTS); 
  4253.     S.SIZE := S.SIZE - 1; 
  4254.   exception
  4255.     when EMPTYLIST => 
  4256.       raise EMPTY_STACK; 
  4257.     when CONSTRAINT_ERROR => 
  4258.       raise UNINITIALIZED_STACK; 
  4259.   end POP; 
  4260.  
  4261.   function COPY(S : in STACK) return STACK is 
  4262.   begin
  4263.     if S = null then 
  4264.       raise UNINITIALIZED_STACK; 
  4265.     end if; 
  4266.  
  4267.     return new STACK_REC'(SIZE => S.SIZE, ELTS => COPY(S.ELTS)); 
  4268.   end COPY; 
  4269.  
  4270.  
  4271.   -- Queries:
  4272.  
  4273.   function TOP(S : in STACK) return ELEM_TYPE is 
  4274.   begin
  4275.     return FIRSTVALUE(S.ELTS); 
  4276.   exception
  4277.     when EMPTYLIST => 
  4278.       raise EMPTY_STACK; 
  4279.     when CONSTRAINT_ERROR => 
  4280.       raise UNINITIALIZED_STACK; 
  4281.   end TOP; 
  4282.  
  4283.   function SIZE(S : in STACK) return NATURAL is 
  4284.   begin
  4285.     return S.SIZE; 
  4286.   exception
  4287.     when CONSTRAINT_ERROR => 
  4288.       raise UNINITIALIZED_STACK; 
  4289.   end SIZE; 
  4290.  
  4291.   function IS_EMPTY(S : in STACK) return BOOLEAN is 
  4292.   begin
  4293.     return S.SIZE = 0; 
  4294.   exception
  4295.     when CONSTRAINT_ERROR => 
  4296.       raise UNINITIALIZED_STACK; 
  4297.   end IS_EMPTY; 
  4298.  
  4299.  
  4300.   -- Heap Management:
  4301.  
  4302.   procedure DESTROY(S : in out STACK) is 
  4303.     procedure FREE_STACK is 
  4304.       new UNCHECKED_DEALLOCATION(STACK_REC, STACK); 
  4305.   begin
  4306.     DESTROY(S.ELTS); 
  4307.     FREE_STACK(S); 
  4308.   exception
  4309.     when CONSTRAINT_ERROR => 
  4310.  
  4311.       -- stack is null
  4312.       return; 
  4313.   end DESTROY; 
  4314.  
  4315. end STACK_PKG; 
  4316.  
  4317. with UNCHECKED_DEALLOCATION; 
  4318. with LISTS, STACK_PKG; 
  4319.  
  4320. package body STRING_PKG is 
  4321.  
  4322. --| Overview:
  4323. --| The implementation for most operations is fairly straightforward.
  4324. --| The interesting aspects involve the allocation and deallocation of
  4325. --| heap space.  This is done as follows:
  4326. --|
  4327. --|     1. A stack of accesses to lists of string_type values is set up
  4328. --|        so that the top of the stack always refers to a list of values
  4329. --|        that were allocated since the last invocation of mark.
  4330. --|        The stack is called scopes, referring to the dynamic scopes
  4331. --|        defined by the invocations of mark and release.
  4332. --|        There is an implicit invocation of mark when the
  4333. --|        package body is elaborated; this is implemented with an explicit 
  4334. --|        invocation in the package initialization code.
  4335. --|
  4336. --|     2. At each invocation of mark, a pointer to an empty list
  4337. --|        is pushed onto the stack.
  4338. --|
  4339. --|     3. At each invocation of release, all of the values in the
  4340. --|        list referred to by the pointer at the top of the stack are
  4341. --|        returned to the heap.  Then the list, and the pointer to it,
  4342. --|        are returned to the heap.  Finally, the stack is popped.
  4343.  
  4344.   package STRING_LIST_PKG is 
  4345.     new LISTS(STRING_TYPE); 
  4346.   subtype STRING_LIST is STRING_LIST_PKG.LIST; 
  4347.  
  4348.   type STRING_LIST_PTR is access STRING_LIST; 
  4349.  
  4350.   package SCOPE_STACK_PKG is 
  4351.     new STACK_PKG(STRING_LIST_PTR); 
  4352.   subtype SCOPE_STACK is SCOPE_STACK_PKG.STACK; 
  4353.  
  4354.   use STRING_LIST_PKG; 
  4355.   use SCOPE_STACK_PKG; 
  4356.  
  4357.   SCOPES : SCOPE_STACK;  -- See package body overview.
  4358.  
  4359.  
  4360.   -- Utility functions/procedures:
  4361.  
  4362.   function ENTER(S : in STRING_TYPE) return STRING_TYPE; 
  4363.  
  4364.   --| Raises: illegal_alloc
  4365.   --| Effects:
  4366.   --| Stores s, the address of s.all, in current scope list (top(scopes)),
  4367.   --| and returns s.  Useful for functions that create and return new
  4368.   --| string_type values.
  4369.   --| Raises illegal_alloc if the scopes stack is empty.
  4370.  
  4371.   function MATCH_STRING(S1, S2 : in STRING; 
  4372.                         START  : in POSITIVE := 1) return NATURAL; 
  4373.  
  4374.   --| Raises: no_match
  4375.   --| Effects:
  4376.   --| Returns the minimum index, i, in s1'range such that
  4377.   --| s1(i..i + s2'length - 1) = s2.  Returns 0 if no such index.
  4378.   --| Requires:
  4379.   --| s1'first = 1.
  4380.  
  4381.   -- Constructors:
  4382.  
  4383.   function CREATE(S : in STRING) return STRING_TYPE is 
  4384.     subtype CONSTR_STR is STRING(1 .. S'LENGTH); 
  4385.     DEC_S : CONSTR_STR := S; 
  4386.   begin
  4387.     return ENTER(new CONSTR_STR'(DEC_S)); 
  4388.  
  4389.   -- DECada bug; above code (and decl of dec_s) replaces the following: 
  4390.   --        return enter(new constr_str'(s));
  4391.   end CREATE; 
  4392.  
  4393.   function "&"(S1, S2 : in STRING_TYPE) return STRING_TYPE is 
  4394.   begin
  4395.     if IS_EMPTY(S1) then 
  4396.       return ENTER(MAKE_PERSISTENT(S2)); 
  4397.     end if; 
  4398.     if IS_EMPTY(S2) then 
  4399.       return ENTER(MAKE_PERSISTENT(S1)); 
  4400.     end if; 
  4401.     return CREATE(S1.all & S2.all); 
  4402.   end "&"; 
  4403.  
  4404.   function "&"(S1 : in STRING_TYPE; 
  4405.                S2 : in STRING) return STRING_TYPE is 
  4406.   begin
  4407.     if S1 = null then 
  4408.       return CREATE(S2); 
  4409.     end if; 
  4410.     return CREATE(S1.all & S2); 
  4411.   end "&"; 
  4412.  
  4413.   function "&"(S1 : in STRING; 
  4414.                S2 : in STRING_TYPE) return STRING_TYPE is 
  4415.   begin
  4416.     if S2 = null then 
  4417.       return CREATE(S1); 
  4418.     end if; 
  4419.     return CREATE(S1 & S2.all); 
  4420.   end "&"; 
  4421.  
  4422.   function SUBSTR(S   : in STRING_TYPE; 
  4423.                   I   : in POSITIVE; 
  4424.                   LEN : in NATURAL) return STRING_TYPE is 
  4425.   begin
  4426.     if LEN = 0 then 
  4427.       return null; 
  4428.     end if; 
  4429.     return CREATE(S(I .. (I + LEN - 1))); 
  4430.   exception
  4431.     when CONSTRAINT_ERROR => 
  4432.  
  4433.       -- on array fetch or null deref
  4434.       raise BOUNDS; 
  4435.   end SUBSTR; 
  4436.  
  4437.   function SPLICE(S   : in STRING_TYPE; 
  4438.                   I   : in POSITIVE; 
  4439.                   LEN : in NATURAL) return STRING_TYPE is 
  4440.   begin
  4441.     if LEN = 0 then 
  4442.       return ENTER(MAKE_PERSISTENT(S)); 
  4443.     end if; 
  4444.     if I + LEN - 1 > LENGTH(S) then 
  4445.       raise BOUNDS; 
  4446.     end if; 
  4447.  
  4448.     return CREATE(S(1 .. (I - 1)) & S((I + LEN) .. LENGTH(S))); 
  4449.   end SPLICE; 
  4450.  
  4451.   function INSERT(S1, S2 : in STRING_TYPE; 
  4452.                   I      : in POSITIVE) return STRING_TYPE is 
  4453.   begin
  4454.     if I > LENGTH(S1) then 
  4455.       raise BOUNDS; 
  4456.     end if; 
  4457.     if IS_EMPTY(S2) then 
  4458.       return CREATE(S1.all); 
  4459.     end if; 
  4460.  
  4461.     return CREATE(S1(1 .. (I - 1)) & S2.all & S1(I .. S1'LAST)); 
  4462.   end INSERT; 
  4463.  
  4464.   function INSERT(S1 : in STRING_TYPE; 
  4465.                   S2 : in STRING; 
  4466.                   I  : in POSITIVE) return STRING_TYPE is 
  4467.   begin
  4468.     if I > LENGTH(S1) then 
  4469.       raise BOUNDS; 
  4470.     end if; 
  4471.  
  4472.     return CREATE(S1(1 .. (I - 1)) & S2 & S1(I .. S1'LAST)); 
  4473.   end INSERT; 
  4474.  
  4475.   function INSERT(S1 : in STRING; 
  4476.                   S2 : in STRING_TYPE; 
  4477.                   I  : in POSITIVE) return STRING_TYPE is 
  4478.   begin
  4479.     if not (I in S1'range ) then 
  4480.       raise BOUNDS; 
  4481.     end if; 
  4482.     if S2 = null then 
  4483.       return CREATE(S1); 
  4484.     end if; 
  4485.  
  4486.     return CREATE(S1(S1'FIRST .. (I - 1)) & S2.all & S1(I .. S1'LAST)); 
  4487.   end INSERT; 
  4488.  
  4489.   function LOWER(S : in STRING) return STRING_TYPE is 
  4490.     S2 : STRING_TYPE := CREATE(S); 
  4491.  
  4492.     procedure LC(C : in out CHARACTER) is 
  4493.     begin
  4494.       if ('A' <= C) and then (C <= 'Z') then 
  4495.         C := CHARACTER'VAL(CHARACTER'POS(C) - CHARACTER'POS('A') + CHARACTER'POS
  4496.           ('a')); 
  4497.       end if; 
  4498.     end LC; 
  4499.  
  4500.   begin
  4501.     for I in S2'range loop
  4502.       LC(S2(I)); 
  4503.     end loop; 
  4504.     return S2; 
  4505.   end LOWER; 
  4506.  
  4507.   function LOWER(S : in STRING_TYPE) return STRING_TYPE is 
  4508.   begin
  4509.     if S = null then 
  4510.       return null; 
  4511.     end if; 
  4512.     return LOWER(S.all); 
  4513.   end LOWER; 
  4514.  
  4515.   function UPPER(S : in STRING) return STRING_TYPE is 
  4516.     S2 : STRING_TYPE := CREATE(S); 
  4517.  
  4518.     procedure UC(C : in out CHARACTER) is 
  4519.     begin
  4520.       if ('a' <= C) and then (C <= 'z') then 
  4521.         C := CHARACTER'VAL(CHARACTER'POS(C) - CHARACTER'POS('a') + CHARACTER'POS
  4522.           ('A')); 
  4523.       end if; 
  4524.     end UC; 
  4525.  
  4526.   begin
  4527.     for I in S2'range loop
  4528.       UC(S2(I)); 
  4529.     end loop; 
  4530.     return S2; 
  4531.   end UPPER; 
  4532.  
  4533.   function UPPER(S : in STRING_TYPE) return STRING_TYPE is 
  4534.   begin
  4535.     if S = null then 
  4536.       return null; 
  4537.     end if; 
  4538.     return UPPER(S.all); 
  4539.   end UPPER; 
  4540.  
  4541.  
  4542.   -- Heap Management:
  4543.  
  4544.   function MAKE_PERSISTENT(S : in STRING_TYPE) return STRING_TYPE is 
  4545.     subtype CONSTR_STR is STRING(1 .. LENGTH(S)); 
  4546.   begin
  4547.     if S = null or else S.all = "" then 
  4548.       return null; 
  4549.     else 
  4550.       return new CONSTR_STR'(S.all); 
  4551.     end if; 
  4552.   end MAKE_PERSISTENT; 
  4553.  
  4554.   function MAKE_PERSISTENT(S : in STRING) return STRING_TYPE is 
  4555.     subtype CONSTR_STR is STRING(1 .. S'LENGTH); 
  4556.   begin
  4557.     if S = "" then 
  4558.       return null; 
  4559.     else 
  4560.       return new CONSTR_STR'(S); 
  4561.     end if; 
  4562.   end MAKE_PERSISTENT; 
  4563.  
  4564.   procedure REAL_FLUSH is 
  4565.     new UNCHECKED_DEALLOCATION(STRING, STRING_TYPE); 
  4566.     --| Effect:
  4567.     --| Return space used by argument to heap.  Does nothing if null.
  4568.     --| Notes:
  4569.     --| This procedure is actually the body for the flush procedure,
  4570.     --| but a generic instantiation cannot be used as a body for another
  4571.     --| procedure.  You tell me why.
  4572.  
  4573.   procedure FLUSH(S : in out STRING_TYPE) is 
  4574.   begin
  4575.     if S /= null then 
  4576.       REAL_FLUSH(S); 
  4577.     end if; 
  4578.  
  4579.   -- Actually, the if isn't needed; however, DECada compiler chokes
  4580.   -- on deallocation of null.
  4581.   end FLUSH; 
  4582.  
  4583.   procedure MARK is 
  4584.   begin
  4585.     PUSH(SCOPES, new STRING_LIST'(CREATE)); 
  4586.   end MARK; 
  4587.  
  4588.   procedure RELEASE is 
  4589.     procedure FLUSH_LIST_PTR is 
  4590.       new UNCHECKED_DEALLOCATION(STRING_LIST, STRING_LIST_PTR); 
  4591.     ITER     : STRING_LIST_PKG.LISTITER; 
  4592.     TOP_LIST : STRING_LIST_PTR; 
  4593.     S        : STRING_TYPE; 
  4594.   begin
  4595.     POP(SCOPES, TOP_LIST); 
  4596.     ITER := MAKELISTITER(TOP_LIST.all); 
  4597.     while MORE(ITER) loop
  4598.       NEXT(ITER, S); 
  4599.       FLUSH(S); 
  4600.  
  4601.     -- real_flush is bad, DECada bug
  4602.     --          real_flush(s);            
  4603.     end loop; 
  4604.     DESTROY(TOP_LIST.all); 
  4605.     FLUSH_LIST_PTR(TOP_LIST); 
  4606.   exception
  4607.     when EMPTY_STACK => 
  4608.       raise ILLEGAL_DEALLOC; 
  4609.   end RELEASE; 
  4610.  
  4611.  
  4612.   -- Queries:
  4613.  
  4614.   function IS_EMPTY(S : in STRING_TYPE) return BOOLEAN is 
  4615.   begin
  4616.     return (S = null) or else (S.all = ""); 
  4617.   end IS_EMPTY; 
  4618.  
  4619.   function LENGTH(S : in STRING_TYPE) return NATURAL is 
  4620.   begin
  4621.     if S = null then 
  4622.       return 0; 
  4623.     end if; 
  4624.     return (S.all'LENGTH); 
  4625.   end LENGTH; 
  4626.  
  4627.   function VALUE(S : in STRING_TYPE) return STRING is 
  4628.     subtype NULL_RANGE is POSITIVE range 1 .. 0; 
  4629.     subtype NULL_STRING is STRING(NULL_RANGE); 
  4630.   begin
  4631.     if S = null then 
  4632.       return NULL_STRING'(""); 
  4633.     end if; 
  4634.     return S.all; 
  4635.   end VALUE; 
  4636.  
  4637.   function FETCH(S : in STRING_TYPE; 
  4638.                  I : in POSITIVE) return CHARACTER is 
  4639.   begin
  4640.     if IS_EMPTY(S) or else (not (I in S'range )) then 
  4641.       raise BOUNDS; 
  4642.     end if; 
  4643.     return S(I); 
  4644.   end FETCH; 
  4645.  
  4646.   function EQUAL(S1, S2 : in STRING_TYPE) return BOOLEAN is 
  4647.   begin
  4648.     if IS_EMPTY(S1) then 
  4649.       return IS_EMPTY(S2); 
  4650.     end if; 
  4651.     return (S2 /= null) and then (S1.all = S2.all); 
  4652.  
  4653.   -- The above code replaces the following.  (DECada buggy)
  4654.   --        return s1.all = s2.all;
  4655.   --    exception
  4656.   --    when constraint_error =>     -- s is null
  4657.   --        return is_empty(s1) and is_empty(s2);
  4658.   end EQUAL; 
  4659.  
  4660.   function EQUAL(S1 : in STRING_TYPE; 
  4661.                  S2 : in STRING) return BOOLEAN is 
  4662.   begin
  4663.     if S1 = null then 
  4664.       return S2 = ""; 
  4665.     end if; 
  4666.     return S1.all = S2; 
  4667.   end EQUAL; 
  4668.  
  4669.   function EQUAL(S1 : in STRING; 
  4670.                  S2 : in STRING_TYPE) return BOOLEAN is 
  4671.   begin
  4672.     if S2 = null then 
  4673.       return S1 = ""; 
  4674.     end if; 
  4675.     return S1 = S2.all; 
  4676.   end EQUAL; 
  4677.  
  4678.   function "<"(S1 : in STRING_TYPE; 
  4679.                S2 : in STRING_TYPE) return BOOLEAN is 
  4680.   begin
  4681.     if IS_EMPTY(S1) then 
  4682.       return (not IS_EMPTY(S2)); 
  4683.     else 
  4684.       return (S1.all < S2); 
  4685.     end if; 
  4686.  
  4687.   -- Got rid of the following code:  (Think that DECada is buggy)
  4688.   --return s1.all < s2.all; 
  4689.   --exception
  4690.   --when constraint_error =>   -- on null deref
  4691.   --return (not is_empty(s2)); 
  4692.   -- one of them must be empty
  4693.   end "<"; 
  4694.  
  4695.   function "<"(S1 : in STRING_TYPE; 
  4696.                S2 : in STRING) return BOOLEAN is 
  4697.   begin
  4698.     if S1 = null then 
  4699.       return S2 /= ""; 
  4700.     end if; 
  4701.     return S1.all < S2; 
  4702.   end "<"; 
  4703.  
  4704.   function "<"(S1 : in STRING; 
  4705.                S2 : in STRING_TYPE) return BOOLEAN is 
  4706.   begin
  4707.     if S2 = null then 
  4708.       return FALSE; 
  4709.     end if; 
  4710.     return S1 < S2.all; 
  4711.   end "<"; 
  4712.  
  4713.   function "<="(S1 : in STRING_TYPE; 
  4714.                 S2 : in STRING_TYPE) return BOOLEAN is 
  4715.   begin
  4716.     if IS_EMPTY(S1) then 
  4717.       return TRUE; 
  4718.     end if; 
  4719.     return (S1.all <= S2); 
  4720.  
  4721.   -- Replaces the following:  (I think DECada is buggy)
  4722.   --return s1.all <= s2.all; 
  4723.   --exception
  4724.   --when constraint_error =>   -- on null deref
  4725.   --return is_empty(s1);   -- one must be empty, so s1<=s2 iff s1 = ""
  4726.   end "<="; 
  4727.  
  4728.   function "<="(S1 : in STRING_TYPE; 
  4729.                 S2 : in STRING) return BOOLEAN is 
  4730.   begin
  4731.     if S1 = null then 
  4732.       return TRUE; 
  4733.     end if; 
  4734.     return S1.all <= S2; 
  4735.   end "<="; 
  4736.  
  4737.   function "<="(S1 : in STRING; 
  4738.                 S2 : in STRING_TYPE) return BOOLEAN is 
  4739.   begin
  4740.     if S2 = null then 
  4741.       return S1 = ""; 
  4742.     end if; 
  4743.     return S1 <= S2.all; 
  4744.   end "<="; 
  4745.  
  4746.   function MATCH_C(S     : in STRING_TYPE; 
  4747.                    C     : in CHARACTER; 
  4748.                    START : in POSITIVE := 1) return NATURAL is 
  4749.   begin
  4750.     if S = null then 
  4751.       return 0; 
  4752.     end if; 
  4753.     for I in START .. S.all'LAST loop
  4754.       if S(I) = C then 
  4755.         return I; 
  4756.       end if; 
  4757.     end loop; 
  4758.     return 0; 
  4759.   end MATCH_C; 
  4760.  
  4761.   function MATCH_NOT_C(S     : in STRING_TYPE; 
  4762.                        C     : in CHARACTER; 
  4763.                        START : in POSITIVE := 1) return NATURAL is 
  4764.   begin
  4765.     if S = null then 
  4766.       return 0; 
  4767.     end if; 
  4768.     for I in START .. S.all'LAST loop
  4769.       if S(I) /= C then 
  4770.         return I; 
  4771.       end if; 
  4772.     end loop; 
  4773.     return 0; 
  4774.   end MATCH_NOT_C; 
  4775.  
  4776.   function MATCH_S(S1, S2 : in STRING_TYPE; 
  4777.                    START  : in POSITIVE := 1) return NATURAL is 
  4778.   begin
  4779.     if (S1 = null) or else (S2 = null) then 
  4780.       return 0; 
  4781.     end if; 
  4782.     return MATCH_STRING(S1.all, S2.all, START); 
  4783.   end MATCH_S; 
  4784.  
  4785.   function MATCH_S(S1    : in STRING_TYPE; 
  4786.                    S2    : in STRING; 
  4787.                    START : in POSITIVE := 1) return NATURAL is 
  4788.   begin
  4789.     if S1 = null then 
  4790.       return 0; 
  4791.     end if; 
  4792.     return MATCH_STRING(S1.all, S2, START); 
  4793.   end MATCH_S; 
  4794.  
  4795.   function MATCH_ANY(S, ANY : in STRING_TYPE; 
  4796.                      START  : in POSITIVE := 1) return NATURAL is 
  4797.   begin
  4798.     if ANY = null then 
  4799.       raise ANY_EMPTY; 
  4800.     end if; 
  4801.     return MATCH_ANY(S, ANY.all, START); 
  4802.   end MATCH_ANY; 
  4803.  
  4804.   function MATCH_ANY(S     : in STRING_TYPE; 
  4805.                      ANY   : in STRING; 
  4806.                      START : in POSITIVE := 1) return NATURAL is 
  4807.   begin
  4808.     if ANY = "" then 
  4809.       raise ANY_EMPTY; 
  4810.     end if; 
  4811.     if S = null then 
  4812.       return 0; 
  4813.     end if; 
  4814.  
  4815.     for I in START .. S.all'LAST loop
  4816.       for J in ANY'range loop
  4817.         if S(I) = ANY(J) then 
  4818.           return I; 
  4819.         end if; 
  4820.       end loop; 
  4821.     end loop; 
  4822.     return 0; 
  4823.   end MATCH_ANY; 
  4824.  
  4825.   function MATCH_NONE(S, NONE : in STRING_TYPE; 
  4826.                       START   : in POSITIVE := 1) return NATURAL is 
  4827.   begin
  4828.     if IS_EMPTY(S) then 
  4829.       return 0; 
  4830.     end if; 
  4831.     if IS_EMPTY(NONE) then 
  4832.       return 1; 
  4833.     end if; 
  4834.  
  4835.     return MATCH_NONE(S, NONE.all, START); 
  4836.   end MATCH_NONE; 
  4837.  
  4838.   function MATCH_NONE(S     : in STRING_TYPE; 
  4839.                       NONE  : in STRING; 
  4840.                       START : in POSITIVE := 1) return NATURAL is 
  4841.     FOUND : BOOLEAN; 
  4842.   begin
  4843.     if IS_EMPTY(S) then 
  4844.       return 0; 
  4845.     end if; 
  4846.  
  4847.     for I in START .. S.all'LAST loop
  4848.       FOUND := TRUE; 
  4849.       for J in NONE'range loop
  4850.         if S(I) = NONE(J) then 
  4851.           FOUND := FALSE; 
  4852.           exit; 
  4853.         end if; 
  4854.       end loop; 
  4855.       if FOUND then 
  4856.         return I; 
  4857.       end if; 
  4858.     end loop; 
  4859.     return 0; 
  4860.   end MATCH_NONE; 
  4861.  
  4862.  
  4863.   -- Utilities:
  4864.  
  4865.   function ENTER(S : in STRING_TYPE) return STRING_TYPE is 
  4866.   begin
  4867.     TOP(SCOPES).all := ATTACH(TOP(SCOPES).all, S); 
  4868.     return S; 
  4869.   exception
  4870.     when EMPTY_STACK => 
  4871.       raise ILLEGAL_ALLOC; 
  4872.   end ENTER; 
  4873.  
  4874.   function MATCH_STRING(S1, S2 : in STRING; 
  4875.                         START  : in POSITIVE := 1) return NATURAL is 
  4876.     OFFSET : NATURAL; 
  4877.   begin
  4878.     OFFSET := S2'LENGTH - 1; 
  4879.     for I in START .. (S1'LAST - OFFSET) loop
  4880.       if S1(I .. (I + OFFSET)) = S2 then 
  4881.         return I; 
  4882.       end if; 
  4883.     end loop; 
  4884.     return 0; 
  4885.   exception
  4886.     when CONSTRAINT_ERROR => 
  4887.  
  4888.       -- on offset := s2'length (= 0)
  4889.       return 0; 
  4890.   end MATCH_STRING; 
  4891.  
  4892. begin
  4893.  
  4894.   -- Initialize the scopes stack with an implicit mark.
  4895.   SCOPES := CREATE; 
  4896.   MARK; 
  4897. end STRING_PKG; 
  4898. with Text_IO, Calendar;
  4899.  
  4900. ---------------------------
  4901. package body Time_Library_1 is
  4902. ---------------------------
  4903.  
  4904. --| Overview
  4905. --| TimeLib contains procedures and functions for getting, putting,
  4906. --| and calculating times, and dates. It augments the
  4907. --| predefined library package Calendar to simplify IO and provide
  4908. --| additional time routines common to all Ada Test and Evaluation
  4909. --| Tool Set (ATETS) tools.
  4910.  
  4911. --| Requires
  4912. --| All procedures and functions that perform IO use the
  4913. --| predefined library package Text_IO and require that the
  4914. --| specified file be opened by the calling program prior to use.
  4915. --| All times and durations must be of types declared in the
  4916. --| predefined library package Calendar.
  4917.  
  4918. --| Errors
  4919. --| No error messages or exceptions are raised by any of the TimeLib
  4920. --| procedures and functions. However, any Text_IO and Calendar
  4921. --| exceptions that may be raised are allowed to pass, unhandled,
  4922. --| back to the calling program.
  4923.  
  4924. --| N/A:  Raises, Modifies
  4925.  
  4926. --  Version         : 1.1
  4927. --  Author          : Jeff England
  4928. --  Initial Release : 05/19/85
  4929. --  Last Modified   : 06/07/85
  4930.  
  4931.  
  4932. package Time_IO is new Text_IO.Fixed_IO( Calendar.Day_Duration );
  4933. package Int_IO  is new Text_IO.Integer_IO( Integer );
  4934.  
  4935. Timing_Method : Timing_Type := Wall_Clock;
  4936.             --| When Timing_Method = WALL_CLOCK then Put_Time
  4937.             --| puts the time to the file in the form HH:MM:SS:FF.
  4938.             --| When Timing_Method = RAW the time put using
  4939.             --| Fixed_IO(Day_Duration).
  4940.  
  4941.  
  4942. ----------------
  4943. function Convert( --| Convert an integer to a string
  4944.     Input_Number : in integer;
  4945.     Width        : in integer := 0
  4946.     ) return string is
  4947.  
  4948.   --| Effects:
  4949.   --| Converts an integer to a string of length Width. If the
  4950.   --| number if digits in Input_Number is less than Width then
  4951.   --| the digits are right justified in the output string and
  4952.   --| filled with zeros (0) on the left.
  4953.  
  4954.     Temp_Text : string (1 .. 16);
  4955.     Index     : integer;
  4956.  
  4957.  
  4958. begin
  4959.  
  4960.     Int_IO.Put(Temp_Text, Input_Number);
  4961.     if Width <= 0 then
  4962.         Index := Temp_Text'last;
  4963.         for i in Temp_Text'range loop
  4964.             if Temp_Text(i) /= ' ' then
  4965.                 Index := i;
  4966.                 exit;
  4967.             end if;
  4968.         end loop;
  4969.     else
  4970.         Index := Temp_Text'last - Width + 1;
  4971.         for i in Index .. Temp_Text'last loop
  4972.             if Temp_Text(i) = ' ' then
  4973.                 Temp_Text(i) := '0';
  4974.             end if;
  4975.         end loop;
  4976.     end if;
  4977.     return Temp_Text(Index .. Temp_Text'last);
  4978.  
  4979. end Convert;
  4980.  
  4981.  
  4982. -----------------
  4983. function Fraction ( --| returns the fraction portion of the time in seconds
  4984.     Seconds : Calendar.Day_Duration
  4985.     ) return string is
  4986.  
  4987. Temp_Secs : String(1..10);
  4988.  
  4989. begin
  4990.     Time_IO.Put( Temp_Secs, Seconds, 2, 0 );
  4991.     return Temp_Secs( Temp_Secs'Last-2 .. Temp_Secs'Last );
  4992. end Fraction;
  4993.  
  4994.  
  4995. ----------------
  4996. function Date_of ( --| Convert the date to a string
  4997.     Date : Calendar.Time    --| The date to be converted
  4998.     ) return string is
  4999.  
  5000.   --| Effects
  5001.   --| Converts the date to a string in the format MM/DD/YY
  5002.  
  5003.   --| N/A:  Raises, Requires, Modifies, Errors
  5004.  
  5005.     Year        : Calendar.Year_Number;
  5006.     Month       : Calendar.Month_Number;
  5007.     Day         : Calendar.Day_Number;
  5008.     Seconds     : Calendar.Day_Duration;
  5009.  
  5010. begin
  5011.  
  5012.     Calendar.Split(Date, Year, Month, Day, Seconds );
  5013.     return Convert(integer(Month), 2) & "/"
  5014.            & Convert(integer(Day), 2) & "/"
  5015.            & Convert(integer(Year mod 100), 2);
  5016.  
  5017. end Date_of;
  5018.  
  5019.  
  5020.  
  5021. ----------------------
  5022. function Wall_Clock_of ( --| Convert seconds to wall clock time
  5023.     Seconds : Calendar.Day_Duration  --| The time to be converted
  5024.     ) return string is
  5025.  
  5026.   --| Effects
  5027.   --| Converts the time of day or elapsed time, in seconds,
  5028.   --| to a string in the format HH:MM:SS.FF.
  5029.  
  5030.   --| N/A:  Raises, Requires, Modifies, Errors
  5031.  
  5032.     use Calendar;  -- For "-" of times and durations
  5033.  
  5034.     Half_Second : Day_Duration := 0.5;
  5035.  
  5036. begin
  5037.  
  5038.     If Seconds < Half_Second then
  5039.         Half_Second := 0.0;
  5040.     end if;
  5041.  
  5042.     return Convert(   integer(Seconds - Half_Second) / 3600, 2)
  5043.          & ":"
  5044.          & Convert( ( integer(Seconds - Half_Second) mod 3600 ) / 60, 2 )
  5045.          & ":"
  5046.          & Convert(   integer(Seconds - Half_Second) mod 60, 2 ) 
  5047.          & Fraction( Seconds );
  5048.  
  5049. end Wall_Clock_of;
  5050.  
  5051.  
  5052. -------------------------
  5053. procedure Put_Time_of_Day ( --| Put the time of day to the file
  5054.     Fyle : in Text_IO.File_Type;        --| The output file
  5055.     Seconds : in Calendar.Day_Duration  --| The time to be output
  5056.     ) is
  5057.  
  5058.   --| Effects
  5059.   --| If Timing = WALL_CLOCK then the time is put to the file in the
  5060.   --| format HH:MM:SS.FF. If Timing = RAW then the time of
  5061.   --| day is put to the file using new Fixed_IO( Day_Duration ).
  5062.   --|
  5063.   --| Requires
  5064.   --| Fyle must have been previously opened by the calling program.
  5065.  
  5066.   --| N/A:  Raises, Modifies, Errors
  5067.  
  5068.  
  5069. begin
  5070.  
  5071.     if Timing_Method = Wall_Clock then
  5072.         Text_IO.Put( Fyle, Wall_Clock_of( Seconds ) );
  5073.     else
  5074.         Time_IO.Put( Fyle, Seconds, 0, 2, 0 );
  5075.     end if;
  5076.  
  5077. end Put_Time_of_Day;
  5078.  
  5079.  
  5080. ------------------
  5081. procedure Put_Time ( --| Put the time to the file
  5082.     Fyle : in Text_IO.File_Type;  --| The output file
  5083.     Date : in Calendar.Time       --| The time to be output
  5084.     ) is
  5085.  
  5086.   --| Effects
  5087.   --| If Timing = WALL_CLOCK then the time is put to the file in the
  5088.   --| format MM/DD/YYYY HH:MM:SS.FF. If Timing = RAW then the time of
  5089.   --| day is put to the file using new Fixed_IO( Day_Duration ).
  5090.   --|
  5091.   --| Requires
  5092.   --| Fyle must have been previously opened by the calling program.
  5093.  
  5094.   --| N/A:  Raises, Modifies, Errors
  5095.  
  5096.  
  5097. begin
  5098.  
  5099.     Text_IO.Put( Fyle, Date_of( Date ) );
  5100.  
  5101.     Text_IO.Put( Fyle, ' ' );
  5102.  
  5103.     Put_Time_of_Day( Fyle, Calendar.Seconds( Date ) );
  5104.  
  5105. end Put_Time;
  5106.  
  5107.  
  5108. --------------------
  5109. procedure Set_Timing ( --| Set the method of recording timing data
  5110.  
  5111.     Timing : Timing_Type  --| The type of timing data to be recorded
  5112.  
  5113.     ) is
  5114.  
  5115.   --| Effects
  5116.   --| Sets th method of recording timing data to either RAW or Wall_Clock.
  5117.   --| If Timing = WALL_CLOCK then the time is put to the file in the
  5118.   --| format MM/DD/YYYY HH:MM:SS.FF. If Timing = RAW then the time of
  5119.   --| day is put to the file using new Fixed_IO( Day_Duration ).
  5120.   --| Overhead for either method may vary from system to system.
  5121.  
  5122.   --| N/A:  Raises, Requires, Modifies, Errors
  5123.  
  5124. begin
  5125.  
  5126.     Timing_Method := Timing; --| Set timing method to RAW or WALL_CLOCK
  5127.  
  5128. end Set_Timing;
  5129.  
  5130. end Time_Library_1;
  5131. with Run_Time_Monitor; use Run_Time_Monitor;
  5132. with Type_Definitions; use Type_Definitions;
  5133. with Implementation_Dependencies; use Implementation_Dependencies;
  5134. with Text_IO;
  5135. with System;
  5136. with Calendar;
  5137.  
  5138. package Trace_Predefined_Types is
  5139.  
  5140.    --| types defined in package Standard
  5141.  
  5142.    procedure Source_Instrumenter_Added_Tracevar 
  5143.       (Current_Unit: Program_Unit_Unique_Identifier;
  5144.        Variable_Name: String;
  5145.        Current_Value: Integer);
  5146.  
  5147.    procedure Source_Instrumenter_Added_Tracevar 
  5148.       (Current_Unit: Program_Unit_Unique_Identifier;
  5149.        Variable_Name: String;
  5150.        Current_Value: Short_Integer);
  5151.  
  5152.    procedure Source_Instrumenter_Added_Tracevar 
  5153.       (Current_Unit: Program_Unit_Unique_Identifier;
  5154.        Variable_Name: String;
  5155.        Current_Value: Long_Integer);
  5156.  
  5157.    procedure Source_Instrumenter_Added_Tracevar 
  5158.       (Current_Unit: Program_Unit_Unique_Identifier;
  5159.        Variable_Name: String;
  5160.        Current_Value: Float);
  5161.  
  5162.    procedure Source_Instrumenter_Added_Tracevar 
  5163.       (Current_Unit: Program_Unit_Unique_Identifier;
  5164.        Variable_Name: String;
  5165.        Current_Value: Short_Float);
  5166.  
  5167.    procedure Source_Instrumenter_Added_Tracevar 
  5168.       (Current_Unit: Program_Unit_Unique_Identifier;
  5169.        Variable_Name: String;
  5170.        Current_Value: Long_Float);
  5171.  
  5172.    procedure Source_Instrumenter_Added_Tracevar 
  5173.       (Current_Unit: Program_Unit_Unique_Identifier;
  5174.        Variable_Name: String;
  5175.        Current_Value: Duration);
  5176.  
  5177.    procedure Source_Instrumenter_Added_Tracevar 
  5178.       (Current_Unit: Program_Unit_Unique_Identifier;
  5179.        Variable_Name: String;
  5180.        Current_Value: String);
  5181.  
  5182.    procedure Source_Instrumenter_Added_Tracevar 
  5183.       (Current_Unit: Program_Unit_Unique_Identifier;
  5184.        Variable_Name: String;
  5185.        Current_Value: Character);
  5186.  
  5187.    procedure Source_Instrumenter_Added_Tracevar 
  5188.       (Current_Unit: Program_Unit_Unique_Identifier;
  5189.        Variable_Name: String;
  5190.        Current_Value: Boolean);
  5191.  
  5192.    
  5193.    --| types defined in package Text_IO;
  5194.  
  5195.    procedure Source_Instrumenter_Added_Tracevar 
  5196.       (Current_Unit: Program_Unit_Unique_Identifier;
  5197.        Variable_Name: String;
  5198.        Current_Value: Text_IO.File_Type);
  5199.  
  5200.    procedure Source_Instrumenter_Added_Tracevar 
  5201.       (Current_Unit: Program_Unit_Unique_Identifier;
  5202.        Variable_Name: String;
  5203.        Current_Value: Text_IO.File_Mode);
  5204.  
  5205.    procedure Source_Instrumenter_Added_Tracevar 
  5206.       (Current_Unit: Program_Unit_Unique_Identifier;
  5207.        Variable_Name: String;
  5208.        Current_Value: Text_IO.Count);
  5209.  
  5210.    procedure Source_Instrumenter_Added_Tracevar 
  5211.       (Current_Unit: Program_Unit_Unique_Identifier;
  5212.        Variable_Name: String;
  5213.        Current_Value: Text_IO.Type_Set);
  5214.  
  5215.  
  5216.    --| types defined in package System
  5217.  
  5218.    procedure Source_Instrumenter_Added_Tracevar 
  5219.       (Current_Unit: Program_Unit_Unique_Identifier;
  5220.        Variable_Name: String;
  5221.        Current_Value: System.Address);
  5222.  
  5223.    procedure Source_Instrumenter_Added_Tracevar 
  5224.       (Current_Unit: Program_Unit_Unique_Identifier;
  5225.        Variable_Name: String;
  5226.        Current_Value: System.Name);
  5227.  
  5228.  
  5229.    --| types defined in package Calendar
  5230.  
  5231.    procedure Source_Instrumenter_Added_Tracevar 
  5232.       (Current_Unit: Program_Unit_Unique_Identifier;
  5233.        Variable_Name: String;
  5234.        Current_Value: Calendar.Time);
  5235.  
  5236. end Trace_Predefined_Types ;
  5237.  
  5238. ---------------------------------------------------------------------
  5239.  
  5240. package body Trace_Predefined_Types is
  5241.  
  5242.    --| Types defined in package Standard
  5243.  
  5244.    procedure Source_Instrumenter_Added_Tracevar 
  5245.       (Current_Unit: Program_Unit_Unique_Identifier;
  5246.        Variable_Name: String;
  5247.        Current_Value: Integer) is
  5248.    begin
  5249.       RTM.Put_Value (Current_Unit, Variable_Name, Current_Value);
  5250.    end;
  5251.  
  5252.    procedure Source_Instrumenter_Added_Tracevar 
  5253.       (Current_Unit: Program_Unit_Unique_Identifier;
  5254.        Variable_Name: String;
  5255.        Current_Value: Short_Integer) is
  5256.    begin
  5257.       RTM.Put_Value (Current_Unit, Variable_Name, Integer(Current_Value));
  5258.    end;
  5259.  
  5260.    procedure Source_Instrumenter_Added_Tracevar 
  5261.       (Current_Unit: Program_Unit_Unique_Identifier;
  5262.        Variable_Name: String;
  5263.        Current_Value: Long_Integer) is
  5264.    begin
  5265.       RTM.Put_Value (Current_Unit, Variable_Name, Integer(Current_Value));
  5266.    end;
  5267.  
  5268.    procedure Source_Instrumenter_Added_Tracevar 
  5269.       (Current_Unit: Program_Unit_Unique_Identifier;
  5270.        Variable_Name: String;
  5271.        Current_Value: Float) is
  5272.    begin
  5273.       RTM.Put_Value (Current_Unit, Variable_Name, Current_Value);
  5274.    end;
  5275.    
  5276.    procedure Source_Instrumenter_Added_Tracevar 
  5277.       (Current_Unit: Program_Unit_Unique_Identifier;
  5278.        Variable_Name: String;
  5279.        Current_Value: Short_Float) is
  5280.    begin
  5281.       RTM.Put_Value (Current_Unit, Variable_Name, Float(Current_Value));
  5282.    end;
  5283.    
  5284.    procedure Source_Instrumenter_Added_Tracevar 
  5285.       (Current_Unit: Program_Unit_Unique_Identifier;
  5286.        Variable_Name: String;
  5287.        Current_Value: Long_Float) is
  5288.    begin
  5289.       RTM.Put_Value (Current_Unit, Variable_Name, Float(Current_Value));
  5290.    end;
  5291.    
  5292.    procedure Source_Instrumenter_Added_Tracevar 
  5293.       (Current_Unit: Program_Unit_Unique_Identifier;
  5294.        Variable_Name: String;
  5295.        Current_Value: Duration) is
  5296.    begin
  5297.       RTM.Put_Value (Current_Unit, Variable_Name, Float(Current_Value));
  5298.    end;
  5299.  
  5300.    procedure Source_Instrumenter_Added_Tracevar 
  5301.       (Current_Unit: Program_Unit_Unique_Identifier;
  5302.        Variable_Name: String;
  5303.        Current_Value: String) is
  5304.    begin
  5305.       RTM.Put_Value (Current_Unit, Variable_Name, Current_Value);
  5306.   end;
  5307.  
  5308.    procedure Source_Instrumenter_Added_Tracevar 
  5309.       (Current_Unit: Program_Unit_Unique_Identifier;
  5310.        Variable_Name: String;
  5311.        Current_Value: Character) is
  5312.    begin
  5313.       RTM.Put_Value (Current_Unit, Variable_Name, 
  5314.                      character'image(Current_Value));
  5315.    end;
  5316.  
  5317.    procedure Source_Instrumenter_Added_Tracevar 
  5318.       (Current_Unit: Program_Unit_Unique_Identifier;
  5319.        Variable_Name: String;
  5320.        Current_Value: Boolean) is
  5321.    begin
  5322.       RTM.Put_Value (Current_Unit, Variable_Name, 
  5323.                      Boolean'image(Current_Value));
  5324.    end;
  5325.  
  5326.  
  5327.    --| types defined in package Text_IO
  5328.  
  5329.    procedure Source_Instrumenter_Added_Tracevar 
  5330.       (Current_Unit: Program_Unit_Unique_Identifier;
  5331.        Variable_Name: String;
  5332.        Current_Value: Text_IO.File_Type) is
  5333.    begin
  5334.       RTM.Put_Value (Current_Unit, Variable_Name,
  5335.                      "Values of type Text_IO.File_Type cannot be displayed");
  5336.    end;
  5337.  
  5338.    procedure Source_Instrumenter_Added_Tracevar 
  5339.       (Current_Unit: Program_Unit_Unique_Identifier;
  5340.        Variable_Name: String;
  5341.        Current_Value: Text_IO.File_Mode) is
  5342.    begin
  5343.       RTM.Put_Value (Current_Unit, Variable_Name,
  5344.                      Text_IO.File_Mode'image(Current_Value));
  5345.    end;
  5346.  
  5347.    procedure Source_Instrumenter_Added_Tracevar 
  5348.       (Current_Unit: Program_Unit_Unique_Identifier;
  5349.        Variable_Name: String;
  5350.        Current_Value: Text_IO.Count) is
  5351.    begin
  5352.       RTM.Put_Value (Current_Unit, Variable_Name,
  5353.                      integer(Current_Value));
  5354.    end;
  5355.  
  5356.    procedure Source_Instrumenter_Added_Tracevar 
  5357.       (Current_Unit: Program_Unit_Unique_Identifier;
  5358.        Variable_Name: String;
  5359.        Current_Value: Text_IO.Type_Set) is
  5360.    begin
  5361.       RTM.Put_Value (Current_Unit, Variable_Name,
  5362.                      Text_IO.Type_Set'image(Current_Value));
  5363.    end;
  5364.  
  5365.  
  5366.    --| types defined in package System
  5367.  
  5368.    procedure Source_Instrumenter_Added_Tracevar 
  5369.       (Current_Unit: Program_Unit_Unique_Identifier;
  5370.        Variable_Name: String;
  5371.        Current_Value: System.Address) is
  5372.    begin
  5373.       RTM.Put_Value (Current_Unit, Variable_Name,
  5374.                      "Values of type System.Address cannot be displayed");
  5375.    end;
  5376.  
  5377.    procedure Source_Instrumenter_Added_Tracevar 
  5378.       (Current_Unit: Program_Unit_Unique_Identifier;
  5379.        Variable_Name: String;
  5380.        Current_Value: System.Name) is
  5381.    begin
  5382.       RTM.Put_Value (Current_Unit, Variable_Name,
  5383.                      System.Name'image(Current_Value));
  5384.    end;
  5385.  
  5386.  
  5387.    --| types defined in package Calendar
  5388.  
  5389.    procedure Source_Instrumenter_Added_Tracevar 
  5390.       (Current_Unit: Program_Unit_Unique_Identifier;
  5391.        Variable_Name: String;
  5392.        Current_Value: Calendar.Time) is
  5393.    begin
  5394.       RTM.Put_Value (Current_Unit, Variable_Name,
  5395.                      "Values of type System.Time cannot be displayed");
  5396.    end;
  5397.  
  5398.  
  5399. end Trace_Predefined_Types;
  5400. with TYPE_DEFINITIONS, IMPLEMENTATION_DEPENDENCIES, TIME_LIBRARY_1, TEXT_IO,
  5401.   CALENDAR, STRING_PKG;
  5402.  
  5403. ----------------------
  5404. package body WRITE_LOG is
  5405. ----------------------
  5406.  
  5407. --| Overview
  5408. --| Write_Log is an output package used by the Run Time Monitor (RTM)
  5409. --| for the Ada Testing and Evaluation Tools. It performs all output
  5410. --| to the Execution Log File (ELF) that is used to dynamically record
  5411. --| information about programs written in the Ada language. The ELF is
  5412. --| used for output by the Run Time Monitor (RTM) to record runtime
  5413. --| information about the execution of the Ada program being
  5414. --| tested. It is used as input by various report generators which
  5415. --| summarize the information and present it in a meaningful format.
  5416.  
  5417. --| N/A: Errors, Raises, Modifies, Requires
  5418.  
  5419. --  Version         : 5.0
  5420. --  Author          : Jeff England
  5421. --  Initial Release : 04/09/85
  5422. --  Last Modified   : 07/18/85
  5423.  
  5424.   use TYPE_DEFINITIONS;            --| Global type declarations for all of
  5425.                                    --| the Ada Testing and Analysis Tools.
  5426.  
  5427.   use IMPLEMENTATION_DEPENDENCIES; --| Ada Compiler dependencies
  5428.  
  5429.   use STRING_PKG;                  --| for String_Types;
  5430.  
  5431.   use TIME_LIBRARY_1;
  5432.  
  5433.   use TEXT_IO;
  5434.  
  5435.   package NEW_INTEGER_IO is
  5436.     new INTEGER_IO(INTEGER);
  5437.   use NEW_INTEGER_IO;
  5438.  
  5439.   LOGFILE         : TEXT_IO.FILE_TYPE;
  5440.   TOOL_NAME       : TOOL_NAMES;       --| Name of the tool
  5441.   TIMING          : BOOLEAN := TRUE;  --| Timing option is used by Profile
  5442.   LOGFILE_IS_OPEN : BOOLEAN := FALSE; --| Goes true when logfile is opened
  5443.  
  5444.   LAST_TIME       : CALENDAR.TIME;
  5445.  
  5446.  
  5447.   --------------------
  5448.   procedure CREATE_LOG(--| Creates and opens the ELF for output
  5449.  
  5450.     LOGFILE_NAME  : in FILENAME; --| Name of logfile to be created
  5451.  
  5452.     TIMING_METHOD : in TIMING_TYPE := RAW;
  5453.                 --| The method of recording Timing data
  5454.  
  5455.     START_TIME    : in CALENDAR.TIME   --| Program start time
  5456.  
  5457.       ) is
  5458.  
  5459.     --| Raises: Logfile_Access_Error
  5460.  
  5461.     --| Effects
  5462.     --| Creates and opens the ELF for output by the Run Time Monitor.
  5463.     --| If the logfile already exists it will be overwritten.
  5464.     --| The date and time of the test are written
  5465.     --| to the logfile. If the logfile is already open then a
  5466.     --| Logfile_Access_Error exception is raised. Any other
  5467.     --| Text_IO exceptions that may be raised are allowed to pass
  5468.     --| unhandled back to the calling program.
  5469.  
  5470.     --| Requires
  5471.     --| Logfile_Name must conform to the file naming conventions for
  5472.     --| the host computer operating system.
  5473.  
  5474.     --| N/A:  Modifies, Errors
  5475.  
  5476.     use TIME_LIBRARY_1;
  5477.  
  5478.   begin
  5479.  
  5480.     if LOGFILE_IS_OPEN then
  5481.       raise LOGFILE_ACCESS_ERROR;
  5482.     end if;
  5483.  
  5484.     CREATE(LOGFILE, OUT_FILE, VALUE(LOGFILE_NAME)); --| Create log file
  5485.     LOGFILE_IS_OPEN := TRUE;                        --| Open for business
  5486.     PUT(LOGFILE, LOGFILE_KEYS'POS(TEST_TIME), 0);   --| Log date and time
  5487.  
  5488.     case TIMING_METHOD is
  5489.       when WALL_CLOCK => PUT(LOGFILE, " W ");
  5490.       when RAW        => PUT(LOGFILE, " R ");
  5491.     end case;
  5492.  
  5493.     TIME_LIBRARY_1.SET_TIMING(TIMING_METHOD);
  5494.     PUT_TIME(LOGFILE, START_TIME);
  5495.     LAST_TIME := START_TIME;
  5496.     NEW_LINE(LOGFILE);
  5497.  
  5498.   end CREATE_LOG;
  5499.  
  5500.  
  5501.   --------------------------------
  5502.   procedure PUT_CONFIGURATION_DATA(--| Records configuration info in the ELF
  5503.  
  5504.     TOOL_NAME    : in TOOL_NAMES;      --| Name of the tool
  5505.  
  5506.     PROGRAM_NAME : in ADA_NAME;        --| Program being tested
  5507.  
  5508.     TEST_IDENT   : in TEST_IDENTIFIER  --| A unique identifier specified
  5509.                                        --| by the user
  5510.  
  5511.       ) is
  5512.  
  5513.     --| Raises: Logfile_Access_Error
  5514.  
  5515.     --| Effects
  5516.     --| Records test configuration information in the logfile. The purpose of
  5517.     --| recording this information in the logfile is to internally uniquely
  5518.     --| identify the logfile for later use by the report generators. If the
  5519.     --| logfile already exists it will be overwritten. If the logfile
  5520.     --| is already open then the exception Logfile_Access_Error is raised.
  5521.     --| Any other Text_IO exceptions that may  be raised are allowed to
  5522.     --| pass unhandled back to the calling program.
  5523.  
  5524.     --| Requires
  5525.     --| The logfile must have been previously opened via a call to the
  5526.     --| procedure Create_Log.
  5527.  
  5528.     --| N/A:  Modifies, Errors
  5529.  
  5530.     use CALENDAR;
  5531.  
  5532.   begin
  5533.  
  5534.     if not LOGFILE_IS_OPEN then
  5535.       raise LOGFILE_ACCESS_ERROR;
  5536.     end if;
  5537.  
  5538.     PUT(LOGFILE, LOGFILE_KEYS'POS(PROGRAM), 0);     --| Log program name
  5539.     PUT(LOGFILE, " ");
  5540.     PUT_LINE(LOGFILE, VALUE(PROGRAM_NAME));
  5541.     PUT(LOGFILE, LOGFILE_KEYS'POS(TOOL), 0);        --| Log tool name
  5542.     PUT(LOGFILE, " ");
  5543.     PUT_LINE(LOGFILE, TOOL_NAMES'IMAGE(TOOL_NAME));
  5544.     PUT(LOGFILE, LOGFILE_KEYS'POS(TEST_ID), 0);     --| Log test id
  5545.     PUT(LOGFILE, " ");
  5546.     PUT_LINE(LOGFILE, VALUE(TEST_IDENT));
  5547.  
  5548.     case TOOL_NAME is
  5549.       when PROFILE_TOOL => TIMING := TRUE;
  5550.       when others       => TIMING := FALSE;
  5551.     end case;
  5552.  
  5553.   end PUT_CONFIGURATION_DATA;
  5554.  
  5555.  
  5556.   ---------------------
  5557.   procedure PUT_UNIT_ID( --| Puts the program unit id to the ELF
  5558.  
  5559.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER
  5560.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5561.  
  5562.       ) is
  5563.  
  5564.     --| Effects
  5565.     --| This is a local procedure that logs the program unit id to the
  5566.     --| log file.
  5567.  
  5568.     --| Requires
  5569.     --| The log file must have been previously opened via a call
  5570.     --| to Create_Log. This procedure assumes that the correct
  5571.     --| logfile key has already been written to the log file.
  5572.  
  5573.     --| N/A:  Raises, Modifies, Errors
  5574.  
  5575.   begin
  5576.  
  5577.     PUT(LOGFILE, " " & VALUE(UNIT_IDENTIFIER.ENCLOSING_UNIT_IDENTIFIER) & " ");
  5578.     PUT(LOGFILE, UNIT_IDENTIFIER.PROGRAM_UNIT_NUMBER, 0);
  5579.  
  5580.     case UNIT_IDENTIFIER.UNIT_TYPE is
  5581.       when PROCEDURE_TYPE =>
  5582.         PUT(LOGFILE, " P ");
  5583.       when FUNCTION_TYPE =>
  5584.         PUT(LOGFILE, " F ");
  5585.       when TASK_TYPE =>
  5586.         PUT(LOGFILE, " T ");
  5587.         PUT(LOGFILE, UNIT_IDENTIFIER.TASK_TYPE_ACTIVATION_NUMBER, 0);
  5588.         PUT(LOGFILE, " ");
  5589.       when GENERIC_TYPE =>
  5590.         PUT(LOGFILE, " G ");
  5591.       when PACKAGE_TYPE =>
  5592.         PUT(LOGFILE, " K ");
  5593.       when others =>
  5594.         null;
  5595.     end case;
  5596.  
  5597.   end PUT_UNIT_ID;
  5598.  
  5599.  
  5600.   ---------------------------------
  5601.   procedure DEFINE_COMPILATION_UNIT( --| Define a new compilation unit
  5602.  
  5603.     COMPILATION_UNIT      : in ADA_NAME; --| Name of the compilation unit
  5604.  
  5605.     NUMBER_OF_BREAKPOINTS : in BREAKPOINT_NUMBER_RANGE;
  5606.     --| Number of breakpoints in the compilation unit
  5607.  
  5608.     LIST_OF_PROCEDURES    : in PROCEDURE_LIST
  5609.     --| Array of names and unit types of all program units in compilation unit
  5610.  
  5611.       ) is
  5612.  
  5613.     --| Raises: Logfile_Access_Error
  5614.  
  5615.     --| Effects
  5616.     --| Defines a new Compilation Unit and all of its program units
  5617.     --| to the execution log file. Subsequent references by the calling
  5618.     --| program to program units in the current compilation unit will
  5619.     --| be by a unit ID of type Program_Unit where:
  5620.     --|
  5621.     --|   Unit_Identifier.Program_Unit_Number = offset into List_of_Procedures
  5622.     --|
  5623.     --| If the logfile has not been previously opened via a call to
  5624.     --| the procedure Create_Log then the exception Logfile_Access_Error
  5625.     --| is raised.
  5626.  
  5627.     --| Requires
  5628.     --| The log file must have been previously opened by the calling
  5629.     --| program via a call to Create_Log.
  5630.  
  5631.     --| N/A:  Modifies, Errors
  5632.  
  5633.     use CALENDAR;
  5634.  
  5635.     UNIT_IDENTIFIER : PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5636.  
  5637.   begin
  5638.  
  5639.     if not LOGFILE_IS_OPEN then
  5640.       raise LOGFILE_ACCESS_ERROR;
  5641.     end if;
  5642.  
  5643.     PUT(LOGFILE, LOGFILE_KEYS'POS(COMPILATION_UNIT_DEFINITION), 0);
  5644.     PUT(LOGFILE, " " & VALUE(COMPILATION_UNIT) & " ");
  5645.     PUT(LOGFILE, NUMBER_OF_BREAKPOINTS, 0);
  5646.     NEW_LINE(LOGFILE);
  5647.  
  5648.     for UNIT_NUMBER in LIST_OF_PROCEDURES'range loop
  5649.  
  5650.       PUT(LOGFILE, LOGFILE_KEYS'POS(PROGRAM_UNIT_DEFINITION), 0);
  5651.       UNIT_IDENTIFIER := (COMPILATION_UNIT, UNIT_NUMBER,
  5652.                           LIST_OF_PROCEDURES(UNIT_NUMBER).UNIT_TYPE,
  5653.                           0); -- Task_Type_Activation_Number
  5654.       PUT_UNIT_ID(UNIT_IDENTIFIER);
  5655.       PUT_LINE(LOGFILE,
  5656.                VALUE(LIST_OF_PROCEDURES(UNIT_NUMBER).UNIT_IDENTIFIER));
  5657.  
  5658.     end loop;
  5659.  
  5660.   end DEFINE_COMPILATION_UNIT;
  5661.  
  5662.  
  5663.   --------------------
  5664.   procedure START_UNIT( --| starts the current unit in the ELF
  5665.  
  5666.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5667.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5668.  
  5669.     START_TIME      : in out CALENDAR.TIME   --| Program unit start time
  5670.  
  5671.       ) is
  5672.  
  5673.     --| Effects
  5674.     --| Puts the program unit and start time to the execution log file.
  5675.  
  5676.     --| Requires
  5677.     --| The log file must have been previously opened by the calling
  5678.     --| program via a call to Create_Log.
  5679.  
  5680.     --| N/A:  Raises, Modifies, Errors
  5681.  
  5682.     use CALENDAR;
  5683.  
  5684.   begin
  5685.  
  5686.     if TIMING then
  5687.  
  5688.       if START_TIME < LAST_TIME then
  5689.         START_TIME := LAST_TIME;
  5690.       else
  5691.         LAST_TIME := START_TIME;
  5692.       end if;
  5693.  
  5694.       PUT(LOGFILE, LOGFILE_KEYS'POS(UNIT_START), 0);
  5695.       PUT_UNIT_ID(UNIT_IDENTIFIER);
  5696.       PUT_TIME_OF_DAY(LOGFILE, SECONDS(START_TIME));
  5697.       NEW_LINE(LOGFILE);
  5698.  
  5699.     else
  5700.  
  5701.       PUT(LOGFILE, LOGFILE_KEYS'POS(UNIT_START), 0);
  5702.       PUT_UNIT_ID(UNIT_IDENTIFIER);
  5703.       NEW_LINE(LOGFILE);
  5704.  
  5705.     end if;
  5706.  
  5707.   end START_UNIT;
  5708.  
  5709.  
  5710.   -------------------
  5711.   procedure STOP_UNIT(--| Stops the current unit in the ELF
  5712.  
  5713.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5714.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5715.  
  5716.     STOP_TIME       : in out CALENDAR.TIME   --| Program unit stop time
  5717.  
  5718.       ) is
  5719.  
  5720.     --| Effects
  5721.     --| Puts the program unit and stop time to the execution log file.
  5722.  
  5723.     --| Requires
  5724.     --| The log file must have been previously opened by the calling
  5725.     --| program via a call to Create_Log.
  5726.     --| The program unit must have been previously defined to the log file by
  5727.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5728.  
  5729.     --| N/A:  Raises, Modifies, Errors
  5730.  
  5731.     use CALENDAR;
  5732.  
  5733.   begin
  5734.  
  5735.     if TIMING then
  5736.  
  5737.       if STOP_TIME < LAST_TIME then
  5738.         STOP_TIME := LAST_TIME;
  5739.       else
  5740.         LAST_TIME := STOP_TIME;
  5741.       end if;
  5742.  
  5743.       PUT(LOGFILE, LOGFILE_KEYS'POS(UNIT_STOP), 0);
  5744.       PUT_UNIT_ID(UNIT_IDENTIFIER);
  5745.       PUT_TIME_OF_DAY(LOGFILE, SECONDS(STOP_TIME));
  5746.       NEW_LINE(LOGFILE);
  5747.  
  5748.     else
  5749.  
  5750.       PUT(LOGFILE, LOGFILE_KEYS'POS(UNIT_STOP), 0);
  5751.       PUT_UNIT_ID(UNIT_IDENTIFIER);
  5752.       NEW_LINE(LOGFILE);
  5753.  
  5754.     end if;
  5755.  
  5756.   end STOP_UNIT;
  5757.  
  5758.  
  5759.   -----------------------
  5760.   function STARTING_DELAY(--| Records a delay for the specified unit and
  5761.                           --| duration in the ELF
  5762.  
  5763.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5764.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5765.  
  5766.     SECONDS         : in DURATION
  5767.  
  5768.       ) return DURATION is
  5769.  
  5770.     --| Effects
  5771.     --| Records a delay for the specified unit and duration in the
  5772.     --| Execution Log File. The length of the Delay is returned to
  5773.     --| the calling unit.
  5774.  
  5775.     --| Requires
  5776.     --| The log file must have been previously opened by the calling
  5777.     --| program via a call to Create_Log.
  5778.     --| The program unit must have been previously defined to the log file by
  5779.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5780.  
  5781.     --| N/A:  Raises, Modifies, Errors
  5782.  
  5783.     use CALENDAR;
  5784.  
  5785.   begin
  5786.  
  5787.     if TIMING then
  5788.       PUT(LOGFILE, LOGFILE_KEYS'POS(DELAY_TIME), 0);
  5789.       PUT_UNIT_ID(UNIT_IDENTIFIER);
  5790.       PUT_TIME_OF_DAY(LOGFILE, SECONDS);
  5791.       NEW_LINE(LOGFILE);
  5792.     end if;
  5793.  
  5794.     return SECONDS;
  5795.  
  5796.   end STARTING_DELAY;
  5797.  
  5798.  
  5799.   ------------------------
  5800.   procedure PUT_BREAKPOINT(--| Puts info about the current breakpont to ELF
  5801.  
  5802.     BREAKPOINT_TYPE    : in BREAKPOINT_TYPES; --| The type of breakpoint
  5803.  
  5804.     UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5805.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5806.  
  5807.     CURRENT_BREAKPOINT : in BREAKPOINT_NUMBER_RANGE
  5808.     --| The breakpoint number assigned by the Source Instrumenter
  5809.  
  5810.       ) is
  5811.  
  5812.     --| Effects
  5813.     --| Puts the program unit, statement type, and current breakpoint
  5814.     --| number to the execution log file.
  5815.  
  5816.     --| Requires
  5817.     --| The log file must have been previously opened by the calling
  5818.     --| program via a call to Create_Log.
  5819.     --| The program unit must have been previously defined to the log file by
  5820.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5821.  
  5822.     --| N/A:  Raises, Modifies, Errors
  5823.  
  5824.     use CALENDAR;
  5825.  
  5826.   begin
  5827.  
  5828.     PUT(LOGFILE, LOGFILE_KEYS'POS(BREAKPOINT_TYPE), 0);
  5829.     PUT_UNIT_ID(UNIT_IDENTIFIER);
  5830.     PUT(LOGFILE, CURRENT_BREAKPOINT, 0);
  5831.     NEW_LINE(LOGFILE);
  5832.  
  5833.   end PUT_BREAKPOINT;
  5834.  
  5835.  
  5836.   -----------------------------
  5837.   procedure PUT_CALL_PARAMETERS( --| Log AutoPath input parameter list to ELF
  5838.  
  5839.     CALL_PARAMETERS : in INPUT_PARAMETER_LIST
  5840.                   --| The user specified input parameter list
  5841.  
  5842.       ) is
  5843.  
  5844.     --| Effects
  5845.     --| Logs the calling parameter list for a single execution of the
  5846.     --| unit under test by the AutoPath shell.
  5847.  
  5848.     --| Requires
  5849.     --| The log file must have been previously opened by the calling
  5850.     --| program via a call to Create_Log.
  5851.  
  5852.     --| N/A:  Raises, Modifies, Errors
  5853.  
  5854.   begin
  5855.  
  5856.     PUT(LOGFILE, LOGFILE_KEYS'POS(AUTOPATH_CALL), 0);
  5857.     PUT_LINE(LOGFILE, " " & VALUE(CALL_PARAMETERS));
  5858.  
  5859.   end PUT_CALL_PARAMETERS;
  5860.  
  5861.  
  5862.   -------------------
  5863.   procedure PUT_VALUE(--| Logs value of integer variable to the ELF
  5864.  
  5865.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5866.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5867.  
  5868.     VARIABLE_NAME   : in STRING; --| The name of the variable
  5869.  
  5870.     INTEGER_VALUE   : in INTEGER --| The variable's value
  5871.  
  5872.       ) is
  5873.  
  5874.     --| Effects
  5875.     --| Logs integer values to the execution log file.
  5876.     --| Puts the program unit, variable name, and current value.
  5877.  
  5878.     --| Requires
  5879.     --| The log file must have been previously opened by the calling
  5880.     --| program via a call to Create_Log.
  5881.     --| The program unit must have been previously defined to the log file by
  5882.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5883.  
  5884.     --| N/A:  Raises, Modifies, Errors
  5885.  
  5886.   begin
  5887.  
  5888.     PUT(LOGFILE, LOGFILE_KEYS'POS(INTEGER_VARIABLE), 0);
  5889.     PUT_UNIT_ID(UNIT_IDENTIFIER);
  5890.     PUT(LOGFILE, VARIABLE_NAME & " ");
  5891.     PUT(LOGFILE, INTEGER_VALUE, 0);
  5892.     NEW_LINE(LOGFILE);
  5893.  
  5894.   end PUT_VALUE;
  5895.  
  5896.  
  5897.   -------------------
  5898.   procedure PUT_VALUE(--| Logs value of Long_Integer variable to the ELF
  5899.  
  5900.     UNIT_IDENTIFIER    : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5901.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5902.  
  5903.     VARIABLE_NAME      : in STRING;      --| The name of the variable
  5904.  
  5905.     LONG_INTEGER_VALUE : in LONG_INTEGER --| The variable's value
  5906.  
  5907.       ) is
  5908.  
  5909.     --| Effects
  5910.     --| Logs long_integer values to the execution log file.
  5911.     --| Puts the program unit, variable name, and current value.
  5912.  
  5913.     --| Requires
  5914.     --| The log file must have been previously opened by the calling
  5915.     --| program via a call to Create_Log.
  5916.     --| The program unit must have been previously defined to the log file by
  5917.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5918.  
  5919.     --| N/A:  Raises, Modifies, Errors
  5920.  
  5921.     package NEW_LONG_INTEGER_IO is
  5922.       new INTEGER_IO(LONG_INTEGER);
  5923.     use NEW_LONG_INTEGER_IO;
  5924.  
  5925.   begin
  5926.     NEW_INTEGER_IO.PUT(LOGFILE, LOGFILE_KEYS'POS(LONG_INTEGER_VARIABLE), 0);
  5927.     PUT_UNIT_ID(UNIT_IDENTIFIER);
  5928.     PUT(LOGFILE, VARIABLE_NAME & " ");
  5929.     NEW_LONG_INTEGER_IO.PUT(LOGFILE, LONG_INTEGER_VALUE, 0);
  5930.     NEW_LINE(LOGFILE);
  5931.   end PUT_VALUE;
  5932.  
  5933.  
  5934.   -------------------
  5935.   procedure PUT_VALUE(--| Logs value of FLOAT variable to the ELF
  5936.  
  5937.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5938.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5939.  
  5940.     VARIABLE_NAME   : in STRING; --| The name of the variable
  5941.  
  5942.     FLOAT_VALUE     : in FLOAT   --| The variable's value
  5943.  
  5944.       ) is
  5945.  
  5946.     --| Effects
  5947.     --| Logs floating point values to the execution log file
  5948.     --| Puts the program unit, variable name, and current value
  5949.  
  5950.     --| Requires
  5951.     --| The log file must have been previously opened by the calling
  5952.     --| program via a call to Create_Log.
  5953.     --| The program unit must have been previously defined to the log file by
  5954.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5955.  
  5956.     --| N/A:  Raises, Modifies, Errors
  5957.  
  5958.     package NEW_FLOAT_IO is
  5959.       new FLOAT_IO(FLOAT);
  5960.     use NEW_FLOAT_IO;
  5961.  
  5962.   begin
  5963.  
  5964.     PUT(LOGFILE, LOGFILE_KEYS'POS(FLOAT_VARIABLE), 0);
  5965.     PUT_UNIT_ID(UNIT_IDENTIFIER);
  5966.     PUT(LOGFILE, VARIABLE_NAME & " ");
  5967.     PUT(LOGFILE, FLOAT_VALUE, 0);
  5968.     NEW_LINE(LOGFILE);
  5969.  
  5970.   end PUT_VALUE;
  5971.  
  5972.  
  5973.   -------------------
  5974.   procedure PUT_VALUE(--| Logs value of Long_Float variable to the ELF
  5975.  
  5976.     UNIT_IDENTIFIER  : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  5977.     --| A unique ID assigned by the Source Instrumenter for the current unit
  5978.  
  5979.     VARIABLE_NAME    : in STRING;    --| The name of the variable
  5980.  
  5981.     LONG_FLOAT_VALUE : in LONG_FLOAT --| The variable's value
  5982.  
  5983.       ) is
  5984.  
  5985.     --| Effects
  5986.     --| Logs long_float values to the execution log file.
  5987.     --| Puts the program unit, variable name, and current value.
  5988.  
  5989.     --| Requires
  5990.     --| The log file must have been previously opened by the calling
  5991.     --| program via a call to Create_Log.
  5992.     --| The program unit must have been previously defined to the log file by
  5993.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  5994.  
  5995.     --| N/A:  Raises, Modifies, Errors
  5996.  
  5997.     package NEW_LONG_FLOAT_IO is
  5998.       new FLOAT_IO(LONG_FLOAT);
  5999.     use NEW_LONG_FLOAT_IO;
  6000.  
  6001.   begin
  6002.     PUT(LOGFILE, LOGFILE_KEYS'POS(LONG_FLOAT_VARIABLE), 0);
  6003.     PUT_UNIT_ID(UNIT_IDENTIFIER);
  6004.     PUT(LOGFILE, VARIABLE_NAME & " ");
  6005.     PUT(LOGFILE, LONG_FLOAT_VALUE, 0);
  6006.     NEW_LINE(LOGFILE);
  6007.   end PUT_VALUE;
  6008.  
  6009.  
  6010.   -------------------
  6011.   procedure PUT_VALUE(--| Logs value of string variable to the ELF
  6012.  
  6013.     UNIT_IDENTIFIER : in PROGRAM_UNIT_UNIQUE_IDENTIFIER;
  6014.     --| A unique ID assigned by the Source Instrumenter for the current unit
  6015.  
  6016.     VARIABLE_NAME   : in STRING; --| The name of the variable
  6017.  
  6018.     STRING_VALUE    : in STRING  --| The variable's value
  6019.  
  6020.       ) is
  6021.  
  6022.     --| Effects
  6023.     --| Logs string values to the execution log file
  6024.     --| Puts the program unit, variable name, and current value
  6025.     --| This procedure used to log the value of
  6026.     --|        strings
  6027.     --|        characters
  6028.     --|        enumerated data types (including booleans)
  6029.     --| If STRING_VALUE contains trailing blanks then the
  6030.     --| trailing blanks are suppressed and the notation <<N blanks>>
  6031.     --| is appended, where N is the number of trailing blanks
  6032.  
  6033.     --| Requires
  6034.     --| The log file must have been previously opened by the calling
  6035.     --| program via a call to Create_Log.
  6036.     --| The program unit must have been previously defined to the log file by
  6037.     --| the calling program via a call to the procedure Define_Compilation_Unit.
  6038.  
  6039.     --| N/A:  Raises, Modifies, Errors
  6040.  
  6041.     NUMBER_OF_BLANKS : NATURAL := 0;
  6042.  
  6043.   begin
  6044.     PUT(LOGFILE, LOGFILE_KEYS'POS(STRING_VARIABLE), 0);
  6045.     PUT_UNIT_ID(UNIT_IDENTIFIER);
  6046.     for i in reverse STRING_VALUE'range loop
  6047.       if STRING_VALUE(i) = ' ' then
  6048.         NUMBER_OF_BLANKS := NUMBER_OF_BLANKS + 1;
  6049.       else
  6050.         exit;
  6051.       end if;
  6052.     end loop;
  6053.  
  6054.     PUT(LOGFILE, VARIABLE_NAME & " ");
  6055.  
  6056.     if STRING_VALUE'last > NUMBER_OF_BLANKS then
  6057.       PUT(LOGFILE, STRING_VALUE(1..STRING_VALUE'last - NUMBER_OF_BLANKS));
  6058.     end if;
  6059.  
  6060.     case NUMBER_OF_BLANKS is
  6061.       when 0 =>
  6062.         NEW_LINE(LOGFILE);
  6063.       when 1 =>
  6064.         PUT_LINE(LOGFILE, "<<1 blank>>");
  6065.       when others =>
  6066.         PUT(LOGFILE, "<<");
  6067.         PUT(LOGFILE, NUMBER_OF_BLANKS, 0);
  6068.         PUT_LINE(LOGFILE, " blanks>>");
  6069.     end case;
  6070.   end PUT_VALUE;
  6071.  
  6072.  
  6073.   -------------------
  6074.   procedure CLOSE_LOG(  --| Closes the execution log file
  6075.  
  6076.     ACCUMULATED_OVERHEAD : in DURATION  --| Total accumulated tool overhead
  6077.  
  6078.       ) is
  6079.  
  6080.     --| Raises:  Logfile_Access_Error
  6081.  
  6082.     --| Effects
  6083.     --| Closes the execution log file.
  6084.     --| If the logfile has not been previously opened via a call to
  6085.     --| the procedure Create_Log then the exception Logfile_Access_Error
  6086.     --| is raised.
  6087.  
  6088.     --| Requires
  6089.     --| The log file must have been previously opened by the calling
  6090.     --| program via a call to Create_Log.
  6091.  
  6092.     --| N/A:  Modifies, Errors
  6093.  
  6094.     use CALENDAR;
  6095.  
  6096.   begin
  6097.  
  6098.     if not LOGFILE_IS_OPEN then
  6099.       raise LOGFILE_ACCESS_ERROR;
  6100.     end if;
  6101.  
  6102.     if TIMING then
  6103.       PUT(LOGFILE, LOGFILE_KEYS'POS(TIMING_OVERHEAD), 0);
  6104.       PUT(LOGFILE, ' ');
  6105.       PUT_TIME_OF_DAY(LOGFILE, ACCUMULATED_OVERHEAD);
  6106.     end if;
  6107.  
  6108.     CLOSE(LOGFILE);
  6109.  
  6110.     LOGFILE_IS_OPEN := FALSE;  --| Logfile is now closed for business
  6111.  
  6112.     --| Reset Timing to true just in case AutoPath
  6113.     --| tries to create more than 1 logfile
  6114.     TIMING := TRUE;
  6115.  
  6116.   end CLOSE_LOG;
  6117.  
  6118. end WRITE_LOG;
  6119.