home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / stubs / stub2.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  125.5 KB  |  3,085 lines

  1. --::::::::::
  2. --stub2.dis
  3. --::::::::::
  4. -- STUBBER 2.0
  5. stubber.pro
  6. -- The following files are in compilation order
  7. osdepc3.ada
  8. getoken.ada
  9. stubber.ada
  10. stubsup.ada
  11. -- The following files, in compilation order, are used to test STUBBER 2.0
  12. stubtest.spc
  13. stubtest.bdy
  14. --::::::::::
  15. --stubber.pro
  16. --::::::::::
  17. -------- SIMTEL20 Ada Software Repository Prologue ------------
  18. --                                                           -*
  19. -- Unit name    : Body Stubber
  20. -- Version      : 2.0
  21. -- Author       : Joseph M. Orost
  22. --              : Concurrent Computer Corporation
  23. --              : 106 Apple St
  24. --              : Tinton Falls, NJ  07724
  25. -- DDN Address  : petsd!joe@RUTGERS.EDU
  26. -- Date created : 15 July 1983
  27. -- Release date :
  28. -- Last update  : 5 May 1987
  29. -- Compiled by  : Concurrent Computer Corporation C3Ada R00-01
  30. --                                                           -*
  31. ---------------------------------------------------------------
  32. --                                                           -*
  33. -- Keywords     : 
  34. ----------------:
  35. --
  36. -- Abstract     : This program reads an Ada specification
  37. ----------------: and generates a corresponding Body with 
  38. ----------------: stubs for all subprograms.
  39. ----------------: All of the OS dependencies are contained in
  40. ----------------: the OS_DEPENDENCIES package.
  41. ----------------:
  42. ----------------: Version 1.0:
  43. ----------------: This tool was developed as a precursor for 
  44. ----------------: the WMCCS Information System (WIS).  An
  45. ----------------: executable version of the tool has been 
  46. ----------------: demonstrated.  This source code has sub-
  47. ----------------: sequently been recompiled but has not under-
  48. ----------------: gone extensive testing.
  49. ----------------:
  50. ----------------: Version 2.0:
  51. ----------------: Complete overhaul.  All non-Ansi Ada 
  52. ----------------: dependencies removed.  Bugs fixed/
  53. ----------------: Enhancements:
  54. ----------------:    Task specifications are now stubbed.
  55. ----------------:    Pragma INTERFACE now suppresses stubs.
  56. ----------------:    OUTPUT_LINE_LENGTH parameter - not
  57. ----------------:     exceeded.
  58. ----------------:    Output properly indented and aligned.
  59. ----------------:    Overwrite of output file now asks
  60. ----------------:     permission.
  61. ----------------:    Comments and declarations from spec
  62. ----------------:     included in stub.
  63. ----------------:    Spec is no longer duplicated in output.
  64. ----------------:    ID Comment is generated on "begin".
  65. ----------------:    Execution-time message now is fully
  66. ----------------:     qualified.
  67. ----------------:    Exception handler part is now a source
  68. ----------------:     parameter.
  69. ----------------:    Multiple specs in input file now works.
  70. ----------------:    Generic "with procedure" or "with
  71. ----------------:     function" now not taken as declaration 
  72. ----------------:     to be stubbed.
  73. ----------------: In addition, many code speed-ups are
  74. ----------------: included.
  75. ----------------: 
  76. ----------------: Rehosting is performed by modifying the
  77. ----------------: package OS_DEPENDENCIES: (file OSDEPxxx.ADA)
  78. ----------------:    Select the output line length.
  79. ----------------:    Select the indent amount and indent limit.
  80. ----------------:    Select the standard suffix for the
  81. ----------------:     input/output files.
  82. ----------------:    Code ADD_SUFFIX to insert the suffix into
  83. ----------------:     the filename.
  84. --                                                           -*
  85. ------------------ Revision history ---------------------------
  86. --                                                           -*
  87. -- DATE         VERSION AUTHOR                  HISTORY 
  88. -- 07/15/83     1.0     Steven E. Nameroff      Initial Release
  89. -- 05/05/87     2.0     Joseph M. Orost         Major rewrite
  90. --                                                           -*
  91. ------------------ Distribution and Copyright -----------------
  92. --                                                           -*
  93. -- This prologue must be included in all copies of this software.
  94. -- 
  95. -- This software is released to the Ada community.
  96. -- This software is released to the Public Domain (note:
  97. --   software released to the Public Domain is not subject
  98. --   to copyright protection).
  99. -- Restrictions on use or distribution:  NONE
  100. --                                                           -*
  101. ----------------- Disclaimer ----------------------------------
  102. --                                                           -*
  103. -- This software and its documentation are provided "AS IS" and
  104. -- without any expressed or implied warranties whatsoever.
  105. --
  106. -- No warranties as to performance, merchantability, or fitness
  107. -- for a particular purpose exist.
  108. --
  109. -- Because of the diversity of conditions and hardware under
  110. -- which this software may be used, no warranty of fitness for
  111. -- a particular purpose is offered.  The user is advised to 
  112. -- test the software thoroughly before relying on it.  The user
  113. -- must assume the entire risk and liability of using this 
  114. -- software.
  115. --
  116. -- In no event shall any person or organization of people be
  117. -- held responsible for any direct, indirect, consequential
  118. -- or inconsequential damages or lost profits.
  119. --                                                          -*
  120. ----------------- Known Problems -----------------------------
  121. --
  122. -- The stubber does not handle task declarations with entry
  123. -- families that are specified other than: 
  124. --         (integer_LB .. integer_UB)
  125. -- In this case, the body stub contains ACCEPT statements for
  126. -- all family members IN integer_LB .. integer_UB.
  127. --
  128. -- Entry families specified by 
  129. --         (TYPE_NAME) or 
  130. --         (TYPE_NAME'RANGE) 
  131. -- will cause a legal body to be generated, but only 1 accept
  132. -- statement (for TYPE_NAME'FIRST) is generated.  A warning
  133. -- message is produced.
  134. --
  135. -- Entry families of the form:
  136. --         (Expression .. Expression)
  137. -- causes illegal code produced in the body stub.  A warning
  138. -- message is produced.
  139. --
  140. ----------------- END-PROLOGUE -------------------------------
  141.  
  142. --::::::::::
  143. --osdepc3.ada
  144. --::::::::::
  145. --                                                                    --
  146. --                     package OS_DEPENDENCIES                        --
  147. --                                                                    --
  148. --         This version for Concurrent Computer Corporation           --
  149. --                          C3Ada R00-01                              --
  150. --                                                                    --
  151. ------------------------------------------------------------------------
  152. ------------------------------------------------------------------------
  153.  
  154. with TEXT_IO;
  155. use  TEXT_IO;
  156.  
  157. package OS_DEPENDENCIES is
  158.  
  159.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  160.   --                                                                  --
  161.   --    Package OS_DEPENDENCIES is designed to support all of the     --
  162.   --    packages that use file input/output with the OS operating     --
  163.   --    system.  It includes all of the peculiarities and machine-    --
  164.   --    dependencies that are not part of the Ada language.  These    --
  165.   --    include getting characters (GETC), and new OPEN and CREATE    --
  166.   --    CREATE commands which automatically trans-                    --
  167.   --    late file names (from GET_FILENAME) to suit the OS filer.     --
  168.   --                                                                  --
  169.   --    The package was written so that a programmer needs to only    --
  170.   --    change this package to meet another system,  to use any of    --
  171.   --    the other routines in the STUBBER.                            --
  172.   --                                                                  --
  173.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  174.   --    Date  :  15 July 1983                                         --
  175.   --    Updated: 4/28/87  J. Orost, Concurrent Computer Corporation   --
  176.   --                                                                  --
  177.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  178.  
  179.    --Set this to TRUE to generate an exception handler in the stub
  180.    --which prints a message.  If FALSE, no exception handler is declared
  181.    --in the stub.  Use FALSE is your Ada compiler already provides a
  182.    --walkback on unhandled exceptions.
  183.  
  184.    GENERATE_EXCEPTION_PART : constant BOOLEAN := TRUE;  --Compiler dependent
  185.  
  186.    OUTPUT_LINE_LENGTH      : constant := 80;     --Host dependent
  187.  
  188.    INDENT_AMOUNT           : constant := 3;      --User preference
  189.    INDENT_LIMIT            : constant := 27;     --User preference
  190.  
  191.    procedure GETC (FILE     : in FILE_TYPE;
  192.                    CHAR     : out CHARACTER;
  193.                    POSITION : in out INTEGER);
  194.  
  195.    package OS_FILE_OPS is                          -- all required due to
  196.                                                    -- the filer
  197.  
  198.       OPEN_SUFFIX   : constant STRING := ".SPC";   --Host dependent
  199.       CREATE_SUFFIX : constant STRING := ".BDY";   --Host dependent
  200.  
  201.       function  GET_FILENAME return STRING;
  202.  
  203.       procedure OPEN (FILE_NAME : in out FILE_TYPE;
  204.                       LONG_NAME : in STRING;
  205.                       SUFFIX    : in STRING := OPEN_SUFFIX);
  206.  
  207.       procedure CREATE (FILE_NAME : in out FILE_TYPE;
  208.                         LONG_NAME : in STRING;
  209.                         SUFFIX    : in STRING := CREATE_SUFFIX);
  210.  
  211.     -- All other file operations are the same as TEXT_IO
  212.     -- versions, so are not needed here.
  213.  
  214.    end OS_FILE_OPS; -- specifications.
  215.  
  216. end OS_DEPENDENCIES;  -- specifications.
  217.  
  218. ------------------- package body OS_DEPENDENCIES ----------------------
  219. ------------------------------------------------------------------------
  220.  
  221. with TEXT_IO;
  222. use  TEXT_IO;
  223. with ADA_IO_SERVICES;                                       --CCUR
  224. use  ADA_IO_SERVICES;                                       --CCUR
  225.  
  226. package body OS_DEPENDENCIES is
  227.    ENDFILE : constant CHARACTER := CHARACTER'VAL (28);
  228.  
  229.   ----------------------------------------------------------------------
  230.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  231.   ----------------------------------------------------------------------
  232.  
  233.    package body OS_FILE_OPS is
  234.  
  235.           ---------------------------------------------------------
  236.           --  This package contains all of the procedures that   --
  237.           --  are necessary for using files with the OS filer   --
  238.           --  system.                                            --
  239.           ---------------------------------------------------------
  240.  
  241.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  242.  
  243.       function  GET_FILENAME return STRING is
  244.  
  245.                     ------------------------------------------
  246.                     --  This procedure accepts input from   --
  247.                     --  the terminal for a correct system   --
  248.                     --  file name.                          --
  249.                     ------------------------------------------
  250.  
  251.          INPUT_LINE      : STRING (1 .. 72);
  252.          LENGTH_OF_INPUT : NATURAL;
  253.       begin
  254.          PUT ("Enter name of file (suffix """);
  255.          PUT (OPEN_SUFFIX);
  256.          PUT (""" assumed) : ");
  257.          NEW_LINE;                                   --CCUR
  258.          GET_LINE (INPUT_LINE, LENGTH_OF_INPUT);
  259.          return INPUT_LINE (1 .. LENGTH_OF_INPUT);
  260.       end GET_FILENAME;
  261.  
  262.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  263.  
  264.       --This routine is the where most of the host dependencies are
  265.       --located.
  266.  
  267.       function  ADD_SUFFIX (NAME    : in STRING;          --host dependent
  268.                             SUFFIX  : in STRING;                      --CCUR
  269.                             REPLACE : in BOOLEAN) return STRING is    --CCUR
  270.  
  271.                     ------------------------------------------
  272.                     --  This procedure adds the necessary   --
  273.                     --  suffix to the name that the user    --
  274.                     --  gave in GET_FILENAME to make it a   --
  275.                     --  legal system file name.             --
  276.                     --  REPLACE means to replace the suffix --
  277.                     --  into the given NAME and strip off   --
  278.                     --  any directory name.  Otherwise,     --
  279.                     --  the suffix is inserted if not       --
  280.                     --  otherwise specified by the user.    --
  281.                     ------------------------------------------
  282.  
  283.       begin
  284.          if REPLACE then                                                  --CCUR
  285.             return FILENAME (NAME) & SUFFIX;                              --CCUR
  286.          else                                                             --CCUR
  287.             if EXTENSION (NAME) = "" then                                 --CCUR
  288.                return VOLUMENAME (NAME) & FILENAME (NAME) & SUFFIX &      --CCUR
  289.                   ACCOUNT (NAME);                                         --CCUR
  290.             else                                                          --CCUR
  291.                return VOLUMENAME (NAME) & FILENAME (NAME) &               --CCUR
  292.                   EXTENSION (NAME) & ACCOUNT (NAME);                      --CCUR
  293.             end if;                                                       --CCUR
  294.          end if;                                                          --CCUR
  295.       end ADD_SUFFIX;
  296.  
  297.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  298.  
  299.       procedure OPEN (FILE_NAME : in out FILE_TYPE;
  300.                       LONG_NAME : in STRING;
  301.                       SUFFIX    : in STRING := OPEN_SUFFIX) is
  302.  
  303.                     ------------------------------------------
  304.                     --  This procedure opens a file with    --
  305.                     --  the name LONG_NAME, and the suffix  --
  306.                     --  SUFFIX.                             --
  307.                     ------------------------------------------
  308.  
  309.          NAME : constant STRING := ADD_SUFFIX (LONG_NAME, SUFFIX, FALSE);
  310.       begin
  311.          TEXT_IO.OPEN (FILE_NAME, IN_FILE, NAME);
  312.       end OPEN;
  313.  
  314.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  315.  
  316.       procedure CREATE (FILE_NAME : in out FILE_TYPE;
  317.                         LONG_NAME : in STRING;
  318.                         SUFFIX    : in STRING := CREATE_SUFFIX) is
  319.  
  320.                     ------------------------------------------
  321.                     -- This procedure creates a file with   --
  322.                     -- the name LONG_NAME and the suffix    --
  323.                     -- SUFFIX.                              --
  324.                     ------------------------------------------
  325.  
  326.          NAME : constant STRING := ADD_SUFFIX (LONG_NAME, SUFFIX, TRUE);
  327.          STOP_PROGRAM : exception;
  328.       begin
  329.          declare
  330.             BUFF : STRING(1..80);
  331.             LEN  : INTEGER;
  332.          begin
  333.             TEXT_IO.OPEN(FILE_NAME, OUT_FILE, NAME);
  334.             TEXT_IO.CLOSE(FILE_NAME);
  335.             PUT (NAME & " already exists, overwrite (y/n)?");
  336.             NEW_LINE;                                            --CCUR
  337.             GET_LINE (BUFF, LEN);
  338.             if BUFF(1) = 'Y' or else BUFF(1) = 'y' then
  339.                null;
  340.             else
  341.                raise STOP_PROGRAM;
  342.             end if;
  343.          exception
  344.             when STOP_PROGRAM =>
  345.                raise;               --Not handled
  346.             when others =>
  347.                null;
  348.          end;
  349.  
  350.          TEXT_IO.CREATE (FILE_NAME, OUT_FILE, NAME);
  351.       end CREATE;
  352.  
  353.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  354.  
  355.    begin   -- OS_FILE_OPS initializations
  356.       SET_INPUT (STANDARD_INPUT);
  357.    end OS_FILE_OPS;   -- body.
  358.  
  359.   ----------------------------------------------------------------------
  360.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  361.   ----------------------------------------------------------------------
  362.   ----------------------------------------------------------------------
  363.  
  364.    --You shouldn't have to change this procedure:
  365.  
  366.    procedure GETC (FILE     : in FILE_TYPE;
  367.                    CHAR     : out CHARACTER;
  368.                    POSITION : in out INTEGER) is
  369.  
  370.           ---------------------------------------------------------
  371.           --  This procedure gets one character, CHAR, from the  --
  372.           --  file FILE, and also returns its position, POSITION.--
  373.           ---------------------------------------------------------
  374.  
  375.    begin      -- GETC
  376.       if END_OF_FILE (FILE) then
  377.          raise END_ERROR;
  378.       elsif END_OF_LINE (FILE) then
  379.          CHAR := CHARACTER'VAL (13);
  380.          SKIP_LINE (FILE);
  381.       else
  382.          GET (FILE, CHAR);
  383.       end if;
  384.       POSITION := POSITION + 1;
  385.    exception
  386.       when END_ERROR =>                  --  Expected at end of file
  387.          raise;
  388.  
  389.       when others =>
  390.          PUT_LINE ("unexpected exception in OS_DEPENDENCIES.GETC");
  391.          raise;
  392.  
  393.    end GETC;
  394.  
  395.   ----------------------------------------------------------------------
  396.  
  397. end OS_DEPENDENCIES;
  398.  
  399. --::::::::::
  400. --getoken.ada
  401. --::::::::::
  402. --                                                                    --
  403. --                          package GETTOKEN                          --
  404. --                                                                    --
  405. ------------------------------------------------------------------------
  406. ------------------------------------------------------------------------
  407.  
  408. with TEXT_IO;
  409. use  TEXT_IO;
  410.  
  411. package GETTOKEN is
  412.  
  413.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  414.   --                                                                  --
  415.   --    Package GETTOKEN is designed to scan a string of characters   --
  416.   --    in a file, and split it up into tokens.  The only available   --
  417.   --    procedure is GET_TOKEN, which finds one token.  The package   --
  418.   --    is general enough to scan command files, but is designed to   --
  419.   --    scan Ada code, specifically.                                  --
  420.   --                                                                  --
  421.   --    All of the compiler peculiarities, editor dependencies, and   --
  422.   --    filer dependencies  have been moved to the OS_DEPENDENCIES    --
  423.   --    package.                                                      --
  424.   --                                                                  --
  425.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  426.   --    Date  :  15 July 1983                                         --
  427.   --                                                                  --
  428.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  429.  
  430.    END_FILE      : constant CHARACTER := CHARACTER'VAL (3);
  431.    END_OF_LINE   : constant CHARACTER := CHARACTER'VAL (13);
  432.    BLANK_LINE    : constant CHARACTER := CHARACTER'VAL (17);
  433.    STRING_LENGTH : constant INTEGER := 250;
  434.  
  435.    subtype LENGTH_TYPE is INTEGER range 0 .. STRING_LENGTH;
  436.  
  437.    type CLASS_TYPE is (NUM, WORD, DELIM, COMMENT, END_OF_FILE, NONE);
  438.  
  439.    type STRING_RECORD is
  440.       record
  441.          STR_ZERO : CHARACTER := END_OF_LINE; --  ########
  442.          STR      : STRING (1 .. STRING_LENGTH);
  443.          LENGTH   : LENGTH_TYPE := 0;
  444.          CLASS    : CLASS_TYPE := NONE;
  445.          POSITION : LENGTH_TYPE; -- actual position in text (for comments)
  446.       end record;
  447.  
  448.    procedure GET_TOKEN (INPUT_FILE : FILE_TYPE;
  449.                         TOKEN      : in out STRING_RECORD);
  450.  
  451. end GETTOKEN;
  452.  
  453. ------------------------------------------------------------------------
  454. ----------------------- package body GETOKEN ---------------------------
  455. ------------------------------------------------------------------------
  456.  
  457. with TEXT_IO;
  458. use  TEXT_IO;
  459. with OS_DEPENDENCIES;
  460. use  OS_DEPENDENCIES;
  461.  
  462. package body GETTOKEN is
  463.    use  OS_FILE_OPS;
  464.  
  465.    package INT_IO is new INTEGER_IO (INTEGER);
  466.    use  INT_IO;
  467.  
  468.    type CHARACTER_TABLE is array(CHARACTER) of BOOLEAN;
  469.    pragma PACK(CHARACTER_TABLE);
  470.  
  471.    DELIMITER : constant CHARACTER_TABLE := CHARACTER_TABLE'
  472.    ('"' | ',' | '&' | ''' | '(' | ')' | '*' | '+' | '-' | '/' | ':' |
  473.     ';' | '<' | '>' | '=' | '|' | '.' | BLANK_LINE => TRUE,
  474.     others => FALSE);
  475.  
  476.    LETTER    : constant CHARACTER_TABLE := CHARACTER_TABLE'
  477.    ('A'..'Z' | 'a'..'z' | '_' => TRUE, others => FALSE);
  478.  
  479.    NUMBER    : constant CHARACTER_TABLE := CHARACTER_TABLE'
  480.    ('0'..'9' | '_' | '.' => TRUE, others => FALSE);
  481.  
  482.    CURRENT_POSITION : LENGTH_TYPE := 1; -- the location of the current
  483.                                         -- character on the line, of the
  484.                                         -- input file
  485.  
  486.   ----------------------------------------------------------------------
  487.  
  488.    procedure GET_TOKEN (INPUT_FILE : FILE_TYPE;
  489.                         TOKEN      : in out STRING_RECORD) is
  490.  
  491.           ---------------------------------------------------------
  492.           --  This procedure is the meat of the package:  it is  --
  493.           --  a scanner that finds one token (TOKEN) in the      --
  494.           --  input file (INPUT_FILE), making sure that it does  --
  495.           --  not look ahead, or else characters will be lost.   --
  496.           ---------------------------------------------------------
  497.  
  498.       type STATE_TYPE is
  499.          (START_STATE, NUMBER_STATE, WORD_STATE, DELIMITER_STATE, FINAL_STATE);
  500.       PRESENT_STATE    : STATE_TYPE;      -- see explanation below
  501.       CHAR             : CHARACTER;
  502.       DOUBLE_PERIOD    : constant CHARACTER := CHARACTER'VAL (1); -- see below
  503.  
  504.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  505.  
  506.       procedure GET_CHAR (CH  : in out CHARACTER;
  507.                           INF : FILE_TYPE) is
  508.  
  509.                     ------------------------------------------
  510.                     --  This procedure gets one character   --
  511.                     --  from the input file (INF).          --
  512.                     ------------------------------------------
  513.  
  514.       begin
  515.          OS_DEPENDENCIES.GETC (INF, CH, CURRENT_POSITION);
  516.          if CH = END_OF_LINE then
  517.             CURRENT_POSITION := 1;
  518.  
  519. --        put ('.');
  520.  
  521.             if TOKEN.STR_ZERO = END_OF_LINE and TOKEN.LENGTH = 0 then
  522.                CH := BLANK_LINE;
  523.             end if;
  524.             if TOKEN.LENGTH = 0 then      -- This is to tell if a comment is
  525.                TOKEN.STR_ZERO := END_OF_LINE; -- on its own line (see the FORMAT
  526.             end if;                       -- _SUPPORT package for details).
  527.          end if;
  528.       exception
  529.          when END_ERROR =>
  530.             CH := CHARACTER'VAL (3);
  531.  
  532.          when others =>
  533.             PUT_LINE ("unexpected exception in GETTOKEN.GET_TOKEN.GET_CHAR");
  534.             raise;
  535.  
  536.       end GET_CHAR;
  537.  
  538.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  539.  
  540.       procedure ADD_ON (CH  : in out CHARACTER;
  541.                         ST  : in out STRING_RECORD;
  542.                         INF : FILE_TYPE) is
  543.  
  544.                     --------------------------------------------
  545.                     --  This procedure adds the character CH  --
  546.                     --  to the token string (ST), and calls   --
  547.                     --  GET_CHAR for the next character.      --
  548.                     --------------------------------------------
  549.  
  550.       begin
  551.          ST.LENGTH := ST.LENGTH + 1;
  552.          ST.STR (ST.LENGTH) := CH;
  553.          if CH = BLANK_LINE then
  554.             CH := END_OF_LINE;
  555.          else
  556.             GET_CHAR (CH, INF);
  557.          end if;
  558.       end ADD_ON;
  559.  
  560.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  561.  
  562.    begin    --  GET_TOKEN
  563.  
  564.       CHAR := TOKEN.STR_ZERO;    -- This one statement is the key to the whole
  565.                                  -- algorithm:  TOKEN.ST_ZERO holds the
  566.                                  -- character that stopped the algorithm the
  567.                                  -- last time it went through.  Otherwise,
  568.                                  -- that character would be lost.
  569.  
  570.       for I in 1 .. TOKEN.LENGTH + 1 loop
  571.          TOKEN.STR (I) := ' ';
  572.       end loop;
  573.       TOKEN.LENGTH := 0;
  574.  
  575.                                                 -- The basic algorithm is done
  576.       PRESENT_STATE := START_STATE;             -- by tracing through a state
  577.                                                 -- diagram.
  578.  
  579.       while PRESENT_STATE /= FINAL_STATE loop
  580.          case PRESENT_STATE is                  -- In Ada one can tell whether
  581.                                                 -- a token will be a delimiter,
  582.                                                 -- number, or word, just by
  583.                                                 -- looking at the first char.
  584.             when START_STATE =>
  585.                if DELIMITER (CHAR) then
  586.                   if CHAR /= BLANK_LINE then
  587.                      TOKEN.POSITION := CURRENT_POSITION - 1;
  588.                   end if;                       -- The position of a token is
  589.                   TOKEN.CLASS := DELIM;         -- going to be the position of
  590.                                                 -- the first character in that
  591.                                                 -- string, which is one less
  592.                                                 -- than the current position.
  593.                   PRESENT_STATE := DELIMITER_STATE;
  594.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  595.                elsif LETTER (CHAR) then
  596.                   TOKEN.POSITION := CURRENT_POSITION - 1;
  597.                   TOKEN.CLASS := WORD;
  598.                   PRESENT_STATE := WORD_STATE;
  599.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  600.                elsif NUMBER (CHAR) then
  601.                   TOKEN.POSITION := CURRENT_POSITION - 1;
  602.                   TOKEN.CLASS := NUM;
  603.                   PRESENT_STATE := NUMBER_STATE;
  604.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  605.                elsif CHAR = END_FILE then
  606.                   TOKEN.CLASS := END_OF_FILE;
  607.                   if TOKEN.STR_ZERO = END_FILE then -- If the procedure gets to
  608.                                                 -- this
  609.                      raise END_ERROR;           -- point (two end-of-file indi-
  610.                   end if;                       -- cators in a row), the program
  611.                                                 -- being scanned has an error in
  612.                                                 -- it somewhere, so an error is
  613.                   PRESENT_STATE := FINAL_STATE; -- propogated.
  614.                elsif CHAR = DOUBLE_PERIOD then         -- This is needed because
  615.                   TOKEN.STR (1 .. 2) := "..";          -- if the current token
  616.                   TOKEN.LENGTH := 2;                   -- is a number, then when
  617.                   GET_CHAR (CHAR, INPUT_FILE); -- it finds a period, it
  618.                   PRESENT_STATE := FINAL_STATE;        -- needs to look ahead to
  619.                                                        -- see if the next char-
  620.                                                        -- acter is a period or
  621.                                                        -- the rest of a decimal
  622.                                                        -- number.  This is the
  623.                                                        -- only time I could not
  624.                                                        -- work around the look-
  625.                                                        -- ahead requirement.
  626.                else  -- space or end-of-line
  627.                   GET_CHAR (CHAR, INPUT_FILE);
  628.                end if;
  629.  
  630.             when WORD_STATE =>
  631.  
  632.             --    word ::= letter {[under-score] letter|digit}
  633.  
  634.                if LETTER (CHAR) or else
  635.                   (NUMBER (CHAR) and CHAR /= '.')
  636.                then
  637.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  638.                else                          -- Please note that the algorithm
  639.                   PRESENT_STATE := FINAL_STATE;
  640.                                              -- does not check to make sure the
  641.                end if;                       -- under-scores are isolated, since
  642.                                              -- it is assumed that the program
  643.                                              -- being scanned is syntactically
  644.                                              -- correct.
  645.             when NUMBER_STATE =>
  646.  
  647.             --   number ::= decimal_number | based_number
  648.             --   decimal_number ::= integer [.integer] [E{+|-}integer]
  649.             --   integer ::= digit {[under-score] digit}   -- see note above
  650.             --   based_number ::= integer # GARBAGE # [E{+|-}integer]
  651.             --     GARBAGE ::= anything, for all I care.
  652.  
  653.                if NUMBER (CHAR) then
  654.                   if CHAR = '.' then
  655.                      GET_CHAR (CHAR, INPUT_FILE);
  656.                      if CHAR = '.' then     -- see explanation in START_STATE
  657.                         CHAR := DOUBLE_PERIOD;
  658.                         PRESENT_STATE := FINAL_STATE;
  659.                      else
  660.                         TOKEN.LENGTH := TOKEN.LENGTH + 1;
  661.                         TOKEN.STR (TOKEN.LENGTH) := '.';
  662.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  663.                      end if;
  664.                   else
  665.                      ADD_ON (CHAR, TOKEN, INPUT_FILE);
  666.                   end if;
  667.                elsif CHAR = '#' then                       -- based number
  668.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  669.                   while CHAR /= '#' loop
  670.                      ADD_ON (CHAR, TOKEN, INPUT_FILE);
  671.                   end loop;
  672.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  673.                elsif CHAR = 'E' then                       -- exponent
  674.                   ADD_ON (CHAR, TOKEN, INPUT_FILE);
  675.                   if CHAR = '+' or CHAR = '-' then
  676.                      ADD_ON (CHAR, TOKEN, INPUT_FILE);
  677.                   end if;
  678.                else
  679.                   PRESENT_STATE := FINAL_STATE;
  680.                end if;
  681.  
  682.             when DELIMITER_STATE =>         -- This part takes advantage of the
  683.                PRESENT_STATE := FINAL_STATE; -- fact that any delimiter can be
  684.                case TOKEN.STR (1) is        -- identified by looking at the
  685.                                             -- first two characters of the
  686.                                             -- string -- the one that was added
  687.                                             -- to the token already (T.STR(1)),
  688.                                             -- and the current character.
  689.                                             -- Again, nothing is lost.
  690.                   when '<' =>
  691.                      if CHAR = '=' or CHAR = '<' or CHAR = '>' then
  692.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  693.                      end if;
  694.  
  695.                   when '>' =>
  696.                      if CHAR = '=' or CHAR = '>' then
  697.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  698.                      end if;
  699.  
  700.                   when '=' =>
  701.                      if CHAR = '>' then
  702.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  703.                      end if;
  704.  
  705.                   when '/' | ':' =>
  706.                      if CHAR = '=' then
  707.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  708.                      end if;
  709.  
  710.                   when '*' =>
  711.                      if CHAR = '*' then
  712.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  713.                      end if;
  714.  
  715.                   when '.' =>
  716.                      if CHAR = '.' then
  717.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  718.                      end if;
  719.  
  720.                   when ''' =>  -- attribute indicator or character
  721.                      ADD_ON (CHAR, TOKEN, INPUT_FILE);
  722.                      if CHAR /= ''' then          -- fortunately, no attributes
  723.                                                   -- have < 3 characters.
  724.                         PRESENT_STATE := START_STATE;
  725.                      end if;                      -- Note that I cheated a bit
  726.                                                   -- here.  The algorithm will
  727.                                                   -- now go back, and recog-
  728.                                                   -- nize the token as a word,
  729.                                                   -- since the ' has been added
  730.                                                   -- to the token already.
  731.  
  732.                      ADD_ON (CHAR, TOKEN, INPUT_FILE);
  733.  
  734.                   when '-' =>
  735.                      if CHAR = '-' then
  736.                         TOKEN.CLASS := COMMENT;
  737.                         CURRENT_POSITION := CURRENT_POSITION - 1; --  #########
  738.                         while CHAR /= END_OF_LINE loop
  739.                            ADD_ON (CHAR, TOKEN, INPUT_FILE);
  740.                         end loop;
  741.                         TOKEN.STR (TOKEN.LENGTH + 1) := TOKEN.STR_ZERO;
  742.                           -- This tells
  743.                           -- the formatter if the comment is on its own line.
  744.                           -- See FORMAT_SUPPORT package for details.
  745.                      end if;
  746.  
  747.                   when '"' =>        -- string ::= " {anything} "
  748.                      while CHAR /= '"' loop
  749.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  750.                      end loop;
  751.                      ADD_ON (CHAR, TOKEN, INPUT_FILE);
  752.  
  753.                     -- All of this garbage is to take of double quotes inside
  754.                     -- strings, and null strings.
  755.  
  756.                      while CHAR = '"' loop
  757.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  758.                         while CHAR /= '"' loop
  759.                            ADD_ON (CHAR, TOKEN, INPUT_FILE);
  760.                         end loop;
  761.                         ADD_ON (CHAR, TOKEN, INPUT_FILE);
  762.                      end loop;
  763.  
  764.                   when others =>
  765.                      null;
  766.  
  767.                end case;
  768.  
  769.             when FINAL_STATE =>
  770.                null;
  771.  
  772.          end case;
  773.       end loop;
  774.       if TOKEN.CLASS = WORD then         -- Convert words to all upper-case
  775.          for I in 1 .. TOKEN.LENGTH loop
  776.             if CHARACTER'POS (TOKEN.STR (I)) in 97 .. 122 then
  777.                TOKEN.STR (I) :=
  778.                   CHARACTER'VAL (CHARACTER'POS (TOKEN.STR (I)) - 32);
  779.             end if;
  780.          end loop;
  781.       end if;
  782.       TOKEN.STR_ZERO := CHAR;    -- see first comment in this procedure
  783. --DEBUG put_line("token => (str_zero =>" &
  784. --DEBUG          integer'image(character'pos(token.str_zero)) & ", str => """ &
  785. --DEBUG          token.str(1..token.length) & """, length =>" &
  786. --DEBUG          length_type'image(token.length) & ", class => " &
  787. --DEBUG          class_type'image(token.class) & ", position =>" &
  788. --DEBUG          length_type'image(token.position) & ')' );
  789.    exception
  790.       when others =>
  791.          PUT_LINE ("unexpected exception in GETTOKEN.GET_TOKEN");
  792.          raise;
  793.  
  794.    end GET_TOKEN;
  795.  
  796.   ----------------------------------------------------------------------
  797.  
  798. begin     -- initializations
  799.    null;
  800.  
  801. end GETTOKEN;
  802.  
  803. --::::::::::
  804. --stubber.ada
  805. --::::::::::
  806. --                                                                    --
  807. --                        procedure STUBBER                           --
  808. --                                                                    --
  809. ------------------------------------------------------------------------
  810. ------------------------------------------------------------------------
  811.  
  812. with GETTOKEN; use  GETTOKEN;
  813. with STUBBER_SUPPORT; use  STUBBER_SUPPORT;
  814. with TEXT_IO; use  TEXT_IO;
  815. with OS_DEPENDENCIES;
  816.  
  817. procedure STUBBER is
  818.  
  819.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  820.   --                                                                  --
  821.   --    Procedure STUBBER is the main procedure for the STUBBER set   --
  822.   --    of packages.  It walks through the input file, one token at   --
  823.   --    a time, storing specifications as it finds them, and taking   --
  824.   --    care bodies, stubbing where necessary.                        --
  825.   --                                                                  --
  826.   --    All operating system dependencies, editor dependencies, and   --
  827.   --    a few compiler dependencies can be found in the file called   --
  828.   --    OS_DEPENDENCIES (that STUBBER_SUPPORT uses).                 --
  829.   --                                                                  --
  830.   --                    PACKAGE SET DEPENDENCE:                       --
  831.   --                                                                  --
  832.   --    >STUBBER                                                      --
  833.   --       |  |                                                       --
  834.   --       |  \___>STUBBER_SUPPORT                                    --
  835.   --       |         |   |                                            --
  836.   --       |         |   \_______________________>OS_DEPENDENCIES     --
  837.   --       |         |                     /                          --
  838.   --       |         \_________>GETTOKEN   |                          --
  839.   --       \______________/        \_______/                          --
  840.   --                                                                  --
  841.   --                                                                  --
  842.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  843.   --    Date  :  15 July 1983                                         --
  844.   --    Update:  4/28/87      J. Orost, CCUR                          --
  845.   --                                                                  --
  846.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  847.  
  848.           ---------------------------------------------------------
  849.           --  The stubber stubs anything in a program that needs --
  850.           --  to be stubbed.  It needs no assistance in deter-   --
  851.           --  mining what needs to be stubbed, and there is no   --
  852.           --  way of stopping it from stubbing everything that   --
  853.           --  needs to be stubbed.  It is imperative that the    --
  854.           --  program is syntactically correct to the point of   --
  855.           --  having all "if"s with matching "end if"s, etc.     --
  856.           --  Failure to follow this simple and straight-forward --
  857.           --  requirement may result in the stubber producing    --
  858.           --  garbage.                                           --
  859.           ---------------------------------------------------------
  860.  
  861.    SPECS      : DECLARATION_PTR;
  862.    NEWFILE_ID : GETTOKEN.STRING_RECORD;
  863.  
  864.   ----------------------------------------------------------------------
  865.  
  866.    function  FORMAL_PARTS_MATCH (FIRST_ONE,
  867.                                  SECOND_ONE : DECLARATION_PTR) return BOOLEAN is
  868.  
  869.           ---------------------------------------------------------
  870.           --  This function determines if the formal parts of    --
  871.           --  two declarations match.                            --
  872.           ---------------------------------------------------------
  873.  
  874.       FPM    : BOOLEAN := TRUE;
  875.       TEMP_1,
  876.       TEMP_2 : BUFFER_PTR;
  877.    begin
  878.       TEMP_1 := FIRST_ONE.FORMAL_PART;
  879.       TEMP_2 := SECOND_ONE.FORMAL_PART;
  880.       while TEMP_1 /= null and TEMP_2 /= null loop
  881.          if TEMP_1.BUFFER_STRING /= TEMP_2.BUFFER_STRING then
  882.             FPM := FALSE;
  883.             exit;                     -- Requirement 1:  all of the declarations
  884.          end if;                      -- of the one have to match that of the
  885.                                       -- other.
  886.  
  887.          TEMP_1 := TEMP_1.NEXT_ONE;
  888.          TEMP_2 := TEMP_2.NEXT_ONE;
  889.       end loop;
  890.       if TEMP_1 /= null or TEMP_2 /= null then
  891.          FPM := FALSE;                -- Requirment 2:  both have to have the
  892.       end if;                         -- same number of declarations in their
  893.                                       -- formal parts.
  894.  
  895.       return FPM;
  896.    exception
  897.       when others =>
  898.          PUT_LINE ("Unhandled exception in STUBBER.FORMAL_PARTS_MATCH");
  899.          raise;
  900.  
  901.    end FORMAL_PARTS_MATCH;
  902.  
  903.   ----------------------------------------------------------------------
  904.  
  905.    procedure DO_FORMAL_PART (CURRENT_DEC : in out DECLARATION_PTR) is
  906.  
  907.           ---------------------------------------------------------
  908.           --  This procedure creates the formal-part buffer for  --
  909.           --  a subprogram specification.                        --
  910.           ---------------------------------------------------------
  911.  
  912.       TEMP_DEC          : BUFFER_PTR;
  913.       PARENTHESIS_COUNT : GETTOKEN.LENGTH_TYPE := 1;  -- used to keep track of
  914.                                                       -- internal parentheses
  915.  
  916.       TEMP_INDENT       : LENGTH_TYPE := 1;    -- used to indent multiple
  917.                                                -- declarations inside the
  918.                                                -- formal part
  919.       FOUND_A_COLON     : BOOLEAN := FALSE;
  920.  
  921.    begin
  922.       -- 12 = "procedure "'LENGTH + " ("'LENGTH
  923.       if CURRENT_DEC.DEC_NAME.LENGTH + 12 <=
  924.          OS_DEPENDENCIES.OUTPUT_LINE_LENGTH then
  925.          TEMP_INDENT := CURRENT_DEC.DEC_NAME.LENGTH + 12;
  926.       end if;
  927.       if TOKEN.STR (1) = '(' then
  928.          CURRENT_DEC.FORMAL_PART := new BUFFER_TYPE;
  929.          CURRENT_DEC.FORMAL_PART.BUFFER_STRING.STR (1 .. 2) := " (";
  930.          CURRENT_DEC.FORMAL_PART.BUFFER_STRING.LENGTH := 2;
  931.          TEMP_DEC := CURRENT_DEC.FORMAL_PART;
  932.          GET_ONE_TOKEN;
  933.          while TOKEN.STR (1) /= ')' loop
  934.  
  935.           -- add tokens to the buffer string until a ")" or a ";" is found
  936.  
  937.             while PARENTHESIS_COUNT > 0 and TOKEN.STR (1) /= ';' loop
  938.                TEMP_DEC.BUFFER_STRING.STR
  939.                   (TEMP_DEC.BUFFER_STRING.LENGTH + 1 .. TEMP_DEC.
  940.                       BUFFER_STRING.LENGTH + TOKEN.LENGTH) :=
  941.                   TOKEN.STR (1 .. TOKEN.LENGTH);
  942.                if CONVERT (TOKEN) /= NOT_KW then
  943.                   --Convert keywords to lower case
  944.                   for I in TEMP_DEC.BUFFER_STRING.LENGTH + 1 ..
  945.                            TEMP_DEC.BUFFER_STRING.LENGTH + TOKEN.LENGTH loop
  946.                      TEMP_DEC.BUFFER_STRING.STR (I) := CHARACTER'VAL(
  947.                            CHARACTER'POS(TEMP_DEC.BUFFER_STRING.STR (I)) -
  948.                            CHARACTER'POS('A') + CHARACTER'POS('a')  );
  949.                   end loop;
  950.                end if;
  951.                TEMP_DEC.BUFFER_STRING.LENGTH :=
  952.                   TEMP_DEC.BUFFER_STRING.LENGTH + TOKEN.LENGTH;
  953.                if TOKEN.LENGTH = 1 and then
  954.                   (TOKEN.STR (1) = ''' or else
  955.                    TOKEN.STR (1) = '.' or else
  956.                    TOKEN.STR (1) = '(') then
  957.                   NULL;        --No space after ''', '.', or '('
  958.                else
  959.                   TEMP_DEC.BUFFER_STRING.LENGTH :=
  960.                      TEMP_DEC.BUFFER_STRING.LENGTH + 1;
  961.                   TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH)
  962.                     := ' ';
  963.                end if;
  964.                GET_ONE_TOKEN;
  965.                if (TOKEN.STR (1) = ''' and then TOKEN.LENGTH > 3) or else
  966.                   (TOKEN.LENGTH = 1 and then
  967.                    (TOKEN.STR (1) = ',' or else
  968.                     TOKEN.STR (1) = '.')) then
  969.                   --No space before ',', "'ATTRIB", or '.'
  970.                   TEMP_DEC.BUFFER_STRING.LENGTH :=
  971.                      TEMP_DEC.BUFFER_STRING.LENGTH - 1;
  972.                elsif TOKEN.STR (1) = '(' then
  973.                   PARENTHESIS_COUNT := PARENTHESIS_COUNT + 1;
  974.                elsif TOKEN.STR (1) = ')' then
  975.                   PARENTHESIS_COUNT := PARENTHESIS_COUNT - 1;
  976.                   --No space before ')'
  977.                   TEMP_DEC.BUFFER_STRING.LENGTH :=
  978.                      TEMP_DEC.BUFFER_STRING.LENGTH - 1;
  979.                elsif TOKEN.STR (1) = ':' then
  980.                   FOUND_A_COLON := TRUE;
  981.                end if;
  982.             end loop;
  983.             if TOKEN.STR (1) = ';' then   -- create a new buffer string
  984.                TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH) := ';'
  985.                   ;
  986.                GET_ONE_TOKEN;
  987.                TEMP_DEC.NEXT_ONE := new BUFFER_TYPE;
  988.                TEMP_DEC := TEMP_DEC.NEXT_ONE;
  989.                for I in 1 .. TEMP_INDENT loop
  990.                   TEMP_DEC.BUFFER_STRING.STR (I) := ' ';
  991.                end loop;
  992.                TEMP_DEC.BUFFER_STRING.LENGTH := TEMP_INDENT;
  993.             end if;
  994.          end loop;
  995.          TEMP_DEC.BUFFER_STRING.LENGTH := TEMP_DEC.BUFFER_STRING.LENGTH + 1;
  996.          TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH) := ')';
  997.          GET_ONE_TOKEN;
  998.          if CURRENT_DEC.TYPE_OF_DEC = KW_ENTRY and then
  999.             (TOKEN.STR (1) = '(' or else
  1000.              FOUND_A_COLON = FALSE) then     --Entry with discrete range
  1001.             --We save the discrete range in the RETURN_TYPE field
  1002.             --which is normally only used for FUNCTIONs
  1003.             CURRENT_DEC.RETURN_TYPE := CURRENT_DEC.FORMAL_PART.BUFFER_STRING;
  1004.             CURRENT_DEC.FORMAL_PART := null;
  1005.             DO_FORMAL_PART (CURRENT_DEC);  --now do the real formal_part
  1006.          end if;
  1007.       end if;
  1008.    exception
  1009.       when others =>
  1010.          PUT_LINE ("Unhandled exception in STUBBER.DO_FORMAL_PART");
  1011.          raise;
  1012.  
  1013.    end DO_FORMAL_PART;
  1014.  
  1015.   ----------------------------------------------------------------------
  1016.  
  1017.    procedure DO_SPEC (FIRST_SPEC : in out DECLARATION_PTR) is
  1018.  
  1019.           ---------------------------------------------------------
  1020.           --  This procedure is the meat of the STUBBER set of   --
  1021.           --  packages.  It walks through the input file, finds  --
  1022.           --  all of the package/subprogram specifications and   --
  1023.           --  bodies, and takes appropriate action.              --
  1024.           ---------------------------------------------------------
  1025.  
  1026.       CURRENT_SPEC,
  1027.       TEMP_SPEC     : DECLARATION_PTR;
  1028.       GOT_ONE_TOKEN : BOOLEAN := FALSE;
  1029.  
  1030.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1031.  
  1032.       procedure CLOSE_OFF (LOSING_SPEC,
  1033.                            MAIN_SPEC   : in out DECLARATION_PTR) is
  1034.  
  1035.                     ------------------------------------------
  1036.                     --  This procedure eliminates one spe-  --
  1037.                     --  cification (LOSING_SPEC) from a     --
  1038.                     --  linked list of specifications       --
  1039.                     --  (MAIN_SPEC).                        --
  1040.                     ------------------------------------------
  1041.  
  1042.          TEMP_DEC : DECLARATION_PTR;
  1043.       begin
  1044.          if LOSING_SPEC = MAIN_SPEC then      -- if the LOSING_SPEC is the first
  1045.             MAIN_SPEC := MAIN_SPEC.NEXT_DEC; -- spec in the linked list, then
  1046.                                             -- the pointer to the first spec now
  1047.                                            -- points to the second spec.
  1048.          else                                          -- Otherwise, TEMP_DEC
  1049.             TEMP_DEC := MAIN_SPEC;                     -- goes through the
  1050.             while TEMP_DEC.NEXT_DEC /= LOSING_SPEC loop -- list until it finds
  1051.                TEMP_DEC := TEMP_DEC.NEXT_DEC;          -- the spec that points
  1052.             end loop;                                  -- to LOSING_SPEC,
  1053.             TEMP_DEC.NEXT_DEC := LOSING_SPEC.NEXT_DEC; -- at which point, it is
  1054.          end if;                                      -- changed so that it now
  1055.                                                      -- points to what LOSING_
  1056.                                                     -- SPEC pointed to.
  1057.  
  1058.       exception
  1059.          when others =>
  1060.             PUT_LINE ("Unhandled exception in STUBBER.DO_SPEC.CLOSE_OFF");
  1061.             raise;
  1062.  
  1063.       end CLOSE_OFF;
  1064.  
  1065.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1066.  
  1067.       procedure FOUND_WORD_PACKAGE is
  1068.  
  1069.                     ------------------------------------------
  1070.                     --  This procedure, called when the re- --
  1071.                     --  served word "package" is found,     --
  1072.                     --  determines if the structure found   --
  1073.                     --  is a package body or package spec., --
  1074.                     --  and takes appropriate action.       --
  1075.                     ------------------------------------------
  1076.  
  1077.          DUMMY        : BUFFER_PTR;
  1078.          STRING_DUMMY : STRING_RECORD;
  1079.          IS_POSITION  : LENGTH_TYPE;
  1080.       begin
  1081.          CURRENT_SPEC.TYPE_OF_DEC := KW_PACKAGE;
  1082.          CURRENT_SPEC.PRIOR_TOKENS := SAVED_TOKENS;
  1083.          GET_ONE_TOKEN;
  1084.          if CONVERT (TOKEN) = KW_BODY then
  1085.             GET_ONE_TOKEN; -- id
  1086.             CURRENT_SPEC.DEC_NAME := TOKEN;
  1087.             GET_ONE_TOKEN; -- 'IS'
  1088.             if CONVERT (TOKEN) /= KW_SEPARATE then -- found a package body
  1089.                NEW_LINE;
  1090.                PUT ("Found package body ");
  1091.                PUT
  1092.                   (CURRENT_SPEC.DEC_NAME.STR (1 .. CURRENT_SPEC.DEC_NAME.LENGTH)
  1093.                       );
  1094.                TEMP_SPEC := FIRST_SPEC;
  1095.  
  1096.        -- search for a matching specification (EXACT match)
  1097.  
  1098.                while TEMP_SPEC.TYPE_OF_DEC /= CURRENT_SPEC.TYPE_OF_DEC or else
  1099.                   TEMP_SPEC.DEC_NAME.STR /= CURRENT_SPEC.DEC_NAME.STR
  1100.                loop
  1101.                   TEMP_SPEC := TEMP_SPEC.NEXT_DEC;
  1102.                end loop;
  1103.                if TEMP_SPEC = CURRENT_SPEC then -- no matching spec.
  1104.                   PUT (" (no matching spec.)");
  1105.                   TEMP_SPEC.INTERNAL_DECS := new DECLARATION_BUFF;
  1106.                else                            -- found matching spec.
  1107.                   PUT (" (with matching spec.)");
  1108.                   CLOSE_OFF (TEMP_SPEC, FIRST_SPEC); -- the spec is no
  1109.                                                      -- longer saved
  1110.                end if;
  1111.                DO_SPEC (TEMP_SPEC.INTERNAL_DECS);
  1112.                STUB (TEMP_SPEC.INTERNAL_DECS);
  1113.                if CONVERT (TOKEN) = KW_BEGIN then
  1114.                   GET_PAST_END;                  -- get through initializations
  1115.                end if;
  1116.             end if;     -- when a package body is found, there is no reason
  1117.                          -- to save anything, because all work has been done
  1118.                           -- on it, so a new storage buffer is not made.
  1119.          else
  1120.             CURRENT_SPEC.DEC_NAME := TOKEN;
  1121.             GET_ONE_TOKEN; -- 'IS' | 'RENAMES'
  1122.             if CONVERT (TOKEN) = KW_IS then
  1123.                IS_POSITION := TOKEN.POSITION;
  1124.                DUMMY := SAVED_TOKENS;        --flush out saved tokens
  1125.                GET_ONE_TOKEN;
  1126.                if CONVERT (TOKEN) /= KW_NEW then -- found package spec.
  1127.                   if SAVED_TOKENS_HEAD /= null and then
  1128.                      SAVED_TOKENS_HEAD.BUFFER_STRING.CLASS = COMMENT and then
  1129.                      SAVED_TOKENS_HEAD.BUFFER_STRING.POSITION > IS_POSITION then
  1130.                      --Grab following comment
  1131.                      CURRENT_SPEC.FOLLOW_TOKENS := SAVED_TOKENS;
  1132.                   end if;
  1133.                   NEW_LINE;
  1134.                   PUT ("Found package spec. ");
  1135.                   PUT
  1136.                      (CURRENT_SPEC.DEC_NAME.STR
  1137.                          (1 .. CURRENT_SPEC.DEC_NAME.LENGTH));
  1138.                   CURRENT_SPEC.INTERNAL_DECS := new DECLARATION_BUFF;
  1139.  
  1140.                   -- recursive call to save internal specifications
  1141.  
  1142.                   DO_SPEC (CURRENT_SPEC.INTERNAL_DECS);
  1143.                   -- end [<IDENTIFIER>] ;
  1144.                   while TOKEN.STR (1) /= ';' loop
  1145.                      GET_ONE_TOKEN;
  1146.                   end loop;
  1147.                   if CURRENT_SPEC.FOLLOW_TOKENS = null then
  1148.                      CURRENT_SPEC.FOLLOW_TOKENS := new BUFFER_TYPE'(
  1149.                                             STRING_DUMMY, SAVED_TOKENS);
  1150.                   else
  1151.                      CURRENT_SPEC.FOLLOW_TOKENS.NEXT_ONE := SAVED_TOKENS;
  1152.                   end if;
  1153.                   CURRENT_SPEC.NEXT_DEC := new DECLARATION_BUFF;
  1154.                   CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;
  1155.                end if;
  1156.             end if;
  1157.          end if;
  1158.       exception
  1159.          when others =>
  1160.             PUT_LINE ("Unhandled exception in " &
  1161.                       "STUBBER.DO_SPEC.FOUND_WORD_PACKAGE");
  1162.             raise;
  1163.  
  1164.       end FOUND_WORD_PACKAGE;
  1165.  
  1166.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1167.  
  1168.       procedure FOUND_SUBPROGRAM is
  1169.  
  1170.                     ------------------------------------------
  1171.                     --  This procedure, called when the re- --
  1172.                     --  served word "procedure", "function" --
  1173.                     --  or "entry" is found, it             --
  1174.                     --  determines if the structure is a    --
  1175.                     --  subprogram specification or body,   --
  1176.                     --  and takes appropriate action.       --
  1177.                     ------------------------------------------
  1178.  
  1179.          DUMMY         : BUFFER_PTR;
  1180.          SEMI_POSITION : LENGTH_TYPE;
  1181.  
  1182.          --Append STR to end of REC
  1183.          procedure APPEND (REC : in out STRING_RECORD; STR : in STRING) is
  1184.          begin
  1185.             REC.STR (REC.LENGTH + 1 .. REC.LENGTH + STR'LENGTH) := STR;
  1186.             REC.LENGTH := REC.LENGTH + STR'LENGTH;
  1187.          end APPEND;
  1188.  
  1189.       begin
  1190.  
  1191.             -- store everything, whether it'll be used or not
  1192.  
  1193.          CURRENT_SPEC.TYPE_OF_DEC := CONVERT (TOKEN);
  1194.          CURRENT_SPEC.PRIOR_TOKENS := SAVED_TOKENS;
  1195.          GET_ONE_TOKEN;  -- id
  1196.          CURRENT_SPEC.DEC_NAME := TOKEN;
  1197.          GET_ONE_TOKEN;
  1198.          DO_FORMAL_PART (CURRENT_SPEC);         -- process (...)
  1199.          if CURRENT_SPEC.TYPE_OF_DEC = KW_FUNCTION then
  1200.             GET_ONE_TOKEN; -- id
  1201.             CURRENT_SPEC.RETURN_TYPE := TOKEN;
  1202.             GET_ONE_TOKEN;
  1203.             while TOKEN.STR (1) = '.' loop    --Handle xxx.yyy.zzz
  1204.                APPEND (CURRENT_SPEC.RETURN_TYPE, ".");
  1205.                GET_ONE_TOKEN;
  1206.                APPEND (CURRENT_SPEC.RETURN_TYPE,
  1207.                        TOKEN.STR (1 .. TOKEN.LENGTH));
  1208.                GET_ONE_TOKEN;
  1209.             end loop;
  1210.          end if;
  1211.          if TOKEN.STR (1) = ';' then    -- found subprogram spec.
  1212.             SEMI_POSITION := TOKEN.POSITION;
  1213.             if TOKEN.STR_ZERO /= GETTOKEN.END_FILE then
  1214.                DUMMY := SAVED_TOKENS;      --clear saved tokens
  1215.                GET_ONE_TOKEN;
  1216.                if SAVED_TOKENS_HEAD /= null and then
  1217.                   SAVED_TOKENS_HEAD.BUFFER_STRING.CLASS = COMMENT and then
  1218.                   SAVED_TOKENS_HEAD.BUFFER_STRING.POSITION > SEMI_POSITION then
  1219.                   --Grab following comment
  1220.                   CURRENT_SPEC.FOLLOW_TOKENS := SAVED_TOKENS;
  1221.                end if;
  1222.                GOT_ONE_TOKEN := TRUE;
  1223.             end if;
  1224.             CURRENT_SPEC.NEXT_DEC := new DECLARATION_BUFF;  -- nothing to do
  1225.             CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;           -- but move on
  1226.          elsif CONVERT (TOKEN) = KW_IS then
  1227.             GET_ONE_TOKEN;
  1228.             if CONVERT (TOKEN) /= KW_NEW and CONVERT (TOKEN) /= KW_SEPARATE then
  1229.                -- found subprogram body
  1230.                NEW_LINE;
  1231.                PUT ("Found subprogram body ");
  1232.                PUT (CURRENT_SPEC.DEC_NAME.STR (1 ..
  1233.                       CURRENT_SPEC.DEC_NAME.LENGTH));
  1234.  
  1235.        -- check for matching spec.
  1236.  
  1237.                TEMP_SPEC := FIRST_SPEC;
  1238.                while TEMP_SPEC.TYPE_OF_DEC /= CURRENT_SPEC.TYPE_OF_DEC or else
  1239.                   TEMP_SPEC.DEC_NAME.STR /= CURRENT_SPEC.DEC_NAME.STR or else
  1240.                   TEMP_SPEC.RETURN_TYPE /= CURRENT_SPEC.RETURN_TYPE or else
  1241.                   not FORMAL_PARTS_MATCH (TEMP_SPEC, CURRENT_SPEC)
  1242.                loop
  1243.                   TEMP_SPEC := TEMP_SPEC.NEXT_DEC;
  1244.                end loop;
  1245.                if TEMP_SPEC = CURRENT_SPEC then
  1246.                   PUT (" (no matching spec)");
  1247.                else
  1248.                   PUT (" (with matching spec)");
  1249.                   CLOSE_OFF (TEMP_SPEC, FIRST_SPEC);
  1250.                end if;
  1251.                CURRENT_SPEC.INTERNAL_DECS := new DECLARATION_BUFF;
  1252.                DO_SPEC (CURRENT_SPEC.INTERNAL_DECS);
  1253.                STUB (CURRENT_SPEC.INTERNAL_DECS);
  1254.                GET_PAST_END;    -- get through the subprogram seq-of-stmts.
  1255.             end if;
  1256.          end if;           -- procedure bodies are never needed for future
  1257.                           -- reference and cannot be stubbed, so a new
  1258.                          -- storage location is not made.
  1259.       exception
  1260.          when others =>
  1261.             PUT_LINE ("Unhandled exception in " &
  1262.                       "STUBBER.DO_SPEC.FOUND_SUBPROGRAM");
  1263.             raise;
  1264.  
  1265.       end FOUND_SUBPROGRAM;
  1266.  
  1267.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1268.  
  1269.       procedure FOUND_INTERFACE is
  1270.  
  1271.                     ------------------------------------------
  1272.                     --  This procedure, called when the     --
  1273.                     --  sequence "pragma INTERFACE" is      --
  1274.                     --  found.  It eliminates the           --
  1275.                     --  corresponding subprogram            --
  1276.                     --  specification.                      --
  1277.                     ------------------------------------------
  1278.  
  1279.          MATCHES : INTEGER := 0;
  1280.       begin
  1281.  
  1282.          GET_ONE_TOKEN;  -- '('
  1283.          SAVE_ONE_TOKEN;
  1284.          GET_ONE_TOKEN;  -- language
  1285.          SAVE_ONE_TOKEN;
  1286.          GET_ONE_TOKEN;  -- ','
  1287.          SAVE_ONE_TOKEN;
  1288.          GET_ONE_TOKEN;  --id
  1289.          SAVE_ONE_TOKEN;
  1290.          NEW_LINE;
  1291.          PUT ("Found pragma interface ");
  1292.          PUT (TOKEN.STR (1 ..
  1293.                 TOKEN.LENGTH));
  1294.  
  1295.        -- check for matching spec.
  1296.  
  1297.          TEMP_SPEC := FIRST_SPEC;
  1298.          while TEMP_SPEC.NEXT_DEC /= null loop
  1299.             if TEMP_SPEC.DEC_NAME.STR = TOKEN.STR and then
  1300.                (TEMP_SPEC.TYPE_OF_DEC = KW_PROCEDURE or else
  1301.                 TEMP_SPEC.TYPE_OF_DEC = KW_FUNCTION) then
  1302.                CLOSE_OFF (TEMP_SPEC, FIRST_SPEC);
  1303.                MATCHES := MATCHES + 1;
  1304.             end if;
  1305.             TEMP_SPEC := TEMP_SPEC.NEXT_DEC;
  1306.          end loop;
  1307.          if MATCHES = 0 then
  1308.             PUT (" (no matching spec)");
  1309.          elsif MATCHES = 1 then
  1310.             PUT (" (with matching spec)");
  1311.          else
  1312.             PUT (" (with matching specs)");
  1313.          end if;
  1314.          GET_ONE_TOKEN;   -- ')'
  1315.          SAVE_ONE_TOKEN;
  1316.          GET_ONE_TOKEN;   -- ';'
  1317.          SAVE_ONE_TOKEN;
  1318.       exception
  1319.          when others =>
  1320.             PUT_LINE ("Unhandled exception in " &
  1321.                       "STUBBER.DO_SPEC.FOUND_INTERFACE");
  1322.             raise;
  1323.  
  1324.       end FOUND_INTERFACE;
  1325.  
  1326.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1327.  
  1328.       procedure FOUND_TASK is
  1329.  
  1330.                     ------------------------------------------
  1331.                     --  This procedure, called when the re- --
  1332.                     --  served word "task" is found,        --
  1333.                     --  determines if the structure found   --
  1334.                     --  is a task body or task spec.,       --
  1335.                     --  and takes appropriate action.       --
  1336.                     ------------------------------------------
  1337.  
  1338.          DUMMY        : BUFFER_PTR;
  1339.          STRING_DUMMY : STRING_RECORD;
  1340.          IS_POSITION  : LENGTH_TYPE;
  1341.       begin
  1342.          CURRENT_SPEC.TYPE_OF_DEC := KW_TASK;
  1343.          CURRENT_SPEC.PRIOR_TOKENS := SAVED_TOKENS;
  1344.          GET_ONE_TOKEN;
  1345.          if CONVERT (TOKEN) = KW_TYPE then
  1346.             GET_ONE_TOKEN; -- id
  1347.          end if;
  1348.          if CONVERT (TOKEN) = KW_BODY then
  1349.             GET_ONE_TOKEN; -- id
  1350.             CURRENT_SPEC.DEC_NAME := TOKEN;
  1351.             GET_ONE_TOKEN; -- 'IS'
  1352.             if CONVERT (TOKEN) /= KW_SEPARATE then -- found a task body
  1353.                NEW_LINE;
  1354.                PUT ("Found task body ");
  1355.                PUT
  1356.                   (CURRENT_SPEC.DEC_NAME.STR (1 .. CURRENT_SPEC.DEC_NAME.LENGTH)
  1357.                       );
  1358.                TEMP_SPEC := FIRST_SPEC;
  1359.  
  1360.        -- search for a matching specification (EXACT match)
  1361.  
  1362.                while TEMP_SPEC.TYPE_OF_DEC /= CURRENT_SPEC.TYPE_OF_DEC or else
  1363.                   TEMP_SPEC.DEC_NAME.STR /= CURRENT_SPEC.DEC_NAME.STR
  1364.                loop
  1365.                   TEMP_SPEC := TEMP_SPEC.NEXT_DEC;
  1366.                end loop;
  1367.                if TEMP_SPEC = CURRENT_SPEC then -- no matching spec.
  1368.                   PUT (" (no matching spec.)");
  1369.                   TEMP_SPEC.INTERNAL_DECS := new DECLARATION_BUFF;
  1370.                else                            -- found matching spec.
  1371.                   PUT (" (with matching spec.)");
  1372.                   CLOSE_OFF (TEMP_SPEC, FIRST_SPEC); -- the spec is no
  1373.                                                      -- longer saved
  1374.                end if;
  1375.                DO_SPEC (TEMP_SPEC.INTERNAL_DECS);
  1376.                STUB (TEMP_SPEC.INTERNAL_DECS);
  1377.                if CONVERT (TOKEN) = KW_BEGIN then
  1378.                   GET_PAST_END;                  -- get through initializations
  1379.                end if;
  1380.             end if;     -- when a task body is found, there is no reason
  1381.                          -- to save anything, because all work has been done
  1382.                           -- on it, so a new storage buffer is not made.
  1383.          else
  1384.             CURRENT_SPEC.DEC_NAME := TOKEN;
  1385.             GET_ONE_TOKEN; -- 'IS' | ';'
  1386.             IS_POSITION := TOKEN.POSITION;
  1387.             if CONVERT (TOKEN) = KW_IS then
  1388.                DUMMY := SAVED_TOKENS;      --clear saved tokens
  1389.                GET_ONE_TOKEN;
  1390.                if SAVED_TOKENS_HEAD /= null and then
  1391.                   SAVED_TOKENS_HEAD.BUFFER_STRING.CLASS = COMMENT and then
  1392.                   SAVED_TOKENS_HEAD.BUFFER_STRING.POSITION > IS_POSITION then
  1393.                   --Grab following comment
  1394.                   CURRENT_SPEC.FOLLOW_TOKENS := SAVED_TOKENS;
  1395.                end if;
  1396.                NEW_LINE;
  1397.                PUT ("Found task spec. ");
  1398.                PUT (CURRENT_SPEC.DEC_NAME.STR
  1399.                       (1 .. CURRENT_SPEC.DEC_NAME.LENGTH));
  1400.                CURRENT_SPEC.INTERNAL_DECS := new DECLARATION_BUFF;
  1401.  
  1402.                -- recursive call to save internal specifications
  1403.  
  1404.                DO_SPEC (CURRENT_SPEC.INTERNAL_DECS);
  1405.                -- end [<IDENTIFIER>] ;
  1406.                while TOKEN.STR (1) /= ';' loop
  1407.                   GET_ONE_TOKEN;
  1408.                end loop;
  1409.                if CURRENT_SPEC.FOLLOW_TOKENS = null then
  1410.                   CURRENT_SPEC.FOLLOW_TOKENS := new BUFFER_TYPE'(
  1411.                                          STRING_DUMMY, SAVED_TOKENS);
  1412.                else
  1413.                   CURRENT_SPEC.FOLLOW_TOKENS.NEXT_ONE := SAVED_TOKENS;
  1414.                end if;
  1415.                CURRENT_SPEC.NEXT_DEC := new DECLARATION_BUFF;
  1416.                CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;
  1417.             elsif TOKEN.STR (1) = ';' then
  1418.                if TOKEN.STR_ZERO /= GETTOKEN.END_FILE then
  1419.                   DUMMY := SAVED_TOKENS;      --clear saved tokens
  1420.                   GET_ONE_TOKEN;
  1421.                   if SAVED_TOKENS_HEAD /= null and then
  1422.                      SAVED_TOKENS_HEAD.BUFFER_STRING.CLASS = COMMENT and then
  1423.                      SAVED_TOKENS_HEAD.BUFFER_STRING.POSITION > IS_POSITION then
  1424.                      --Grab following comment
  1425.                      CURRENT_SPEC.FOLLOW_TOKENS := SAVED_TOKENS;
  1426.                   end if;
  1427.                   GOT_ONE_TOKEN := TRUE;
  1428.                end if;
  1429.                NEW_LINE;
  1430.                PUT ("Found task spec. ");
  1431.                PUT (CURRENT_SPEC.DEC_NAME.STR
  1432.                       (1 .. CURRENT_SPEC.DEC_NAME.LENGTH));
  1433.                CURRENT_SPEC.NEXT_DEC := new DECLARATION_BUFF;
  1434.                CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;
  1435.             end if;
  1436.          end if;
  1437.       exception
  1438.          when others =>
  1439.             PUT_LINE ("Unhandled exception in " &
  1440.                       "STUBBER.DO_SPEC.FOUND_TASK");
  1441.             raise;
  1442.  
  1443.       end FOUND_TASK;
  1444.  
  1445.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1446.  
  1447.    begin    -- DO_SPEC
  1448.       CURRENT_SPEC := FIRST_SPEC;
  1449.       while CURRENT_SPEC.NEXT_DEC /= null loop   -- see main procedure
  1450.          CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;  -- for explanation of
  1451.       end loop;                                  -- the basic logic
  1452.       while TOKEN.STR_ZERO /= GETTOKEN.END_FILE and CONVERT (TOKEN) /= KW_END
  1453.          and CONVERT (TOKEN) /= KW_BEGIN
  1454.       loop
  1455.          case CONVERT (TOKEN) is
  1456.             when KW_PACKAGE =>
  1457.                FOUND_WORD_PACKAGE;
  1458.  
  1459.             when KW_PROCEDURE | KW_FUNCTION | KW_ENTRY =>
  1460.                FOUND_SUBPROGRAM;
  1461.  
  1462.             when KW_TASK =>
  1463.                FOUND_TASK;
  1464.  
  1465.             when KW_PRAGMA =>
  1466.                SAVE_ONE_TOKEN;
  1467.                GET_ONE_TOKEN;
  1468.                SAVE_ONE_TOKEN;
  1469.                if TOKEN.STR (1 .. TOKEN.LENGTH) = "INTERFACE" then
  1470.                   FOUND_INTERFACE;
  1471.                end if;
  1472.  
  1473.             when KW_TYPE =>    -- find records, and get past the "end record",
  1474.                                -- so that the "end" of a record does not get
  1475.                                -- me out of this procedure
  1476.                SAVE_ONE_TOKEN;
  1477.                while CONVERT (TOKEN) /= KW_IS and TOKEN.STR (1) /= ';' loop
  1478.                   GET_ONE_TOKEN;
  1479.                   SAVE_ONE_TOKEN;
  1480.                   if TOKEN.STR (1) = '(' then
  1481.                      while TOKEN.STR (1) /= ')' loop
  1482.                         GET_ONE_TOKEN;
  1483.                         SAVE_ONE_TOKEN;
  1484.                      end loop;
  1485.                   end if;
  1486.                end loop;
  1487.                if CONVERT (TOKEN) = KW_IS then
  1488.                   GET_ONE_TOKEN;
  1489.                   SAVE_ONE_TOKEN;
  1490.                   if CONVERT (TOKEN) = KW_RECORD then
  1491.                      GET_PAST_END;
  1492.                   end if;
  1493.                end if;
  1494.  
  1495.             when KW_FOR =>     -- find representation records, and get past
  1496.                                -- the "end record"
  1497.                SAVE_ONE_TOKEN;
  1498.                while CONVERT (TOKEN) /= KW_USE loop
  1499.                   GET_ONE_TOKEN;
  1500.                   SAVE_ONE_TOKEN;
  1501.                end loop;
  1502.                GET_ONE_TOKEN;
  1503.                SAVE_ONE_TOKEN;
  1504.                if CONVERT (TOKEN) = KW_RECORD then
  1505.                   GET_PAST_END;
  1506.                end if;
  1507.  
  1508.             when KW_WITH =>        --Handle "with function"
  1509.                SAVE_ONE_TOKEN;     --and    "with procedure"
  1510.                GET_ONE_TOKEN;      --by ignoring the token following "with"
  1511.                SAVE_ONE_TOKEN;
  1512.  
  1513.             when others =>
  1514.                SAVE_ONE_TOKEN;
  1515.  
  1516.          end case;
  1517.       exit when TOKEN.STR_ZERO = GETTOKEN.END_FILE;
  1518.          if not GOT_ONE_TOKEN then
  1519.             GET_ONE_TOKEN;  -- anything
  1520.          else
  1521.             GOT_ONE_TOKEN := FALSE;
  1522.          end if;
  1523.       end loop;
  1524.       CURRENT_SPEC := null;
  1525.    exception
  1526.       when others =>
  1527.          PUT_LINE ("Unhandled exception in STUBBER.DO_SPEC");
  1528.          raise;
  1529.  
  1530.    end DO_SPEC;
  1531.  
  1532.   ----------------------------------------------------------------------
  1533.  
  1534. begin     -- stubber
  1535.    INITIALIZE (NEWFILE_ID);
  1536.    GET_ONE_TOKEN;
  1537.    SPECS := new DECLARATION_BUFF;
  1538.  
  1539.     -- At this point, let me try to explain the system I used.  Every-
  1540.     -- thing revolves around the data structure, "DECLARATION_BUFF" (I
  1541.     -- hope that you are now grabbing the package "STUBBER_SUPPORT",
  1542.     -- which contains the type declaration, so that you can follow what
  1543.     -- I am about to say).  All declaration buffers have two pointers
  1544.     -- to other declaration buffers:  INTERNAL_DECS points to the first
  1545.     -- of those declarations which are one lexical level inside the dec-
  1546.     -- laration being looked at.  In other words, if a given declaration
  1547.     -- buffer is for a package specification, INTERNAL_DECS points to the
  1548.     -- first package/subprogram specification found within that package
  1549.     -- specification.  NEXT_DEC points to the next declaration on the same
  1550.     -- lexical level as the given declaration.  PRIOR_TOKENS points to a
  1551.     -- list of comments and declarative tokens that precede this
  1552.     -- declaration.  They are output as comments.  FOLLOW_TOKENS points to a
  1553.     -- list of comments and declarative tokens, the first being the comment
  1554.     -- immediately following the ";" or "is", and the rest are preceding the
  1555.     -- "end".  RETURN_TYPE contains the function return type for function,
  1556.     -- or the entry_family declaration for entries.  Still confused?  Well,
  1557.     -- let's walk through an example.  Since package STUBBER_SUPPORT is already
  1558.     -- right there in front of you we'll use it.  When the word "package"
  1559.     -- is found by procedure DO_SPEC, it calls FOUND_WORD_PACKAGE.  This
  1560.     -- procedure will determine that it found a package specification, and
  1561.     -- get ready to accept specifications inside package STUBBER_SUPPORT
  1562.     -- by creating a new declaration storage buffer, and pointing to it with
  1563.     -- its INTERNAL_DECS buffer.  Then DO_SPEC will be called recursively,
  1564.     -- to start a new set (horizontally speaking) of specifications.
  1565.     -- When it gets to the function CONVERT declaration, it saves it by
  1566.     -- creating a new storage location, pointing to it with its NEXT_DEC
  1567.     -- pointer, and moving to the new storage buffer.  When DO_SPEC reaches
  1568.     -- the word "end", it will leave the procedure, which will take us back
  1569.     -- to where it was called in FOUND_PACKAGE, which, in turn, will save
  1570.     -- everything by creating a new storage buffer, pointing to it with its
  1571.     -- NEXT_DEC pointer, and moving to the new storage buffer.  still con-
  1572.     -- fused?  Reread this paragraph.  STILL confused?  Tough.
  1573.  
  1574.     -- SAVE_ONE_TOKEN is used to collect the PRIOR_TOKENS and FOLLOW_TOKENS.
  1575.  
  1576.    DO_SPEC (SPECS);
  1577.                               -- the main procedure just initiates the
  1578.    STUB (SPECS);              -- pointers, calls DO_SPEC, and calls STUB
  1579.                               -- to stub anything left.
  1580.    DUMP (NEWFILE_ID);
  1581. exception
  1582.    when others =>
  1583.       PUT_LINE ("Unhandled exception in STUBBER");
  1584.       raise;
  1585.  
  1586. end STUBBER;
  1587.  
  1588. --::::::::::
  1589. --stubsup.ada
  1590. --::::::::::
  1591. --                     package STUBBER_SUPPORT                        --
  1592. --                                                                    --
  1593. ------------------------------------------------------------------------
  1594. ------------------------------------------------------------------------
  1595.  
  1596. with TEXT_IO;
  1597. use  TEXT_IO;
  1598. with GETTOKEN;
  1599. use  GETTOKEN;
  1600.  
  1601. package STUBBER_SUPPORT is
  1602.  
  1603.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  1604.   --                                                                  --
  1605.   --    Package STUBBER_SUPPORT is the support package for package    --
  1606.   --    STUBBER (You wouldn't have guessed that by the title, now,    --
  1607.   --    would you?).  It contains the procedures that initialize &    --
  1608.   --    finalize things and the procedures that do the interaction    --
  1609.   --    with the input_file.                                          --
  1610.   --                                                                  --
  1611.   --    All of the peculiarities that are due to the editor or the    --
  1612.   --    filer have been moved to the OS_DEPENDENCIES package.         --
  1613.   --                                                                  --
  1614.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  1615.   --    Date  :  15 July 1983                                         --
  1616.   --    Update:  4/28/87, Joseph M. Orost, Concurrent Computer Corp.  --
  1617.   --                                                                  --
  1618.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  1619.  
  1620.    type KEY_WORDS is
  1621.       (KW_ABORT    , KW_ABS      , KW_ACCEPT   , KW_ACCESS   , KW_ALL      ,
  1622.        KW_AND      , KW_ARRAY    , KW_AT       , KW_BEGIN    , KW_BODY     ,
  1623.        KW_CASE     , KW_CONSTANT , KW_DECLARE  , KW_DELAY    , KW_DELTA    ,
  1624.        KW_DIGITS   , KW_DO       , KW_ELSE     , KW_ELSIF    , KW_END      ,
  1625.        KW_PRIVATE  , KW_EXCEPTION, KW_EXIT     , KW_FOR      , KW_PRAGMA   ,
  1626.        KW_GENERIC  , KW_GOTO     , KW_IF       , KW_IN       , KW_IS       ,
  1627.        KW_LIMITED  , KW_LOOP     , KW_MOD      , KW_NEW      , KW_NOT      ,
  1628.        KW_NULL     , KW_OF       , KW_OR       , KW_OTHERS   , KW_OUT      ,
  1629.        KW_PACKAGE  , KW_FUNCTION , KW_PROCEDURE, KW_ENTRY    , KW_TASK     ,
  1630.        KW_RANGE    , KW_RECORD   , KW_REM      , KW_RENAMES  , KW_RETURN   ,
  1631.        KW_REVERSE  , KW_SELECT   , KW_SEPARATE , KW_SUBTYPE  , KW_RAISE    ,
  1632.        KW_TERMINATE, KW_THEN     , KW_TYPE     , KW_USE      , KW_WHEN     ,
  1633.        KW_WHILE    , KW_WITH     , KW_XOR      , NOT_KW      );
  1634.  
  1635.    type BUFFER_TYPE;
  1636.  
  1637.    type BUFFER_PTR is access BUFFER_TYPE;
  1638.  
  1639.    type BUFFER_TYPE is
  1640.       record
  1641.          BUFFER_STRING : GETTOKEN.STRING_RECORD;
  1642.          NEXT_ONE      : BUFFER_PTR := null;
  1643.       end record;
  1644.  
  1645.    subtype DEC_TYPE is KEY_WORDS range KW_PACKAGE .. KW_TASK;
  1646.  
  1647.    type DECLARATION_BUFF;
  1648.  
  1649.    type DECLARATION_PTR is access DECLARATION_BUFF;
  1650.  
  1651.    type DECLARATION_BUFF is
  1652.       record
  1653.          TYPE_OF_DEC   : DEC_TYPE;
  1654.          DEC_NAME      : STRING_RECORD;
  1655.          FORMAL_PART   : BUFFER_PTR := null;    -- not used for packages
  1656.          RETURN_TYPE   : STRING_RECORD;        -- used only for functions
  1657.          INTERNAL_DECS : DECLARATION_PTR := null;
  1658.          NEXT_DEC      : DECLARATION_PTR := null; -- I explain all of this
  1659.          PRIOR_TOKENS  : BUFFER_PTR := null;
  1660.          FOLLOW_TOKENS : BUFFER_PTR := null;
  1661.       end record;                               -- nonsense in STUBBER.
  1662.  
  1663.    TOKEN       : STRING_RECORD;
  1664.    INPUT_FILE  : FILE_TYPE;
  1665.    OUTPUT_FILE : FILE_TYPE;
  1666.  
  1667.    function  CONVERT (STR1 : STRING_RECORD) return KEY_WORDS;
  1668.  
  1669.    procedure GET_ONE_TOKEN;
  1670.  
  1671.    SAVED_TOKENS_HEAD       : BUFFER_PTR := null;
  1672.    SAVED_TOKENS_TAIL       : BUFFER_PTR := null;
  1673.  
  1674.    procedure SAVE_ONE_TOKEN;
  1675.  
  1676.    function  SAVED_TOKENS return BUFFER_PTR;
  1677.  
  1678.    procedure INITIALIZE (OUTFILE_ID : out STRING_RECORD);
  1679.  
  1680.    procedure DUMP (FILE_ID : STRING_RECORD);
  1681.  
  1682.    procedure STUB (SPECIFICATION : DECLARATION_PTR);
  1683.  
  1684.    procedure GET_PAST_END;
  1685.  
  1686. end STUBBER_SUPPORT;
  1687.  
  1688. ------------------------------------------------------------------------
  1689. ------------------- package body STUBBER_SUPPORT -----------------------
  1690. ------------------------------------------------------------------------
  1691.  
  1692. with OS_DEPENDENCIES;
  1693. use  OS_DEPENDENCIES;
  1694.  
  1695. package body STUBBER_SUPPORT is
  1696.    use  OS_FILE_OPS;
  1697.  
  1698.    package INT_IO is new INTEGER_IO (INTEGER);
  1699.    use INT_IO;
  1700.  
  1701.    type KWP is access STRING;
  1702.  
  1703.    KW                      : array (KEY_WORDS) of KWP;
  1704.  
  1705.    FIRST_TIME_THROUGH_STUB : BOOLEAN;
  1706.    OUTER_DECLARATION       : DECLARATION_PTR;
  1707.    REAL_INDENT, INDENT     : INTEGER;
  1708.  
  1709.    SPACES                  : constant STRING(1..256) := (1..256 => ' ');
  1710.   ----------------------------------------------------------------------
  1711.  
  1712.    procedure GET_ONE_TOKEN is
  1713.  
  1714.           ---------------------------------------------------------
  1715.           --  This procedure gets one token from the input file, --
  1716.           --  making sure that it is not a comment or a blank    --
  1717.           --  line (which would mix up the stubber itself).      --
  1718.           ---------------------------------------------------------
  1719.  
  1720.    begin
  1721.       GET_TOKEN (INPUT_FILE, TOKEN);  -- not much to it; just a call to
  1722.                                       -- GET_TOKEN until its not a comment
  1723.                                       -- or a blank line
  1724.  
  1725.       while TOKEN.CLASS = COMMENT or TOKEN.STR (1) = GETTOKEN.BLANK_LINE loop
  1726.          SAVE_ONE_TOKEN;
  1727.          GET_TOKEN (INPUT_FILE, TOKEN);
  1728.       end loop;
  1729.    end GET_ONE_TOKEN;
  1730.  
  1731.    procedure SAVE_ONE_TOKEN is
  1732.       TOKEN_BUFFER : BUFFER_PTR := new BUFFER_TYPE'(TOKEN, null);
  1733.    begin
  1734.       if SAVED_TOKENS_TAIL = null then
  1735.          SAVED_TOKENS_TAIL := TOKEN_BUFFER;
  1736.          SAVED_TOKENS_HEAD := TOKEN_BUFFER;
  1737.       else
  1738.          SAVED_TOKENS_TAIL.NEXT_ONE := TOKEN_BUFFER;
  1739.          SAVED_TOKENS_TAIL := TOKEN_BUFFER;
  1740.       end if;
  1741.    end SAVE_ONE_TOKEN;
  1742.  
  1743.   ----------------------------------------------------------------------
  1744.  
  1745.    function  SAVED_TOKENS return BUFFER_PTR is
  1746.       RESULT : BUFFER_PTR := SAVED_TOKENS_HEAD;
  1747.    begin
  1748.       SAVED_TOKENS_HEAD := null;
  1749.       SAVED_TOKENS_TAIL := null;
  1750.       return RESULT;
  1751.    end SAVED_TOKENS;
  1752.  
  1753.   ----------------------------------------------------------------------
  1754.  
  1755.    procedure INITIALIZE (OUTFILE_ID : out STRING_RECORD) is
  1756.  
  1757.           ---------------------------------------------------------
  1758.           --  This procedure sets everything up for the STUBBER  --
  1759.           --  procedure.  It saves the name of the input file    --
  1760.           --  for future reference (OUTFILE_ID).                 --
  1761.           ---------------------------------------------------------
  1762.  
  1763.    begin
  1764.       NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE;
  1765.       NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE;
  1766.       PUT_LINE ("                           STUBBER");
  1767.       NEW_LINE;
  1768.       PUT_LINE ("This program stubs anything in your program that needs to be");
  1769.       PUT_LINE ("stubbed.  You need do nothing to tell the stubber what needs");
  1770.       PUT_LINE ("to be stubbed; it figures it out by itself. It is imperative");
  1771.       PUT_LINE ("that the program being stubbed is syntactically correct,  at");
  1772.       PUT_LINE ("least to the point that each 'if' has and 'end if', etc.  If");
  1773.       PUT_LINE ("this is not the case, then the stubber will self-destruct or");
  1774.       PUT_LINE ("worse than that, it will miss-stub your program.  This stub-");
  1775.       PUT_LINE ("ber will also keep you informed as to where it is and what's");
  1776.       PUT_LINE ("being stubbed.");
  1777.       NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE; NEW_LINE;
  1778.  
  1779.       loop
  1780.          begin
  1781.             declare
  1782.                FILENAME : constant STRING := GET_FILENAME;
  1783.             begin
  1784.                begin
  1785.                   OS_FILE_OPS.OPEN (INPUT_FILE, FILENAME);
  1786.                exception
  1787.                   when NAME_ERROR =>
  1788.                      PUT_LINE ("Cannot open " & FILENAME);
  1789.                      raise;
  1790.                end;
  1791.                OS_FILE_OPS.CREATE (OUTPUT_FILE, FILENAME);
  1792.  
  1793.                declare
  1794.                   NAME : constant STRING := TEXT_IO.NAME (OUTPUT_FILE);
  1795.                begin
  1796.                   OUTFILE_ID.LENGTH := NAME'LENGTH;
  1797.                   OUTFILE_ID.STR (NAME'RANGE) := NAME;
  1798.                end;
  1799.             end;
  1800.        exit;
  1801.          exception
  1802.             when NAME_ERROR =>
  1803.                null;
  1804.          end;
  1805.       end loop;
  1806.       TOKEN.LENGTH := STRING_LENGTH - 1;       -- this will force a blank-out
  1807.       TOKEN.STR_ZERO := GETTOKEN.END_OF_LINE;
  1808.    exception
  1809.       when others =>
  1810.          PUT_LINE ("Unhandled exception in STUBBER_SUPPORT.INITIALIZE");
  1811.          raise;
  1812.  
  1813.    end INITIALIZE;
  1814.  
  1815.   ----------------------------------------------------------------------
  1816.  
  1817.    procedure DUMP (FILE_ID : STRING_RECORD) is
  1818.  
  1819.           ---------------------------------------------------------
  1820.           --  This procedure finishes everything up.  It is the  --
  1821.           --  epitome of making procedures for the sole purpose  --
  1822.           --  of modularization.                                 --
  1823.           ---------------------------------------------------------
  1824.  
  1825.    begin
  1826.       NEW_LINE; NEW_LINE;
  1827.       PUT ("Your stubbed version is under ");
  1828.       PUT_LINE (FILE_ID.STR (1 .. FILE_ID.LENGTH));
  1829.  
  1830.       CLOSE (OUTPUT_FILE);
  1831.    end DUMP;
  1832.  
  1833.   ----------------------------------------------------------------------
  1834.  
  1835.    procedure STUB (SPECIFICATION : DECLARATION_PTR) is
  1836.  
  1837.           ---------------------------------------------------------
  1838.           --  This procedure is the actual stub generator. Given --
  1839.           --  a specification, or set of specifications, as de-  --
  1840.           --  termined by SPECIFICATION, the procedure will      --
  1841.           --  generate the appropriate stub.                     --
  1842.           ---------------------------------------------------------
  1843.  
  1844.       CURRENT_DEC      : DECLARATION_PTR;
  1845.       CURRENT_BUFF     : BUFFER_PTR;
  1846.       RETURN_TYPE_SAVE : STRING_RECORD;
  1847.  
  1848.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1849.  
  1850.       procedure WRITE_ID (FILE : FILE_TYPE;
  1851.                           ID   : in STRING_RECORD) is
  1852.  
  1853.                     ------------------------------------------
  1854.                     --  This procedure writes out an iden-  --
  1855.                     --  tifier when it is in a string.  It  --
  1856.                     --  is necessary for the case of over-  --
  1857.                     --  loaded operators, that have a '"'   --
  1858.                     --  as part of the name, so this has to --
  1859.                     --  be taken care of.                   --
  1860.                     ------------------------------------------
  1861.  
  1862.       begin
  1863.          if ID.STR (1) = '"' then
  1864.             PUT (FILE, '"');
  1865.             PUT (FILE, ID.STR (1 .. ID.LENGTH));
  1866.             PUT (FILE, '"');
  1867.          else
  1868.             PUT (FILE, ID.STR (1 .. ID.LENGTH));
  1869.          end if;
  1870.       end WRITE_ID;
  1871.  
  1872.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1873.  
  1874.       procedure PUT_SPACES (FILE : FILE_TYPE; AMOUNT : INTEGER) is
  1875.       begin
  1876.          PUT (FILE, SPACES(1 .. AMOUNT));
  1877.       end PUT_SPACES;
  1878.  
  1879.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1880.  
  1881.       procedure PUT_INDENT (FILE : FILE_TYPE; ITEM : STRING := "") is
  1882.       begin
  1883.          PUT_SPACES (FILE, INDENT);
  1884.          PUT (FILE, ITEM);
  1885.       end PUT_INDENT;
  1886.  
  1887.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1888.  
  1889.       function IS_ROOM (FILE : FILE_TYPE; LENGTH : NATURAL) return
  1890.          BOOLEAN is
  1891.       begin
  1892.          if INTEGER (COL (FILE)) + LENGTH > OUTPUT_LINE_LENGTH then
  1893.             NEW_LINE (FILE);
  1894.             if INDENT + LENGTH <= OUTPUT_LINE_LENGTH then
  1895.                PUT_INDENT (FILE);
  1896.             end if;
  1897.             return FALSE;
  1898.          end if;
  1899.          return TRUE;
  1900.       end IS_ROOM;
  1901.  
  1902.       procedure MAKE_ROOM (FILE : FILE_TYPE; LENGTH : NATURAL) is
  1903.          DUMMY : BOOLEAN;
  1904.       begin
  1905.          DUMMY := IS_ROOM (FILE, LENGTH);
  1906.       end MAKE_ROOM;
  1907.  
  1908.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1909.  
  1910.       procedure DO_PRIOR_TOKENS (CUR : in out BUFFER_PTR) is
  1911.          NEW_LINE_COL : INTEGER;
  1912.       begin
  1913.          while CUR /= null loop
  1914.             if CUR.BUFFER_STRING.CLASS = COMMENT then
  1915.                PUT_SPACES (OUTPUT_FILE, CUR.BUFFER_STRING.POSITION - 1);
  1916.                PUT_LINE (OUTPUT_FILE, CUR.BUFFER_STRING.STR (1 ..
  1917.                                           CUR.BUFFER_STRING.LENGTH));
  1918.             elsif CUR.BUFFER_STRING.STR (1) = GETTOKEN.BLANK_LINE then
  1919.                NEW_LINE (OUTPUT_FILE);
  1920.             else
  1921.                NEW_LINE_COL := 0;
  1922.                PUT (OUTPUT_FILE, "--");
  1923.                while CUR.BUFFER_STRING.STR (1) /= GETTOKEN.END_OF_LINE loop
  1924.                   if CUR.BUFFER_STRING.POSITION + 2 +
  1925.                      CUR.BUFFER_STRING.LENGTH - 1 - NEW_LINE_COL >
  1926.                      OUTPUT_LINE_LENGTH then
  1927.                      NEW_LINE_COL := CUR.BUFFER_STRING.POSITION - 2;
  1928.                      NEW_LINE (OUTPUT_FILE);
  1929.                      PUT (OUTPUT_FILE, "--");
  1930.                   end if;
  1931.                   PUT_SPACES (OUTPUT_FILE,
  1932.                               CUR.BUFFER_STRING.POSITION + 2 -
  1933.                               (INTEGER(COL(OUTPUT_FILE))+NEW_LINE_COL));
  1934.                   if CUR.BUFFER_STRING.CLASS = WORD and then
  1935.                      CONVERT (CUR.BUFFER_STRING) /= NOT_KW then
  1936.                      --Output keywords in lower case
  1937.                      for I in 1..CUR.BUFFER_STRING.LENGTH loop
  1938.                         PUT (OUTPUT_FILE, CHARACTER'VAL(
  1939.                              CHARACTER'POS(CUR.BUFFER_STRING.STR (I)) -
  1940.                              CHARACTER'POS('A') + CHARACTER'POS('a')));
  1941.                      end loop;
  1942.                   else
  1943.                      PUT (OUTPUT_FILE, CUR.BUFFER_STRING.STR (1 ..
  1944.                                            CUR.BUFFER_STRING.LENGTH));
  1945.                   end if;
  1946.                exit when CUR.BUFFER_STRING.STR_ZERO = GETTOKEN.END_OF_LINE;
  1947.                   CUR := CUR.NEXT_ONE;
  1948.                exit when CUR = null;
  1949.                   if CUR.BUFFER_STRING.STR (1) = GETTOKEN.BLANK_LINE then
  1950.                      NEW_LINE (OUTPUT_FILE);
  1951.                exit;
  1952.                   end if;
  1953.                end loop;
  1954.                NEW_LINE (OUTPUT_FILE);
  1955.             end if;
  1956.          exit when CUR = null;
  1957.             CUR := CUR.NEXT_ONE;
  1958.          exit when CUR = null;
  1959.          end loop;
  1960.       end DO_PRIOR_TOKENS;
  1961.  
  1962.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1963.  
  1964.       procedure DO_FOLLOW_TOKEN (SPECIFICATION : DECLARATION_PTR) is
  1965.          CUR  : BUFFER_PTR := SPECIFICATION.FOLLOW_TOKENS;
  1966.          COUNT : INTEGER;
  1967.       begin
  1968.          if CUR /= null and then CUR.BUFFER_STRING.LENGTH /= 0 then
  1969.             COUNT := CUR.BUFFER_STRING.POSITION - INTEGER (COL (OUTPUT_FILE));
  1970.             if COUNT <= 0 then
  1971.                COUNT := 1;
  1972.             end if;
  1973.             if COUNT + CUR.BUFFER_STRING.LENGTH <= OUTPUT_LINE_LENGTH then
  1974.                PUT_SPACES (OUTPUT_FILE, COUNT);
  1975.             else
  1976.                PUT (OUTPUT_FILE, ' ');
  1977.                MAKE_ROOM (OUTPUT_FILE, CUR.BUFFER_STRING.LENGTH);
  1978.             end if;
  1979.             PUT_LINE (OUTPUT_FILE, CUR.BUFFER_STRING.STR (1 ..
  1980.                                        CUR.BUFFER_STRING.LENGTH));
  1981.             SPECIFICATION.FOLLOW_TOKENS := SPECIFICATION.FOLLOW_TOKENS.NEXT_ONE;
  1982.          else
  1983.             NEW_LINE (OUTPUT_FILE);
  1984.          end if;
  1985.       end DO_FOLLOW_TOKEN;
  1986.  
  1987.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1988.  
  1989.       procedure ENTER_INDENT is
  1990.       begin
  1991.          REAL_INDENT := REAL_INDENT + INDENT_AMOUNT;
  1992.          if REAL_INDENT <= INDENT_LIMIT then
  1993.             INDENT := REAL_INDENT;
  1994.          end if;
  1995.       end ENTER_INDENT;
  1996.  
  1997.       procedure EXIT_INDENT is
  1998.       begin
  1999.          REAL_INDENT := REAL_INDENT - INDENT_AMOUNT;
  2000.          if REAL_INDENT >= 0 and then REAL_INDENT <= INDENT_LIMIT then
  2001.             INDENT := REAL_INDENT;
  2002.          end if;
  2003.       end EXIT_INDENT;
  2004.  
  2005.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2006.  
  2007.       function SPLIT_RANGE (CURRENT_DEC : DECLARATION_PTR) return BOOLEAN is
  2008.          --The discrete_range for a task entry is of the form:
  2009.          --   subtype_indication | T'RANGE |
  2010.          --   simple_expression .. simple_expression
  2011.          --The only form we handle here is integer .. integer
  2012.  
  2013.          --Any other form is not handled and the function returns FALSE
  2014.  
  2015.          --For forms that are handled, a duplicate entry is created for
  2016.          --each entry in the discrete range.
  2017.  
  2018.          NEXT       : DECLARATION_PTR := CURRENT_DEC.NEXT_DEC;
  2019.          TEMP, PREV : DECLARATION_PTR;
  2020.          START1, START2, STOP1, STOP2 : INTEGER;
  2021.          type STATE_TYPE is (INITIAL_STATE, AFTER_OPEN, AFTER_DOT,
  2022.                              AFTER_RANGE);
  2023.          STATE        : STATE_TYPE := INITIAL_STATE;
  2024.          C            : CHARACTER;
  2025.          PAREN        : INTEGER := 0;
  2026.          LB, UB, LAST : INTEGER;
  2027.          FAMILY_MEMBER : STRING_RECORD;
  2028.          ATTRIBUTE     : INTEGER := 0;
  2029.       begin
  2030.          if CURRENT_DEC.RETURN_TYPE.CLASS = GETTOKEN.NUM then
  2031.             return TRUE;            --Already split!
  2032.          end if;
  2033.          for I in 1 .. CURRENT_DEC.RETURN_TYPE.LENGTH loop
  2034.             C := CURRENT_DEC.RETURN_TYPE.STR (I);
  2035.             if C = '(' then
  2036.                PAREN := PAREN + 1;
  2037.             elsif C = ')' then
  2038.                PAREN := PAREN - 1;
  2039.                if PAREN = 0 then
  2040.                   if STATE = AFTER_RANGE then
  2041.                      STOP2 := I - 1;
  2042.          exit;                           --All OK so far!
  2043.                   elsif STATE = AFTER_OPEN then
  2044.                      if ATTRIBUTE /= 0 then        --T'RANGE
  2045.                         CURRENT_DEC.RETURN_TYPE.STR (ATTRIBUTE+1 ..
  2046.                                     ATTRIBUTE+5) := "FIRST";
  2047.                      else
  2048.                         CURRENT_DEC.RETURN_TYPE.STR (I .. I + 6) :=
  2049.                                     "'FIRST)";
  2050.                         CURRENT_DEC.RETURN_TYPE.LENGTH := I + 6;
  2051.                      end if;
  2052.                      return FALSE;   --Not handled, but will compile!
  2053.                   else
  2054.                      return FALSE;   --Not handled, user must edit
  2055.                   end if;
  2056.                end if;
  2057.             end if;
  2058.             case STATE is
  2059.                when INITIAL_STATE =>
  2060.                   if C = '(' then
  2061.                      STATE := AFTER_OPEN;
  2062.                   end if;
  2063.                   START1 := I + 1;
  2064.                when AFTER_OPEN =>
  2065.                   if PAREN = 1 then
  2066.                      if C = '.' then
  2067.                         STATE := AFTER_DOT;
  2068.                      elsif C = ''' then
  2069.                         ATTRIBUTE := I;
  2070.                      end if;
  2071.                   end if;
  2072.                when AFTER_DOT =>
  2073.                   if C = '.' then
  2074.                      STATE := AFTER_RANGE;
  2075.                      STOP1 := I - 2;
  2076.                      START2 := I + 1;
  2077.                   else
  2078.                      STATE := AFTER_OPEN;
  2079.                   end if;
  2080.                when AFTER_RANGE =>
  2081.                   null;
  2082.             end case;
  2083.          end loop;
  2084.          if STATE /= AFTER_RANGE or else PAREN /= 0 then
  2085.             return FALSE;
  2086.          end if;
  2087.          GET (CURRENT_DEC.RETURN_TYPE.STR (START1 .. STOP1),
  2088.               LB, LAST);
  2089.          for I in LAST+1 .. STOP1 loop
  2090.             if CURRENT_DEC.RETURN_TYPE.STR (I) /= ' ' then
  2091.                return FALSE;
  2092.             end if;
  2093.          end loop;
  2094.          GET (CURRENT_DEC.RETURN_TYPE.STR (START2 .. STOP2),
  2095.               UB, LAST);
  2096.          for I in LAST+1 .. STOP2 loop
  2097.             if CURRENT_DEC.RETURN_TYPE.STR (I) /= ' ' then
  2098.                return FALSE;
  2099.             end if;
  2100.          end loop;
  2101.          if LB > UB then
  2102.             return FALSE;      --Null range not handled
  2103.          end if;
  2104.          PREV := null;
  2105.          for I in LB .. UB loop
  2106.             declare
  2107.                S : constant STRING := INTEGER'IMAGE(I);
  2108.             begin
  2109.                FAMILY_MEMBER.STR (1 .. 2) := " (";
  2110.                FAMILY_MEMBER.STR (3 .. S'LAST + 2) := S;
  2111.                FAMILY_MEMBER.STR (S'LAST + 3 .. S'LAST + 4) := " )";
  2112.                FAMILY_MEMBER.LENGTH := S'LAST + 4;
  2113.                FAMILY_MEMBER.CLASS := GETTOKEN.NUM;
  2114.             end;
  2115.             if PREV = null then
  2116.                CURRENT_DEC.RETURN_TYPE := FAMILY_MEMBER;
  2117.                PREV := CURRENT_DEC;
  2118.             else
  2119.                TEMP := new DECLARATION_BUFF'(CURRENT_DEC.TYPE_OF_DEC,
  2120.                                              CURRENT_DEC.DEC_NAME,
  2121.                                              CURRENT_DEC.FORMAL_PART,
  2122.                                              FAMILY_MEMBER,
  2123.                                              CURRENT_DEC.INTERNAL_DECS,
  2124.                                              null,         --NEXT_DEC
  2125.                                              null,         --PRIOR_TOKENS
  2126.                                              CURRENT_DEC.FOLLOW_TOKENS);
  2127.                PREV.NEXT_DEC := TEMP;
  2128.                PREV := TEMP;
  2129.             end if;
  2130.          end loop;
  2131.          PREV.NEXT_DEC := NEXT;
  2132.          return TRUE;
  2133.       exception
  2134.          when others =>
  2135.             return FALSE;
  2136.       end SPLIT_RANGE;
  2137.  
  2138.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2139.  
  2140.    begin    -- STUB
  2141.       CURRENT_DEC := SPECIFICATION;
  2142.       if FIRST_TIME_THROUGH_STUB then
  2143.          REAL_INDENT := 0;
  2144.          INDENT := 0;
  2145.          FIRST_TIME_THROUGH_STUB := FALSE;
  2146.       else
  2147.          NEW_LINE (OUTPUT_FILE); NEW_LINE (OUTPUT_FILE);
  2148.          ENTER_INDENT;
  2149.       end if;
  2150.       while CURRENT_DEC.NEXT_DEC /= null loop
  2151.          NEW_LINE;
  2152.          PUT ("Now stubbing ");
  2153.          PUT (CURRENT_DEC.DEC_NAME.STR (1 .. CURRENT_DEC.DEC_NAME.LENGTH));
  2154.          DO_PRIOR_TOKENS (CURRENT_DEC.PRIOR_TOKENS);
  2155.          if REAL_INDENT = 0 then
  2156.             OUTER_DECLARATION := CURRENT_DEC;
  2157.             PUT_LINE (OUTPUT_FILE, "with TEXT_IO; use TEXT_IO;");
  2158.          end if;
  2159.          case CURRENT_DEC.TYPE_OF_DEC is
  2160.             when KW_PROCEDURE =>
  2161.                PUT_INDENT (OUTPUT_FILE, "procedure ");
  2162.  
  2163.             when KW_FUNCTION =>
  2164.                PUT_INDENT (OUTPUT_FILE, "function  ");
  2165.  
  2166.             when KW_PACKAGE =>
  2167.                PUT_INDENT (OUTPUT_FILE, "package body ");
  2168.  
  2169.             when KW_TASK =>
  2170.                PUT_INDENT (OUTPUT_FILE, "task body ");
  2171.  
  2172.             when KW_ENTRY =>
  2173.                PUT_INDENT (OUTPUT_FILE, "accept    ");
  2174.  
  2175.          end case;
  2176.          MAKE_ROOM (OUTPUT_FILE, CURRENT_DEC.DEC_NAME.LENGTH);
  2177.          PUT (OUTPUT_FILE,
  2178.               CURRENT_DEC.DEC_NAME.STR (1 .. CURRENT_DEC.DEC_NAME.LENGTH));
  2179.          if CURRENT_DEC.TYPE_OF_DEC = KW_PACKAGE then   -- stubbing a package
  2180.             PUT (OUTPUT_FILE, " is");                   --            body
  2181.             DO_FOLLOW_TOKEN (CURRENT_DEC);    -- output optional comment
  2182.             STUB (CURRENT_DEC.INTERNAL_DECS); -- recursive call to handle the
  2183.                                               -- internal specifications
  2184.             DO_PRIOR_TOKENS (CURRENT_DEC.FOLLOW_TOKENS);
  2185.             NEW_LINE (OUTPUT_FILE);
  2186.             PUT_INDENT (OUTPUT_FILE, "end ");
  2187.             PUT (OUTPUT_FILE,
  2188.                  CURRENT_DEC.DEC_NAME.STR (1 .. CURRENT_DEC.DEC_NAME.LENGTH));
  2189.             PUT_LINE (OUTPUT_FILE, ";  -- body");
  2190.          elsif CURRENT_DEC.TYPE_OF_DEC = KW_TASK then   -- stubbing a task
  2191.             PUT (OUTPUT_FILE, " is");                   --            body
  2192.             DO_FOLLOW_TOKEN (CURRENT_DEC);    -- output optional comment
  2193.             PUT_INDENT (OUTPUT_FILE, "begin");
  2194.             NEW_LINE (OUTPUT_FILE);
  2195.             if CURRENT_DEC.INTERNAL_DECS /= null then
  2196.                ENTER_INDENT;
  2197.                PUT_INDENT (OUTPUT_FILE, "loop");
  2198.                NEW_LINE (OUTPUT_FILE);
  2199.                ENTER_INDENT;
  2200.                PUT_INDENT (OUTPUT_FILE, "select");
  2201.                STUB (CURRENT_DEC.INTERNAL_DECS); -- recursive call to handle the
  2202.                                                  -- internal specifications
  2203.                PUT_INDENT (OUTPUT_FILE, "end select;");
  2204.                NEW_LINE (OUTPUT_FILE);
  2205.                EXIT_INDENT;
  2206.                PUT_INDENT (OUTPUT_FILE, "end loop;");
  2207.                NEW_LINE (OUTPUT_FILE);
  2208.                EXIT_INDENT;
  2209.             else
  2210.                PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT);
  2211.                PUT_INDENT (OUTPUT_FILE, "PUT_LINE (""Body stub for ");
  2212.                if OUTER_DECLARATION /= CURRENT_DEC then
  2213.                   if INTEGER (COL (OUTPUT_FILE)) +
  2214.                      OUTER_DECLARATION.DEC_NAME.LENGTH > OUTPUT_LINE_LENGTH
  2215.                   then
  2216.                      PUT_LINE (OUTPUT_FILE, """ &");
  2217.                      if OUTER_DECLARATION.DEC_NAME.LENGTH + INDENT + 10 +
  2218.                         INDENT_AMOUNT <=
  2219.                         OUTPUT_LINE_LENGTH  then
  2220.                         PUT_SPACES (OUTPUT_FILE, INDENT + 10 + INDENT_AMOUNT);
  2221.                      end if;
  2222.                      PUT (OUTPUT_FILE, '"');
  2223.                   end if;
  2224.                   PUT (OUTPUT_FILE,
  2225.                       OUTER_DECLARATION.DEC_NAME.STR (1 ..
  2226.                            OUTER_DECLARATION.DEC_NAME.LENGTH));
  2227.                   PUT (OUTPUT_FILE, '.');
  2228.                end if;
  2229.                if INTEGER (COL (OUTPUT_FILE)) + CURRENT_DEC.DEC_NAME.LENGTH >
  2230.                   OUTPUT_LINE_LENGTH
  2231.                then
  2232.                   PUT_LINE (OUTPUT_FILE, """ &");
  2233.                   if CURRENT_DEC.DEC_NAME.LENGTH + INDENT + 10 +
  2234.                      INDENT_AMOUNT <= OUTPUT_LINE_LENGTH then
  2235.                      PUT_SPACES (OUTPUT_FILE, INDENT + 10 + INDENT_AMOUNT);
  2236.                   end if;
  2237.                   PUT (OUTPUT_FILE, '"');
  2238.                end if;
  2239.                WRITE_ID (OUTPUT_FILE, CURRENT_DEC.DEC_NAME);
  2240.                PUT_LINE (OUTPUT_FILE, """);");
  2241.             end if;
  2242.             DO_PRIOR_TOKENS (CURRENT_DEC.FOLLOW_TOKENS);
  2243.             NEW_LINE (OUTPUT_FILE);
  2244.             PUT_INDENT (OUTPUT_FILE, "end ");
  2245.             PUT (OUTPUT_FILE,
  2246.                  CURRENT_DEC.DEC_NAME.STR (1 .. CURRENT_DEC.DEC_NAME.LENGTH));
  2247.             PUT_LINE (OUTPUT_FILE, ";  -- body");
  2248.          else          --procedure/function/entry
  2249.             if CURRENT_DEC.TYPE_OF_DEC = KW_ENTRY and then
  2250.                CURRENT_DEC.RETURN_TYPE.LENGTH /= 0 then   --Entry family
  2251.                RETURN_TYPE_SAVE := CURRENT_DEC.RETURN_TYPE;
  2252.                if not SPLIT_RANGE (CURRENT_DEC) then
  2253.                   NEW_LINE;
  2254.                   PUT ("Can't handle entry family without simple range");
  2255.                   if 46 + 5 + CURRENT_DEC.DEC_NAME.LENGTH +
  2256.                      RETURN_TYPE_SAVE.LENGTH <= OUTPUT_LINE_LENGTH then
  2257.                      PUT (' ');
  2258.                   else
  2259.                      NEW_LINE;
  2260.                   end if;
  2261.                   PUT ("for ");
  2262.                   PUT (CURRENT_DEC.DEC_NAME.STR (1 ..
  2263.                              CURRENT_DEC.DEC_NAME.LENGTH));
  2264.                   PUT_LINE (RETURN_TYPE_SAVE.STR (1 ..
  2265.                              RETURN_TYPE_SAVE.LENGTH));
  2266.                   PUT ("You must edit the task body");
  2267.                end if;
  2268.                MAKE_ROOM (OUTPUT_FILE, CURRENT_DEC.RETURN_TYPE.LENGTH);
  2269.                PUT (OUTPUT_FILE,
  2270.                     CURRENT_DEC.RETURN_TYPE.STR (1 ..
  2271.                           CURRENT_DEC.RETURN_TYPE.LENGTH));
  2272.             end if;
  2273.             CURRENT_BUFF := CURRENT_DEC.FORMAL_PART;
  2274.             while CURRENT_BUFF /= null loop
  2275.                if CURRENT_BUFF.BUFFER_STRING.LENGTH > OUTPUT_LINE_LENGTH then
  2276.                   declare
  2277.                      I : INTEGER := 1;
  2278.                      J : INTEGER;
  2279.                   begin
  2280.                      while I <= CURRENT_BUFF.BUFFER_STRING.LENGTH loop
  2281.                         J := I;
  2282.                         while J <= CURRENT_BUFF.BUFFER_STRING.LENGTH and then
  2283.                            CURRENT_BUFF.BUFFER_STRING.STR (J) /= ' ' loop
  2284.                            J := J + 1;
  2285.                         end loop;
  2286.                         if IS_ROOM (OUTPUT_FILE, (J - I)) and then
  2287.                            I /= 1 then
  2288.                            PUT (OUTPUT_FILE, ' ');
  2289.                         end if;
  2290.                         PUT (OUTPUT_FILE,
  2291.                              CURRENT_BUFF.BUFFER_STRING.STR (I .. J-1));
  2292.                         I := J + 1;
  2293.                      end loop;
  2294.                   end;
  2295.                else
  2296.                   MAKE_ROOM(OUTPUT_FILE, CURRENT_BUFF.BUFFER_STRING.LENGTH);
  2297.                   PUT (OUTPUT_FILE,
  2298.                       CURRENT_BUFF.BUFFER_STRING.STR
  2299.                          (1 .. CURRENT_BUFF.BUFFER_STRING.LENGTH));
  2300.                end if;
  2301.                CURRENT_BUFF := CURRENT_BUFF.NEXT_ONE;
  2302.                if CURRENT_BUFF /= null then
  2303.                   NEW_LINE (OUTPUT_FILE);
  2304.                   PUT_INDENT (OUTPUT_FILE);
  2305.                   if CURRENT_DEC.TYPE_OF_DEC = KW_ENTRY then
  2306.                      -- Space over past entry family index (if any)
  2307.                      PUT_SPACES (OUTPUT_FILE,
  2308.                                  CURRENT_DEC.RETURN_TYPE.LENGTH);
  2309.                   end if;
  2310.                end if;
  2311.             end loop;
  2312.             if CURRENT_DEC.TYPE_OF_DEC = KW_FUNCTION then
  2313.                MAKE_ROOM (OUTPUT_FILE, 8);
  2314.                PUT (OUTPUT_FILE, " return ");
  2315.                MAKE_ROOM (OUTPUT_FILE, CURRENT_DEC.RETURN_TYPE.LENGTH);
  2316.                PUT (OUTPUT_FILE,
  2317.                    CURRENT_DEC.RETURN_TYPE.STR
  2318.                       (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH));
  2319.             end if;
  2320.             MAKE_ROOM (OUTPUT_FILE, 3);
  2321.             if CURRENT_DEC.TYPE_OF_DEC = KW_ENTRY then
  2322.                PUT (OUTPUT_FILE, " do");
  2323.             else
  2324.                PUT (OUTPUT_FILE, " is");
  2325.             end if;
  2326.             DO_FOLLOW_TOKEN (CURRENT_DEC);
  2327.             NEW_LINE (OUTPUT_FILE);
  2328.             if CURRENT_DEC.TYPE_OF_DEC = KW_FUNCTION then    -- all functions
  2329.                PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT);
  2330.                PUT_INDENT (OUTPUT_FILE, "DUMMY : ");         -- require a return
  2331.                MAKE_ROOM (OUTPUT_FILE, CURRENT_DEC.RETURN_TYPE.LENGTH);
  2332.                PUT (OUTPUT_FILE,
  2333.                    CURRENT_DEC.RETURN_TYPE.STR               -- statement to
  2334.                    (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH));   -- compile, so to
  2335.  
  2336.           --  An attempt to put in default values for STANDARD types
  2337.           --  Ought to be done for derived types and composites of STANDARD
  2338.  
  2339.                if CURRENT_DEC.RETURN_TYPE.STR
  2340.                      (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "INTEGER"
  2341.                or else CURRENT_DEC.RETURN_TYPE.STR
  2342.                      (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "SHORT_INTEGER"
  2343.                or else CURRENT_DEC.RETURN_TYPE.STR
  2344.                      (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "LONG_INTEGER"
  2345.                or else CURRENT_DEC.RETURN_TYPE.STR
  2346.                      (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "TINY_INTEGER"
  2347.                then
  2348.                   PUT (OUTPUT_FILE, " := 1");
  2349.                elsif CURRENT_DEC.RETURN_TYPE.STR
  2350.                         (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "FLOAT"
  2351.                or else CURRENT_DEC.RETURN_TYPE.STR
  2352.                         (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "SHORT_FLOAT"
  2353.                or else CURRENT_DEC.RETURN_TYPE.STR
  2354.                         (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "LONG_FLOAT"
  2355.                then
  2356.                   PUT (OUTPUT_FILE, " := 1.0");
  2357.                elsif CURRENT_DEC.RETURN_TYPE.STR
  2358.                         (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "BOOLEAN"
  2359.                then
  2360.                   PUT (OUTPUT_FILE, " := TRUE");
  2361.                elsif CURRENT_DEC.RETURN_TYPE.STR
  2362.                         (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "STRING"
  2363.                then
  2364.                   PUT (OUTPUT_FILE, "(1..6) := ""STRING""");
  2365.                elsif CURRENT_DEC.RETURN_TYPE.STR
  2366.                         (1 .. CURRENT_DEC.RETURN_TYPE.LENGTH) = "CHARACTER"
  2367.                then
  2368.                   PUT (OUTPUT_FILE, " := 'C'");
  2369.                end if;
  2370.                PUT (OUTPUT_FILE, ';');                      -- guarantee that
  2371.                NEW_LINE (OUTPUT_FILE);                     -- all types are
  2372.                NEW_LINE (OUTPUT_FILE);                    -- accounted for, a
  2373.             end if;                                      -- dummy variable is
  2374.                                                         -- created and returned.
  2375.                                                        -- One must note that one
  2376.                                                       -- cannot run this func-
  2377.                                                      -- tion, since dummy is
  2378.                                                     -- never initialized (and
  2379.                                                    -- for the same reasons it
  2380.                                                   -- was created, couldn't be),
  2381.                                                  -- but it will compile.
  2382.  
  2383.             if CURRENT_DEC.TYPE_OF_DEC /= KW_ENTRY then
  2384.                PUT_INDENT (OUTPUT_FILE, "begin");
  2385.                if CURRENT_DEC.DEC_NAME.LENGTH + INTEGER (COL (OUTPUT_FILE)) +
  2386.                   13 < OUTPUT_LINE_LENGTH then
  2387.                   PUT (OUTPUT_FILE, "          -- ");
  2388.                   PUT_LINE (OUTPUT_FILE,
  2389.                             CURRENT_DEC.DEC_NAME.STR (1 ..
  2390.                                     CURRENT_DEC.DEC_NAME.LENGTH));
  2391.                else
  2392.                   NEW_LINE (OUTPUT_FILE);
  2393.                end if;
  2394.             end if;
  2395.             PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT);
  2396.             PUT_INDENT (OUTPUT_FILE, "PUT_LINE (""Body stub for ");
  2397.             if OUTER_DECLARATION /= CURRENT_DEC then
  2398.                if INTEGER (COL (OUTPUT_FILE)) +
  2399.                   OUTER_DECLARATION.DEC_NAME.LENGTH > OUTPUT_LINE_LENGTH
  2400.                then
  2401.                   PUT_LINE (OUTPUT_FILE, """ &");
  2402.                   if OUTER_DECLARATION.DEC_NAME.LENGTH + INDENT + 10 +
  2403.                      INDENT_AMOUNT <=
  2404.                      OUTPUT_LINE_LENGTH  then
  2405.                      PUT_SPACES (OUTPUT_FILE, INDENT + 10 + INDENT_AMOUNT);
  2406.                   end if;
  2407.                   PUT (OUTPUT_FILE, '"');
  2408.                end if;
  2409.                PUT (OUTPUT_FILE,
  2410.                    OUTER_DECLARATION.DEC_NAME.STR (1 ..
  2411.                         OUTER_DECLARATION.DEC_NAME.LENGTH));
  2412.                PUT (OUTPUT_FILE, '.');
  2413.             end if;
  2414.             if INTEGER (COL (OUTPUT_FILE)) + CURRENT_DEC.DEC_NAME.LENGTH >
  2415.                OUTPUT_LINE_LENGTH
  2416.             then
  2417.                PUT_LINE (OUTPUT_FILE, """ &");
  2418.                if CURRENT_DEC.DEC_NAME.LENGTH + INDENT + 10 + INDENT_AMOUNT <=
  2419.                   OUTPUT_LINE_LENGTH then
  2420.                   PUT_SPACES (OUTPUT_FILE, INDENT + 10 + INDENT_AMOUNT);
  2421.                end if;
  2422.                PUT (OUTPUT_FILE, '"');
  2423.             end if;
  2424.             WRITE_ID (OUTPUT_FILE, CURRENT_DEC.DEC_NAME);
  2425.             PUT_LINE (OUTPUT_FILE, """);");
  2426.             if CURRENT_DEC.TYPE_OF_DEC = KW_FUNCTION then
  2427.                PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT);
  2428.                PUT_INDENT (OUTPUT_FILE, "return DUMMY;");
  2429.                NEW_LINE (OUTPUT_FILE);
  2430.             end if;
  2431.             NEW_LINE (OUTPUT_FILE);
  2432.             if GENERATE_EXCEPTION_PART and then
  2433.                CURRENT_DEC.TYPE_OF_DEC /= KW_ENTRY then
  2434.                PUT_INDENT (OUTPUT_FILE, "exception");
  2435.                NEW_LINE (OUTPUT_FILE);
  2436.                PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT);
  2437.                PUT_INDENT (OUTPUT_FILE, "when others =>");
  2438.                NEW_LINE (OUTPUT_FILE);
  2439.                PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT * 2);
  2440.                PUT_INDENT (OUTPUT_FILE, "PUT_LINE (""Unhandled exception in ");
  2441.                if OUTER_DECLARATION /= CURRENT_DEC then
  2442.                   if INTEGER (COL (OUTPUT_FILE)) +
  2443.                      OUTER_DECLARATION.DEC_NAME.LENGTH > OUTPUT_LINE_LENGTH
  2444.                   then
  2445.                      PUT_LINE (OUTPUT_FILE, """ &");
  2446.                      if OUTER_DECLARATION.DEC_NAME.LENGTH + INDENT + 10 +
  2447.                         INDENT_AMOUNT * 2 <= OUTPUT_LINE_LENGTH then
  2448.                         PUT_SPACES (OUTPUT_FILE,
  2449.                                     INDENT + 10 + INDENT_AMOUNT * 2);
  2450.                      end if;
  2451.                      PUT (OUTPUT_FILE, '"');
  2452.                   end if;
  2453.                   PUT (OUTPUT_FILE,
  2454.                       OUTER_DECLARATION.DEC_NAME.STR (1 ..
  2455.                            OUTER_DECLARATION.DEC_NAME.LENGTH));
  2456.                   PUT (OUTPUT_FILE, '.');
  2457.                end if;
  2458.                if INTEGER (COL (OUTPUT_FILE)) + CURRENT_DEC.DEC_NAME.LENGTH >
  2459.                   OUTPUT_LINE_LENGTH
  2460.                then
  2461.                   PUT_LINE (OUTPUT_FILE, """ &");
  2462.                   if CURRENT_DEC.DEC_NAME.LENGTH + INDENT + 10 +
  2463.                      INDENT_AMOUNT * 2 <= OUTPUT_LINE_LENGTH then
  2464.                      PUT_SPACES (OUTPUT_FILE, INDENT + 10 + INDENT_AMOUNT * 2);
  2465.                   end if;
  2466.                   PUT (OUTPUT_FILE, '"');
  2467.                end if;
  2468.                WRITE_ID (OUTPUT_FILE, CURRENT_DEC.DEC_NAME);
  2469.                PUT_LINE (OUTPUT_FILE, """);");
  2470.                PUT_SPACES (OUTPUT_FILE, INDENT_AMOUNT * 2);
  2471.                PUT_INDENT (OUTPUT_FILE, "raise;");
  2472.                NEW_LINE (OUTPUT_FILE);
  2473.             end if;
  2474.             PUT_INDENT (OUTPUT_FILE, "end ");
  2475.             MAKE_ROOM (OUTPUT_FILE, CURRENT_DEC.DEC_NAME.LENGTH + 1);
  2476.             PUT (OUTPUT_FILE,
  2477.                  CURRENT_DEC.DEC_NAME.STR (1 .. CURRENT_DEC.DEC_NAME.LENGTH));
  2478.             PUT (OUTPUT_FILE, ';');
  2479.             NEW_LINE (OUTPUT_FILE);
  2480.             if CURRENT_DEC.TYPE_OF_DEC = KW_ENTRY and then
  2481.                CURRENT_DEC.NEXT_DEC /= null then
  2482.                EXIT_INDENT;
  2483.                PUT_INDENT (OUTPUT_FILE, "or");
  2484.                ENTER_INDENT;
  2485.                if CURRENT_DEC.NEXT_DEC.NEXT_DEC = null then
  2486.                   NEW_LINE (OUTPUT_FILE); NEW_LINE (OUTPUT_FILE);
  2487.                   PUT_INDENT (OUTPUT_FILE, "terminate;");
  2488.                end if;
  2489.             end if;
  2490.          end if;
  2491.          CURRENT_DEC := CURRENT_DEC.NEXT_DEC;
  2492.          NEW_LINE (OUTPUT_FILE);
  2493.          NEW_LINE (OUTPUT_FILE);
  2494.       end loop;
  2495.       EXIT_INDENT;
  2496.    exception
  2497.       when others =>
  2498.          PUT_LINE ("Unhandled exception in STUBBER_SUPPORT.STUB");
  2499.          raise;
  2500.  
  2501.    end STUB;
  2502.  
  2503.   ----------------------------------------------------------------------
  2504.  
  2505.    procedure GET_PAST_END is
  2506.  
  2507.           ---------------------------------------------------------
  2508.           --  This procedure is designed to skip past tokens     --
  2509.           --  until it finds the word "end".  However, it must   --
  2510.           --  find the "end" that goes with the token that       --
  2511.           --  forced the procedure call in the first place.  So  --
  2512.           --  when it comes upon a word that will also have an   --
  2513.           --  "end" associated with it, it must get past that    --
  2514.           --  one, too.                                          --
  2515.           ---------------------------------------------------------
  2516.  
  2517.    begin
  2518.       GET_ONE_TOKEN;
  2519.       SAVE_ONE_TOKEN;
  2520.       while CONVERT (TOKEN) /= KW_END loop
  2521.          case CONVERT (TOKEN) is
  2522.             when KW_ACCEPT | KW_BEGIN | KW_CASE | KW_IF | KW_LOOP | KW_RECORD =>
  2523.                GET_PAST_END;
  2524.  
  2525.                                 -- This is a rather ingenious method of getting
  2526.                                -- through the body of a subprogram, record, or
  2527.                               -- whatever.  Every time a word is found that has
  2528.                              -- and "end" associated with it, the procedure
  2529.                             -- calls itself.
  2530.  
  2531.             when others =>
  2532.                null;
  2533.  
  2534.          end case;
  2535.          GET_ONE_TOKEN;
  2536.          SAVE_ONE_TOKEN;
  2537.       end loop;
  2538.       GET_ONE_TOKEN;                                    -- This last GET_ONE is
  2539.       SAVE_ONE_TOKEN;
  2540.                                                        -- to eliminate the
  2541.                                                       -- possibility of the
  2542.                                                      -- procedure finding the
  2543.                                                     -- "if" of an "end if", etc.
  2544.    end GET_PAST_END;
  2545.  
  2546.   ----------------------------------------------------------------------
  2547.  
  2548.    procedure LOAD_KEY_WORDS is
  2549.    begin
  2550.       for I in KEY_WORDS loop
  2551.          KW (I) := new STRING'(KEY_WORDS'IMAGE (I));
  2552.       end loop;
  2553.    end LOAD_KEY_WORDS;
  2554.  
  2555.   ----------------------------------------------------------------------
  2556.  
  2557.    function  CONVERT (STR1 : STRING_RECORD) return KEY_WORDS is
  2558.  
  2559.    --| Overview
  2560.    --|
  2561.    --| This perfect hash algorithm taken from
  2562.    --|  "A Perfect Hash Function for Ada Reserved Words"
  2563.    --|  by David Wolverton, published in Ada Letters Jul-Aug 1984
  2564.    --|
  2565.  
  2566.       subtype HASH_RANGE              is INTEGER;
  2567.  
  2568.       subtype HASH_IDENTIFIER_SUBRANGE is HASH_RANGE range 0 .. 70;
  2569.  
  2570.       type XLATE_ARRAY is array (CHARACTER) of HASH_RANGE;
  2571.  
  2572.       XLATE            : constant XLATE_ARRAY :=
  2573.          XLATE_ARRAY'
  2574.             ('A' => 0   , 'B' => 49  , 'C' => 0   , 'D' => - 7 , 'E' => - 20,
  2575.              'F' => 18  , 'G' => - 2 , 'H' => - 38, 'I' => 33  , 'J' => 0   ,
  2576.              'K' => - 9 , 'L' => 9   , 'M' => 29  , 'N' => - 9 , 'O' => 6   ,
  2577.              'P' => 26  , 'Q' => 0   , 'R' => 8   , 'S' => 1   , 'T' => 1   ,
  2578.              'U' => - 9 , 'V' => 0   , 'W' => 56  , 'X' => - 28, 'Y' => 11  ,
  2579.              'Z' => 0   , others => 0);
  2580.  
  2581.       type HASH_TABLE_ARRAY is array (HASH_IDENTIFIER_SUBRANGE) of KEY_WORDS;
  2582.  
  2583.        --| Mapping from hash value into the token values.
  2584.  
  2585.       HASH_TABLE        : constant HASH_TABLE_ARRAY :=
  2586.          HASH_TABLE_ARRAY'
  2587.             (40 => KW_ABORT    , 6 => KW_ABS       , 37 => KW_ACCEPT   ,
  2588.              43 => KW_ACCESS   , 34 => KW_ALL      , 22 => KW_AND      ,
  2589.              16 => KW_ARRAY    , 3 => KW_AT        , 61 => KW_BEGIN    ,
  2590.              70 => KW_BODY     , 20 => KW_CASE     , 35 => KW_CONSTANT ,
  2591.              14 => KW_DECLARE  , 9 => KW_DELAY     , 36 => KW_DELTA    ,
  2592.              38 => KW_DIGITS   , 7 => KW_DO        , 0 => KW_ELSE      ,
  2593.              19 => KW_ELSIF    , 2 => KW_END       , 30 => KW_ENTRY    ,
  2594.              8 => KW_EXCEPTION , 1 => KW_EXIT      , 57 => KW_FOR      ,
  2595.              45 => KW_FUNCTION , 21 => KW_GENERIC  , 46 => KW_GOTO     ,
  2596.              69 => KW_IF       , 42 => KW_IN       , 52 => KW_IS       ,
  2597.              17 => KW_LIMITED  , 67 => KW_LOOP     , 53 => KW_MOD      ,
  2598.              58 => KW_NEW      , 23 => KW_NOT      , 26 => KW_NULL     ,
  2599.              54 => KW_OF       , 44 => KW_OR       , 47 => KW_OTHERS   ,
  2600.              50 => KW_OUT      , 25 => KW_PACKAGE  , 56 => KW_PRAGMA   ,
  2601.              51 => KW_PRIVATE  , 49 => KW_PROCEDURE, 29 => KW_RAISE    ,
  2602.              5 => KW_RANGE     , 41 => KW_RECORD   , 48 => KW_REM      ,
  2603.              24 => KW_RENAMES  , 39 => KW_RETURN   , 31 => KW_REVERSE  ,
  2604.              12 => KW_SELECT   , 27 => KW_SEPARATE , 18 => KW_SUBTYPE  ,
  2605.              32 => KW_TASK     , 28 => KW_TERMINATE, 4 => KW_THEN      ,
  2606.              15 => KW_TYPE     , 10 => KW_USE      , 59 => KW_WHEN     ,
  2607.              63 => KW_WHILE    , 60 => KW_WITH     , 11 => KW_XOR      ,
  2608.              others => NOT_KW  );
  2609.  
  2610.       IN_IDENTIFIER    : STRING renames STR1.STR (1 .. STR1.LENGTH);
  2611.       OUT_TOKEN_VALUE  : KEY_WORDS;
  2612.       LENGTH           : HASH_RANGE := IN_IDENTIFIER'LENGTH;
  2613.        --| Length of string
  2614.  
  2615.       FIRST            : HASH_RANGE := IN_IDENTIFIER'FIRST;
  2616.        --| Lower bound
  2617.  
  2618.       FIRST_CHAR,
  2619.       LAST_CHAR         : CHARACTER;
  2620.        --| First and last characters
  2621.  
  2622.       SECOND_TO_LAST_CHAR : CHARACTER;
  2623.        --| Second to last character
  2624.  
  2625.       SECOND_TO_LAST     : HASH_RANGE;
  2626.        --| Alphabetic position of 2nd to last char.
  2627.  
  2628.       HASH_VALUE        : HASH_RANGE;
  2629.        --| Perfect hash value.
  2630.  
  2631.       TOKEN_VALUE       : KEY_WORDS;
  2632.    begin
  2633.  
  2634.        -- Assume In_Identifier is a plain identifier.
  2635.  
  2636.       OUT_TOKEN_VALUE := NOT_KW;
  2637.       if (LENGTH <= 1) or else (LENGTH >= 10) then
  2638.          return NOT_KW; -- Couldn't be a reserved word.
  2639.       else
  2640.          FIRST_CHAR := IN_IDENTIFIER (FIRST);
  2641.          LAST_CHAR := IN_IDENTIFIER ((FIRST + LENGTH) - 1);
  2642.          SECOND_TO_LAST_CHAR := IN_IDENTIFIER ((FIRST + LENGTH) - 2);
  2643.          SECOND_TO_LAST :=
  2644.             CHARACTER'POS (SECOND_TO_LAST_CHAR) - CHARACTER'POS ('A');
  2645.          HASH_VALUE := XLATE (FIRST_CHAR) + XLATE (LAST_CHAR) +
  2646.                        2 * SECOND_TO_LAST + LENGTH;
  2647.       end if;
  2648.       if HASH_VALUE in HASH_IDENTIFIER_SUBRANGE then
  2649.  
  2650.            -- index and see if it matches a reserved word value.
  2651.            -- if so, then compare the string to the reserved word text.
  2652.  
  2653.          TOKEN_VALUE := HASH_TABLE (HASH_VALUE);
  2654.          if TOKEN_VALUE /= NOT_KW then
  2655.             declare
  2656.                IM : KWP := KW (TOKEN_VALUE);
  2657.             begin
  2658.                if (IN_IDENTIFIER = IM.all (4 .. IM.all'LAST)) then
  2659.                   OUT_TOKEN_VALUE := TOKEN_VALUE;
  2660.                end if;
  2661.             end;
  2662.          end if;
  2663.       end if;
  2664.       return OUT_TOKEN_VALUE;
  2665.    end CONVERT;
  2666.  
  2667.   ----------------------------------------------------------------------
  2668.  
  2669. begin     -- initializations
  2670.    LOAD_KEY_WORDS;
  2671.    FIRST_TIME_THROUGH_STUB := TRUE;
  2672. end STUBBER_SUPPORT;
  2673.  
  2674. --::::::::::
  2675. --stubtest.spc
  2676. --::::::::::
  2677. --Comments before
  2678. --the package spec
  2679. with calendar;
  2680. package stubtest is               --Comment on package STUBTEST
  2681. --Comment before procedure a
  2682.    procedure a;                   --Comment on procedure A decl
  2683.    function b(arg1, arg2 : integer) return string;
  2684.  
  2685.    type c is record
  2686.       d : calendar.time;
  2687.    end record;
  2688.  
  2689.    --Comment before the generic package f
  2690.    generic
  2691.       type e is private;
  2692.       with procedure gen1 is <>;
  2693.       with procedure gen2;  --This requires special care (looks like a spec)!
  2694.    package f is
  2695.       function g return c;
  2696.       procedure h(arg1 : e; arg2 : OUT float; arg3 : IN OUT integer);
  2697.       function i return e;
  2698.    end f;
  2699.  
  2700.    --Comment before function j
  2701.    function j return boolean;
  2702.    function k return integer;                       --comment on function k decl
  2703.    function l return short_integer;
  2704.    function "and" (left, right : integer) return integer;  --comment on "and"
  2705.  
  2706.    --Comment before task m
  2707.    task m;
  2708.    task type n;                 --comment on n
  2709.    type not_handled is range 1..2;
  2710.    type no_good is array(not_handled) of boolean;
  2711.    task type o is                     --comment on task type o
  2712.       entry p;                        --comment on entry p
  2713.       entry q(arg1, arg2 : integer);
  2714.       entry r(1..3)(arg1 : integer; arg2 : OUT float);
  2715.       entry s(not_handled);
  2716.       entry t(no_good'range)(arg1 : integer);
  2717.       --comment before end of task type o
  2718.    end o;
  2719.  
  2720.    function u (arg1, arg2 : IN calendar.time) return calendar.time;
  2721.    procedure v (arg1, arg2 : IN integer := integer'first;
  2722.                 arg3 : IN float := 16#1_000.0#E0;
  2723.                 arg4 : string := "";
  2724.                 arg5 : character := ''';
  2725.                 arg6 : character := character'val(character'pos('''));
  2726.                 arg7 : integer := (integer'last mod (2**4));
  2727.                 arg8 : string := (1 => 'a',
  2728.                                   2 => ''');
  2729.                 arg9 : string := """inside""";
  2730.                 arga : IN OUT integer);
  2731.  
  2732.    procedure interfaced;
  2733.    function interfaced return boolean;  --this comment should be suppressed
  2734.  
  2735.    type very_long_type_name_for_the_function_result_type         is new integer;
  2736.    type very_long_type_name_for_the_arguments is                            new
  2737.    integer;
  2738.  
  2739.    function
  2740. this_is_a_very_very_long_function_name_see_if_it_is_handled_properly(
  2741. long_argument_name_1, long_argument_name_2, long_argument_name_3,
  2742. long_argument_name_4 : IN integer; long_argument_name_5,
  2743. long_argument_name_6, long_argument_name_7, long_argument_name_8 : IN
  2744. very_long_type_name_for_the_arguments) return
  2745. very_long_type_name_for_the_function_result_type;   --sure is a long function
  2746.  
  2747. private
  2748.    --comment in private part
  2749.    pragma interface(assembler, interfaced);
  2750. end stubtest;
  2751.  
  2752. --comments before the procedure finish
  2753. procedure finish;
  2754. --::::::::::
  2755. --stubtest.bdy
  2756. --::::::::::
  2757. --Comments before
  2758. --the package spec
  2759. --with CALENDAR;
  2760. with TEXT_IO; use TEXT_IO;
  2761. package body STUBTEST is          --Comment on package STUBTEST
  2762.  
  2763.  
  2764.    procedure A is                 --Comment on procedure A decl
  2765.  
  2766.    begin          -- A
  2767.       PUT_LINE ("Body stub for STUBTEST.A");
  2768.  
  2769.    exception
  2770.       when others =>
  2771.          PUT_LINE ("Unhandled exception in STUBTEST.A");
  2772.          raise;
  2773.    end A;
  2774.  
  2775.  
  2776.    function  B (ARG1, ARG2 : INTEGER) return STRING is
  2777.  
  2778.       DUMMY : STRING(1..6) := "STRING";
  2779.  
  2780.    begin          -- B
  2781.       PUT_LINE ("Body stub for STUBTEST.B");
  2782.       return DUMMY;
  2783.  
  2784.    exception
  2785.       when others =>
  2786.          PUT_LINE ("Unhandled exception in STUBTEST.B");
  2787.          raise;
  2788.    end B;
  2789.  
  2790.  
  2791.  
  2792. --   type C is record
  2793. --      D : CALENDAR.TIME;
  2794. --   end record;
  2795.  
  2796.    --Comment before the generic package f
  2797. --   generic
  2798. --      type E is private;
  2799. --      with procedure GEN1 is <>;
  2800. --      with procedure GEN2;  --This requires special care (looks like a spec)!
  2801.    package body F is
  2802.  
  2803.  
  2804.       function  G return C is
  2805.  
  2806.          DUMMY : C;
  2807.  
  2808.       begin          -- G
  2809.          PUT_LINE ("Body stub for STUBTEST.G");
  2810.          return DUMMY;
  2811.  
  2812.       exception
  2813.          when others =>
  2814.             PUT_LINE ("Unhandled exception in STUBTEST.G");
  2815.             raise;
  2816.       end G;
  2817.  
  2818.  
  2819.       procedure H (ARG1 : E;
  2820.                    ARG2 : out FLOAT;
  2821.                    ARG3 : in out INTEGER) is
  2822.  
  2823.       begin          -- H
  2824.          PUT_LINE ("Body stub for STUBTEST.H");
  2825.  
  2826.       exception
  2827.          when others =>
  2828.             PUT_LINE ("Unhandled exception in STUBTEST.H");
  2829.             raise;
  2830.       end H;
  2831.  
  2832.  
  2833.       function  I return E is
  2834.  
  2835.          DUMMY : E;
  2836.  
  2837.       begin          -- I
  2838.          PUT_LINE ("Body stub for STUBTEST.I");
  2839.          return DUMMY;
  2840.  
  2841.       exception
  2842.          when others =>
  2843.             PUT_LINE ("Unhandled exception in STUBTEST.I");
  2844.             raise;
  2845.       end I;
  2846.  
  2847.  
  2848. --
  2849.  
  2850.    end F;  -- body
  2851.  
  2852.  
  2853.  
  2854.    --Comment before function j
  2855.    function  J return BOOLEAN is
  2856.  
  2857.       DUMMY : BOOLEAN := TRUE;
  2858.  
  2859.    begin          -- J
  2860.       PUT_LINE ("Body stub for STUBTEST.J");
  2861.       return DUMMY;
  2862.  
  2863.    exception
  2864.       when others =>
  2865.          PUT_LINE ("Unhandled exception in STUBTEST.J");
  2866.          raise;
  2867.    end J;
  2868.  
  2869.  
  2870.    function  K return INTEGER is                    --comment on function k decl
  2871.  
  2872.       DUMMY : INTEGER := 1;
  2873.  
  2874.    begin          -- K
  2875.       PUT_LINE ("Body stub for STUBTEST.K");
  2876.       return DUMMY;
  2877.  
  2878.    exception
  2879.       when others =>
  2880.          PUT_LINE ("Unhandled exception in STUBTEST.K");
  2881.          raise;
  2882.    end K;
  2883.  
  2884.  
  2885.    function  L return SHORT_INTEGER is
  2886.  
  2887.       DUMMY : SHORT_INTEGER := 1;
  2888.  
  2889.    begin          -- L
  2890.       PUT_LINE ("Body stub for STUBTEST.L");
  2891.       return DUMMY;
  2892.  
  2893.    exception
  2894.       when others =>
  2895.          PUT_LINE ("Unhandled exception in STUBTEST.L");
  2896.          raise;
  2897.    end L;
  2898.  
  2899.  
  2900.    function  "and" (LEFT, RIGHT : INTEGER) return INTEGER is --comment on "and"
  2901.       DUMMY : INTEGER := 1;
  2902.  
  2903.    begin          -- "and"
  2904.       PUT_LINE ("Body stub for STUBTEST.""and""");
  2905.       return DUMMY;
  2906.  
  2907.    exception
  2908.       when others =>
  2909.          PUT_LINE ("Unhandled exception in STUBTEST.""and""");
  2910.          raise;
  2911.    end "and";
  2912.  
  2913.  
  2914.    task body M is
  2915.    begin
  2916.       PUT_LINE ("Body stub for STUBTEST.M");
  2917.  
  2918.    end M;  -- body
  2919.  
  2920.  
  2921.    task body N is               --comment on n
  2922.    begin
  2923.       PUT_LINE ("Body stub for STUBTEST.N");
  2924.  
  2925.    end N;  -- body
  2926.  
  2927.  
  2928. --   type NOT_HANDLED is range 1..2;
  2929. --   type NO_GOOD is array(NOT_HANDLED) of BOOLEAN;
  2930.    task body O is                     --comment on task type o
  2931.    begin
  2932.       loop
  2933.          select
  2934.  
  2935.             accept    P do            --comment on entry p
  2936.  
  2937.                PUT_LINE ("Body stub for STUBTEST.P");
  2938.  
  2939.             end P;
  2940.          or
  2941.  
  2942.             accept    Q (ARG1, ARG2 : INTEGER) do
  2943.  
  2944.                PUT_LINE ("Body stub for STUBTEST.Q");
  2945.  
  2946.             end Q;
  2947.          or
  2948.  
  2949.             accept    R ( 1 ) (ARG1 : INTEGER;
  2950.                                ARG2 : out FLOAT) do
  2951.  
  2952.                PUT_LINE ("Body stub for STUBTEST.R");
  2953.  
  2954.             end R;
  2955.          or
  2956.  
  2957.             accept    R ( 2 ) (ARG1 : INTEGER;
  2958.                                ARG2 : out FLOAT) do
  2959.  
  2960.                PUT_LINE ("Body stub for STUBTEST.R");
  2961.  
  2962.             end R;
  2963.          or
  2964.  
  2965.             accept    R ( 3 ) (ARG1 : INTEGER;
  2966.                                ARG2 : out FLOAT) do
  2967.  
  2968.                PUT_LINE ("Body stub for STUBTEST.R");
  2969.  
  2970.             end R;
  2971.          or
  2972.  
  2973.             accept    S (NOT_HANDLED'FIRST) do
  2974.  
  2975.                PUT_LINE ("Body stub for STUBTEST.S");
  2976.  
  2977.             end S;
  2978.          or
  2979.  
  2980.             accept    T (NO_GOOD'FIRST) (ARG1 : INTEGER) do
  2981.  
  2982.                PUT_LINE ("Body stub for STUBTEST.T");
  2983.  
  2984.             end T;
  2985.          or
  2986.  
  2987.             terminate;
  2988.  
  2989.          end select;
  2990.       end loop;
  2991.       --comment before end of task type o
  2992.  
  2993.    end O;  -- body
  2994.  
  2995.  
  2996.  
  2997.    function  U (ARG1, ARG2 : in CALENDAR.TIME) return CALENDAR.TIME is
  2998.  
  2999.       DUMMY : CALENDAR.TIME;
  3000.  
  3001.    begin          -- U
  3002.       PUT_LINE ("Body stub for STUBTEST.U");
  3003.       return DUMMY;
  3004.  
  3005.    exception
  3006.       when others =>
  3007.          PUT_LINE ("Unhandled exception in STUBTEST.U");
  3008.          raise;
  3009.    end U;
  3010.  
  3011.  
  3012.    procedure V (ARG1, ARG2 : in INTEGER := INTEGER'FIRST;
  3013.                 ARG3 : in FLOAT := 16#1_000.0#E0;
  3014.                 ARG4 : STRING := "";
  3015.                 ARG5 : CHARACTER := ''';
  3016.                 ARG6 : CHARACTER := CHARACTER'VAL (CHARACTER'POS ('''));
  3017.                 ARG7 : INTEGER := (INTEGER'LAST mod (2 ** 4));
  3018.                 ARG8 : STRING := (1 => 'a', 2 => ''');
  3019.                 ARG9 : STRING := """inside""";
  3020.                 ARGA : in out INTEGER) is
  3021.  
  3022.    begin          -- V
  3023.       PUT_LINE ("Body stub for STUBTEST.V");
  3024.  
  3025.    exception
  3026.       when others =>
  3027.          PUT_LINE ("Unhandled exception in STUBTEST.V");
  3028.          raise;
  3029.    end V;
  3030.  
  3031.  
  3032. --   type VERY_LONG_TYPE_NAME_FOR_THE_FUNCTION_RESULT_TYPE         is new
  3033. -- INTEGER;
  3034. --   type VERY_LONG_TYPE_NAME_FOR_THE_ARGUMENTS is
  3035. -- new
  3036. --   INTEGER;
  3037.  
  3038.    function
  3039.    THIS_IS_A_VERY_VERY_LONG_FUNCTION_NAME_SEE_IF_IT_IS_HANDLED_PROPERLY
  3040.    (LONG_ARGUMENT_NAME_1, LONG_ARGUMENT_NAME_2, LONG_ARGUMENT_NAME_3,
  3041.    LONG_ARGUMENT_NAME_4 : in INTEGER;
  3042.  
  3043.      LONG_ARGUMENT_NAME_5, LONG_ARGUMENT_NAME_6, LONG_ARGUMENT_NAME_7,
  3044.    LONG_ARGUMENT_NAME_8 : in VERY_LONG_TYPE_NAME_FOR_THE_ARGUMENTS) return
  3045.    VERY_LONG_TYPE_NAME_FOR_THE_FUNCTION_RESULT_TYPE is --sure is a long function
  3046.  
  3047.       DUMMY : VERY_LONG_TYPE_NAME_FOR_THE_FUNCTION_RESULT_TYPE;
  3048.  
  3049.    begin
  3050.       PUT_LINE ("Body stub for STUBTEST." &
  3051. "THIS_IS_A_VERY_VERY_LONG_FUNCTION_NAME_SEE_IF_IT_IS_HANDLED_PROPERLY");
  3052.       return DUMMY;
  3053.  
  3054.    exception
  3055.       when others =>
  3056.          PUT_LINE ("Unhandled exception in STUBTEST." &
  3057. "THIS_IS_A_VERY_VERY_LONG_FUNCTION_NAME_SEE_IF_IT_IS_HANDLED_PROPERLY");
  3058.          raise;
  3059.    end THIS_IS_A_VERY_VERY_LONG_FUNCTION_NAME_SEE_IF_IT_IS_HANDLED_PROPERLY;
  3060.  
  3061.  
  3062. --private
  3063.    --comment in private part
  3064. --   pragma INTERFACE(ASSEMBLER, INTERFACED);
  3065.  
  3066. end STUBTEST;  -- body
  3067.  
  3068.  
  3069.  
  3070. --comments before the procedure finish
  3071. with TEXT_IO; use TEXT_IO;
  3072. procedure FINISH is
  3073.  
  3074. begin          -- FINISH
  3075.    PUT_LINE ("Body stub for FINISH");
  3076.  
  3077. exception
  3078.    when others =>
  3079.       PUT_LINE ("Unhandled exception in FINISH");
  3080.       raise;
  3081. end FINISH;
  3082.  
  3083.  
  3084.  
  3085.