home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / stubs / stubber.src < prev   
Encoding:
Text File  |  1988-05-03  |  79.4 KB  |  1,809 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --rosdep.txt
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. --                                                                    -- 
  5. --                     package ROS_DEPENDENCIES                       --
  6. --                                                                    --
  7. ------------------------------------------------------------------------
  8. ------------------------------------------------------------------------
  9. with TEXT_IO;  use TEXT_IO; 
  10. package ROS_DEPENDENCIES is 
  11.   
  12.   
  13.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  14.   --                                                                  --
  15.   --    Package ROS_DEPENDENCIES is designed to support all of the    --
  16.   --    packages that use file input/output with the ROS operating    --
  17.   --    system.  It includes all of the peculiarities and machine-    --
  18.   --    dependencies that are not part of the Ada language.  These    --
  19.   --    include getting characters (GETC), indentation of lines in    --
  20.   --    the ROS editor (INDENT_CHECK, PUT_NEW_LINE), and new OPEN,    --
  21.   --    CREATE, and CLOSE(-UP) commands which automatically trans-    --
  22.   --    late file names (from GET_FILENAME) to suit the ROS filer.    --
  23.   --                                                                  --
  24.   --    The package was written so that a programmer needs to only    --
  25.   --    change this package to meet another system,  to use any of    --
  26.   --    the other packages written by this author.                    --
  27.   --                                                                  --
  28.   --    The compiler used in making this package was far from com-    --
  29.   --    plete, so the solution is not necessarily the most elegant    --
  30.   --    one the author could have used.   Also, the compiler still    --
  31.   --    followed the 1982 non-ANSI standard Ada.                      --
  32.   --                                                                  --
  33.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  34.   --    Date  :  15 July 1983                                         --
  35.   --                                                                  --
  36.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  37.   
  38.   
  39.   
  40.   procedure GETC (FILE      : in FILE_TYPE;             -- required due to the 
  41.                   CHAR      : out character;                  -- compiler
  42.                   POSITION  : in out integer); 
  43.   
  44.   procedure INDENT_CHECK (INF       : in FILE_TYPE;     -- required due to the
  45.                           CHAR1,                                -- editor
  46.                           CHAR2     : in out character;
  47.                           POSITION  : in out integer); 
  48.   
  49.   procedure PUT_END_LINE (OUTF  : in FILE_TYPE);             -- same as above
  50.   
  51.   procedure PUT_NEW_LINE (OUTF    : in FILE_TYPE;            -- same as above
  52.                           SPACES  : integer); 
  53.   
  54.   package ROS_FILE_OPS is                          -- all required due to 
  55.                                                    -- the filer
  56.     
  57.     subtype NAME_TYPE    is string (1..72); 
  58.     
  59.     type LONG_FILE_NAME  is record 
  60.       name    : NAME_TYPE; 
  61.       LENGTH  : natural; 
  62.     end record; 
  63.     
  64.     
  65.     procedure GET_FILENAME (LONG_NAME  : out LONG_FILE_NAME); 
  66.     
  67.     procedure open (FILE_NAME  : in out FILE_TYPE; 
  68.                     LONG_NAME  : in LONG_FILE_NAME; 
  69.                     SUFFIX     : in string); 
  70.     
  71.     procedure create (FILE_NAME  : in out FILE_TYPE; 
  72.                       LONG_NAME  : in LONG_FILE_NAME; 
  73.                       SUFFIX     : in string); 
  74.     
  75.     procedure CLOSE_UP (FILE_NAME  : in out FILE_TYPE); 
  76.     
  77.     -- All other file operations are the same as TEXT_IO
  78.     -- versions, so are not needed here.
  79.     
  80.   end ROS_FILE_OPS;  -- specifications.
  81.   
  82.   
  83. end ROS_DEPENDENCIES;  -- specifications.
  84.  
  85.  
  86.  
  87.  
  88. ------------------- package body ROS_DEPENDENCIES ----------------------
  89. ------------------------------------------------------------------------
  90. with text_io; use text_io;
  91. package body ROS_DEPENDENCIES is 
  92.  
  93.   ENDFILE  : constant character := character'VAL (28); 
  94.   
  95.   
  96.   ----------------------------------------------------------------------
  97.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  98.   ----------------------------------------------------------------------
  99.   package body ROS_FILE_OPS is 
  100.           ---------------------------------------------------------
  101.           --  This package contains all of the procedures that   --
  102.           --  are necessary for using files with the ROS filer   --
  103.           --  system.                                            --
  104.           ---------------------------------------------------------
  105.   
  106.     DUMMY_CHAR     : character; 
  107.     
  108.     
  109.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  110.     procedure GET_FILENAME (LONG_NAME  : out LONG_FILE_NAME) is 
  111.                     ------------------------------------------
  112.                     --  This procedure accepts input from   --
  113.                     --  the terminal for a correct system   --
  114.                     --  file name.                          --
  115.                     ------------------------------------------
  116.     
  117.       CHAR  : character; 
  118.  
  119.       INPUT_LINE : STRING(1..72);
  120.       LENGTH_OF_INPUT : NATURAL;
  121.       
  122.       begin 
  123.         for CHAR in NAME_TYPE'RANGE loop      -- zero out string
  124.           LONG_NAME.name (CHAR) := ' '; 
  125.         end loop; 
  126.         LONG_NAME.LENGTH := 0; 
  127.         CHAR := 'a'; 
  128.         
  129.         put ("enter name of file (suffix .TXT; assumed) : "); 
  130.         
  131.         GET_LINE(INPUT_LINE, LENGTH_OF_INPUT);
  132.         for I in 1..LENGTH_OF_INPUT  loop
  133.           CHAR := INPUT_LINE(I);
  134.           
  135.         --  File names can only have a certain set of characters in them.
  136.         --  This part only adds legal characters to the filename.
  137.           
  138.           if ((CHAR = ' ') and (LONG_NAME.LENGTH /= 0)) or (((CHAR = ':') or 
  139.                     (CHAR in '0'..'9')) and (LONG_NAME.LENGTH > 1)) or ((CHAR 
  140.                     = '_') and (LONG_NAME.LENGTH /= 0)) or (CHAR in 'a'..'z') 
  141.                     or (CHAR in 'A'..'Z') then 
  142.             LONG_NAME.LENGTH := LONG_NAME.LENGTH + 1;
  143.             LONG_NAME.name (LONG_NAME.LENGTH) := CHAR; 
  144.             
  145.           elsif CHAR = character'VAL (8) then   -- account for backspaces
  146.             LONG_NAME.LENGTH := LONG_NAME.LENGTH - 1; 
  147.           end if; 
  148.         end loop; 
  149.         new_line; 
  150.       end GET_FILENAME; 
  151.       
  152.       
  153.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  154.     procedure ADD_SUFFIX (LONG_NAME  : in out LONG_FILE_NAME; 
  155.                           SUFFIX     : in string) is 
  156.                     ------------------------------------------
  157.                     --  This procedure adds the necessary   --
  158.                     --  suffix to the name that the user    --
  159.                     --  gave in GET_FILENAME to make it a   --
  160.                     --  legal system file name.             --
  161.                     ------------------------------------------
  162.     
  163.       begin 
  164.         for COUNT in positive loop 
  165.           LONG_NAME.name (LONG_NAME.LENGTH + 1) := SUFFIX (COUNT); 
  166.           LONG_NAME.LENGTH := LONG_NAME.LENGTH + 1; 
  167.         end loop; 
  168.         
  169.       exception 
  170.         when CONSTRAINT_ERROR => 
  171.             -- uses this to exit the "for COUNT" loop, since it is not
  172.             -- possible to determine beforehand the range on the suffix.
  173.           LONG_NAME.LENGTH := LONG_NAME.LENGTH + 4;
  174.           LONG_NAME.NAME (LONG_NAME.LENGTH - 3..LONG_NAME.LENGTH) := ".TXT";
  175.           
  176.       end ADD_SUFFIX; 
  177.       
  178.       
  179.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  180.     procedure open (FILE_NAME  : in out FILE_TYPE; 
  181.                     LONG_NAME  : in LONG_FILE_NAME; 
  182.                     SUFFIX     : in string) is 
  183.                     ------------------------------------------
  184.                     --  This procedure opens a file with    --
  185.                     --  the name LONG_NAME, and the suffix  --
  186.                     --  SUFFIX.                             --
  187.                     ------------------------------------------
  188.     
  189.       DUMMY_NAME  : LONG_FILE_NAME; 
  190.       
  191.       begin 
  192.         DUMMY_NAME := LONG_NAME; 
  193.         ADD_SUFFIX (DUMMY_NAME, SUFFIX); 
  194.         
  195.                                   -- All of the garbage below was necessary
  196.                                   -- because the compiler didn't allow the
  197.                                   -- programmer to open a file using a string
  198.         OPEN_FILE_BLOCK :         -- of length unknown at compilation time,
  199.                                   -- unless it was in a block.
  200.         declare 
  201.           subtype SHORT_FILE_NAME  is string (1..DUMMY_NAME.LENGTH); 
  202.           SHORT_NAME  : SHORT_FILE_NAME; 
  203.         begin 
  204.           SHORT_NAME := DUMMY_NAME.name (1..DUMMY_NAME.LENGTH); 
  205.           TEXT_IO.open (FILE_NAME, IN_FILE, SHORT_NAME); 
  206.         end OPEN_FILE_BLOCK; 
  207.         
  208.       end open; 
  209.       
  210.       
  211.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  212.     procedure create (FILE_NAME  : in out FILE_TYPE; 
  213.                       LONG_NAME  : in LONG_FILE_NAME; 
  214.                       SUFFIX     : in string) is 
  215.                     ------------------------------------------
  216.                     -- This procedure creates a file with   --
  217.                     -- the name LONG_NAME and the suffix    --
  218.                     -- SUFFIX.                              --
  219.                     ------------------------------------------
  220.     
  221.       DUMMY_NAME  : LONG_FILE_NAME; 
  222.       
  223.       begin 
  224.         DUMMY_NAME := LONG_NAME; 
  225.         ADD_SUFFIX (DUMMY_NAME, SUFFIX); 
  226.         
  227.         CREATE_FILE_BLOCK :        -- see OPEN for explanation.
  228.         declare 
  229.           subtype SHORT_FILE_NAME  is string (1..DUMMY_NAME.LENGTH); 
  230.           SHORT_NAME  : SHORT_FILE_NAME; 
  231.         begin 
  232.           SHORT_NAME := DUMMY_NAME.name (1..DUMMY_NAME.LENGTH); 
  233.           TEXT_IO.create (FILE_NAME, OUT_FILE, SHORT_NAME); 
  234.         end CREATE_FILE_BLOCK; 
  235.         
  236.       end create; 
  237.       
  238.       
  239.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  240.     procedure CLOSE_UP (FILE_NAME  : in out FILE_TYPE) is 
  241.                     -----------------------------------------------
  242.                     -- This procedure closes FILE_NAME.          --
  243.                     -----------------------------------------------
  244.     
  245.       begin 
  246.         close (FILE_NAME);                     -- before closing it.
  247.       end CLOSE_UP; 
  248.       
  249.       
  250.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  251.     begin  -- ROS_FILE_OPS initializations
  252.       SET_INPUT(STANDARD_INPUT);
  253.     end ROS_FILE_OPS;  -- body.
  254.     
  255.   ----------------------------------------------------------------------
  256.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  257.   ----------------------------------------------------------------------
  258.     
  259.     
  260.   ----------------------------------------------------------------------
  261.   procedure GETC (FILE      : in FILE_TYPE; 
  262.                   CHAR      : out character; 
  263.                   POSITION  : in out integer) is 
  264.           ---------------------------------------------------------
  265.           --  This procedure gets one character, CHAR, from the  --
  266.           --  file FILE, and also returns its position, POSITION.--
  267.           ---------------------------------------------------------
  268.   
  269.     begin     -- GETC
  270.       
  271.       -- The real reason why this procedure is in this particular package
  272.       -- is that there was evidently a quirk in the compiler used -- the
  273.       -- GET command would not get control characters.  When this quirk is
  274.       -- remedied, this procedure should be removed, a "get" substituted for
  275.       -- the "read", and the whole sequence of statements should be moved
  276.       -- to replace the procedure call, wherever it is found.
  277.  
  278.       -- I AM JUST FAKING IT FOR VAX, GET BUT NO CONTROLS  WAW
  279.       
  280. if END_OF_FILE(FILE)  then
  281.   raise END_ERROR;
  282. elsif END_OF_LINE(FILE)  then
  283.   CHAR := CHARACTER'VAL(13);
  284.   SKIP_LINE(FILE);
  285. else
  286.  
  287. --  #######################################################################
  288.       get (FILE, CHAR); 
  289.       while CHAR = character'VAL (0) loop  -- eliminate all the nulls
  290.       
  291. if END_OF_FILE(FILE)  then
  292.   raise END_ERROR;
  293. end if;
  294. if END_OF_LINE(FILE)  then
  295.   CHAR := CHARACTER'VAL(13);
  296.   SKIP_LINE(FILE);
  297.   exit;
  298. end if;
  299.         get (FILE, CHAR); 
  300.       end loop; 
  301. end if;
  302.       
  303.       POSITION := POSITION + 1; 
  304.  
  305.     exception
  306.       when END_ERROR  =>                 --  Expected at end of file
  307.       raise;
  308.         when others  =>
  309.         put("unexpected exception in ROS_DEPENDENCIES.GETC"); new_line;
  310.       raise;
  311.     end GETC; 
  312.     
  313.     
  314.   ----------------------------------------------------------------------
  315.   procedure INDENT_CHECK (INF       : in FILE_TYPE; 
  316.                           CHAR1,
  317.                           CHAR2     : in out character;
  318.                           POSITION  : in out integer) is 
  319.           ---------------------------------------------------------
  320.           --  This procedure accounts for the unusual way that   --
  321.           --  the system editor indicates automatic indentation. --
  322.           --  If it just uses blanks, this procedure may be null.--
  323.           ---------------------------------------------------------
  324.   
  325.     begin 
  326.       null;    end INDENT_CHECK; 
  327.     
  328.     
  329.   ----------------------------------------------------------------------
  330.   procedure PUT_END_LINE (OUTF  : in FILE_TYPE) is 
  331.           ---------------------------------------------------------
  332.           -- This procedure outputs an end of line indicator to  --
  333.           -- the file OUTF.                                      --
  334.           ---------------------------------------------------------
  335.   
  336.     begin 
  337.       NEW_LINE(OUTF);
  338.     end PUT_END_LINE; 
  339.     
  340.     
  341.   ----------------------------------------------------------------------
  342.   procedure PUT_NEW_LINE (OUTF    : in FILE_TYPE; 
  343.                           SPACES  : integer) is 
  344.           ---------------------------------------------------------
  345.           -- This procedure starts a new line in the file OUTF,  --
  346.           -- using the system indentation indicators.            --
  347.           ---------------------------------------------------------
  348.   
  349.     begin 
  350.       for I in 1..SPACES  loop
  351.         PUT(OUTF, ' ');
  352.       end loop;
  353.     end PUT_NEW_LINE; 
  354.     
  355. end ROS_DEPENDENCIES; 
  356. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  357. --getoken.txt
  358. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  359. --                                                                    -- 
  360. --                          package GETTOKEN                          --
  361. --                                                                    --
  362. ------------------------------------------------------------------------
  363. ------------------------------------------------------------------------
  364. with TEXT_IO;  use TEXT_IO; 
  365. package GETTOKEN is 
  366.   
  367.   
  368.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  369.   --                                                                  --
  370.   --    Package GETTOKEN is designed to scan a string of characters   --
  371.   --    in a file, and split it up into tokens.  The only available   --
  372.   --    procedure is GET_TOKEN, which finds one token.  The package   --
  373.   --    is general enough to scan command files, but is designed to   --
  374.   --    scan Ada code, specifically.                                  --
  375.   --                                                                  --
  376.   --    All of the compiler peculiarities, editor dependencies, and   --
  377.   --    filer dependencies  have been moved to the ROS_DEPENDENCIES   --
  378.   --    package, with the exception of any peculiarities that might   --
  379.   --    occur due to using 1982 non-ANSI standard Ada.                --
  380.   --                                                                  --
  381.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  382.   --    Date  :  15 July 1983                                         --
  383.   --                                                                  --
  384.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  385.   
  386.   
  387.   
  388.   END_FILE       : constant character := character'VAL (3);
  389.   END_OF_LINE    : constant character := character'VAL (13); 
  390.   BLANK_LINE     : constant character := character'VAL (17); 
  391.   
  392.   STRING_LENGTH  : constant integer := 250; 
  393.   subtype LENGTH_TYPE  is integer range 0..STRING_LENGTH; 
  394.   type CLASS_TYPE is (NUMBER,      WORD,        DELIM,       COMMENT,     
  395.                       END_OF_FILE, NONE                                     ); 
  396.   
  397.   type STRING_RECORD   is record 
  398.     STR_ZERO  : character := END_OF_LINE;    --  ########
  399.     STR       : string (1..STRING_LENGTH); 
  400.     LENGTH    : LENGTH_TYPE := 0; 
  401.     CLASS     : CLASS_TYPE := NONE; 
  402.     POSITION  : LENGTH_TYPE;    -- actual position in text (for comments)
  403.   end record; 
  404.   
  405.   
  406.   procedure GET_TOKEN (INPUT_FILE  : FILE_TYPE; 
  407.                        ECHO_FILE   : FILE_TYPE; 
  408.                        TOKEN       : in out STRING_RECORD); 
  409.   
  410.   procedure GET_TOKEN (INPUT_FILE  : FILE_TYPE; 
  411.                        TOKEN       : in out STRING_RECORD); 
  412.   
  413. end GETTOKEN; 
  414.  
  415.  
  416. ------------------------------------------------------------------------
  417. ----------------------- package body GETOKEN ---------------------------
  418. ------------------------------------------------------------------------
  419. with text_io; use text_io;
  420. with ROS_DEPENDENCIES;  use ROS_DEPENDENCIES; 
  421. package body GETTOKEN is 
  422.   use ROS_FILE_OPS; 
  423. use integer_io;
  424.   
  425.   subtype ARRAY_RANGE is integer range 0..STRING_LENGTH;
  426.   type CHECK_ARRAY   is array (ARRAY_RANGE) of character;
  427.   type CHECK_RECORD  is record 
  428.     CH   : CHECK_ARRAY; 
  429.     NUM  : ARRAY_RANGE;
  430.   end record; 
  431.   
  432.   TOKEN_STORAGE,
  433.   DELIMITERS, 
  434.   LETTERS, 
  435.   NUMBERS           : CHECK_RECORD; 
  436.   
  437.   GARBAGE_FILE      : FILE_TYPE; 
  438.   
  439.   
  440.   ----------------------------------------------------------------------
  441.   procedure LOAD_RECORD (DELS, LETS, NUMS  : out CHECK_RECORD) is 
  442.           ---------------------------------------------------------
  443.           -- This procedure loads the arrays of delimiters, let- --
  444.           -- ters, and numbers so that they can be separated.    --
  445.           ---------------------------------------------------------
  446.   
  447.     begin 
  448.       for I in 1..10 loop 
  449.         NUMS.CH (I) := character'VAL (I + 47); 
  450.       end loop; 
  451.       NUMS.CH (11) := '_'; 
  452.       NUMS.CH (12) := '.'; 
  453.       NUMS.NUM := 12; 
  454.       
  455.       for I in 1..26 loop 
  456.         LETS.CH (I) := character'VAL (I + 64); 
  457.         LETS.CH (I + 26) := character'VAL (I + 96); 
  458.       end loop; 
  459.       LETS.CH (53) := '_'; 
  460.       LETS.NUM := 53; 
  461.       
  462.       DELS.CH (1) := '"'; 
  463.       DELS.CH (2) := ','; 
  464.       DELS.CH (3) := '&'; 
  465.       DELS.CH (4) := '''; 
  466.       DELS.CH (5) := '('; 
  467.       DELS.CH (6) := ')'; 
  468.       
  469.       DELS.CH (7) := '*'; 
  470.       DELS.CH (8) := '+'; 
  471.       DELS.CH (09) := '-'; 
  472.       DELS.CH (10) := '/'; 
  473.       DELS.CH (11) := ':'; 
  474.       DELS.CH (12) := ';'; 
  475.       
  476.       DELS.CH (13) := '<'; 
  477.       DELS.CH (14) := '>'; 
  478.       DELS.CH (15) := '=';                -- Spaces and end-of-line indicators
  479.       DELS.CH (16) := '|';                -- are not included in the delimiters
  480.       DELS.CH (17) := '.';                -- since the language does not require
  481.       DELS.CH (18) := BLANK_LINE;         -- them.  The BLANK_LINE is left as a
  482.                                           -- delimiter because it would be lost
  483.       DELS.NUM := 18;                     -- if it wasn't.
  484.       
  485.     end LOAD_RECORD; 
  486.     
  487.     
  488.   ----------------------------------------------------------------------
  489.   function IS_IN (CH    : character; 
  490.                   ARRY  : CHECK_RECORD) return boolean is 
  491.           ---------------------------------------------------------
  492.           --  This function determines whether a character, CH,  --
  493.           --  is in a certain group (ARRY) or not.               --
  494.           ---------------------------------------------------------
  495.   
  496.     IN_ARRY  : boolean; 
  497.     
  498.     begin 
  499.       IN_ARRY := false; 
  500.       for I in 1..ARRY.NUM loop         -- your basic search with exit
  501.         if CH = ARRY.CH (I) then 
  502.           IN_ARRY := true; 
  503.           exit; 
  504.         end if; 
  505.       end loop; 
  506.       return IN_ARRY; 
  507.     end IS_IN; 
  508.     
  509.     
  510.     
  511.   ----------------------------------------------------------------------
  512.   procedure GET_TOKEN (INPUT_FILE  : FILE_TYPE; 
  513.                        ECHO_FILE   : FILE_TYPE; 
  514.                        TOKEN       : in out STRING_RECORD) is 
  515.           ---------------------------------------------------------
  516.           --  This procedure is the meat of the package:  it is  --
  517.           --  a scanner that finds one token (TOKEN) in the      --
  518.           --  input file (INPUT_FILE), making sure that it does  --
  519.           --  not look ahead, or else characters will be lost.   --
  520.           ---------------------------------------------------------
  521.   
  522.     type STATE_TYPE is (START_STATE,     NUMBER_STATE,    WORD_STATE,      
  523.                         DELIMITER_STATE, FINAL_STATE                  ); 
  524.     PRESENT_STATE     : STATE_TYPE;       -- see explanation below
  525.     
  526.     CURRENT_POSITION  : LENGTH_TYPE := 1; -- the location of the current
  527.                                           -- character on the line, of the
  528.                                           -- input file
  529.     CHAR              : character; 
  530.     DOUBLE_PERIOD     : constant character := character'VAL (1);  -- see below
  531.     
  532.     
  533.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  534.     procedure GET_CHAR (CH    : out character; 
  535.                         INF   : FILE_TYPE) is 
  536.                     ------------------------------------------
  537.                     --  This procedure gets one character   --
  538.                     --  from the input file (INF).          --
  539.                     ------------------------------------------
  540.     
  541.       DUMMY_CH : character := character'VAL(0);
  542.       
  543.       begin 
  544.         ROS_DEPENDENCIES.GETC (INF, CH, CURRENT_POSITION); 
  545.         TOKEN_STORAGE.NUM := TOKEN_STORAGE.NUM + 1;
  546.         TOKEN_STORAGE.CH (TOKEN_STORAGE.NUM)     := CH;
  547.  
  548.         if CH = END_OF_LINE then 
  549.           CURRENT_POSITION := 1; 
  550.           put ('.'); 
  551.           if TOKEN.STR_ZERO = END_OF_LINE and TOKEN.LENGTH = 0 then 
  552.             CH := BLANK_LINE; 
  553.           end if; 
  554.           
  555.           if TOKEN.LENGTH = 0 then        -- This is to tell if a comment is
  556.             TOKEN.STR_ZERO := END_OF_LINE; -- on its own line (see the FORMAT_
  557.           end if;                         -- SUPPORT package for details).
  558.         end if; 
  559.         
  560. --  This seems to be set up for the ROS system and ought to be scrubbed
  561.         ROS_DEPENDENCIES.INDENT_CHECK (INF, DUMMY_CH, CH, CURRENT_POSITION);
  562.         if DUMMY_CH /= character'VAL (0) then
  563.           TOKEN_STORAGE.NUM := TOKEN_STORAGE.NUM + 2;
  564.           TOKEN_STORAGE.CH (TOKEN_STORAGE.NUM - 1) := DUMMY_CH;
  565.           if CH = BLANK_LINE then
  566.             TOKEN_STORAGE.CH (TOKEN_STORAGE.NUM) := END_OF_LINE;
  567.           else
  568.             TOKEN_STORAGE.CH (TOKEN_STORAGE.NUM) := CH;
  569.           end if;
  570.         end if;
  571.         
  572.       exception 
  573.         when END_ERROR => 
  574.           CH := character'VAL (3); 
  575.           CLOSE_UP (GARBAGE_FILE); 
  576.         when others  =>
  577.           put("unexpected exception in GETTOKEN.GET_TOKEN.GET_CHAR"); new_line;
  578.           raise;
  579.       end GET_CHAR; 
  580.       
  581.       
  582.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  583.     procedure ADD_ON (CH    : in out character; 
  584.                       ST    : in out STRING_RECORD; 
  585.                       INF   : FILE_TYPE) is 
  586.                     --------------------------------------------
  587.                     --  This procedure adds the character CH  --
  588.                     --  to the token string (ST), and calls   --
  589.                     --  GET_CHAR for the next character.      --
  590.                     --------------------------------------------
  591.     
  592.       begin 
  593.         ST.LENGTH := ST.LENGTH + 1; 
  594.         ST.STR (ST.LENGTH) := CH; 
  595.         if CH = BLANK_LINE then 
  596.           CH := END_OF_LINE; 
  597.         else 
  598.           GET_CHAR (CH, INF); 
  599.         end if; 
  600.       end ADD_ON; 
  601.       
  602.       
  603.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  604.     begin   --  GET_TOKEN
  605.       for I in 1..TOKEN_STORAGE.NUM - 1 loop
  606.         if TOKEN_STORAGE.CH(I) = END_OF_LINE  or
  607.            TOKEN_STORAGE.CH(I) = BLANK_LINE   then
  608.           new_line(ECHO_FILE);
  609.         else
  610.           put (ECHO_FILE, TOKEN_STORAGE.CH (I));
  611.         end if;
  612.       end loop;
  613.       TOKEN_STORAGE.CH (1) := TOKEN_STORAGE.CH (TOKEN_STORAGE.NUM);
  614.       TOKEN_STORAGE.NUM := 1;
  615.       CHAR := TOKEN.STR_ZERO;    -- This one statement is the key to the whole
  616.                                  -- algorithm:  TOKEN.ST_ZERO holds the 
  617.                                  -- character that stopped the algorithm the
  618.                                  -- last time it went through.  Otherwise, 
  619.                                  -- that character would be lost.
  620.       for I in 1..TOKEN.LENGTH + 1 loop 
  621.         TOKEN.STR (I) := ' '; 
  622.       end loop; 
  623.       TOKEN.LENGTH := 0; 
  624.                                                 -- The basic algorithm is done
  625.       PRESENT_STATE := START_STATE;             -- by tracing through a state
  626.                                                 -- diagram.
  627.       while PRESENT_STATE /= FINAL_STATE loop 
  628.         case PRESENT_STATE is                   -- In Ada one can tell whether
  629.                                                 -- a token will be a delimiter,
  630.                                                 -- number, or word, just by
  631.                                                 -- looking at the first char.
  632.           when START_STATE => 
  633.             if IS_IN (CHAR, DELIMITERS) then 
  634.               if CHAR /= BLANK_LINE then 
  635.                 TOKEN.POSITION := CURRENT_POSITION - 1; 
  636.               end if;                           -- The position of a token is
  637.               TOKEN.CLASS := DELIM;             -- going to be the position of
  638.                                                 -- the first character in that
  639.                                                 -- string, which is one less
  640.                                                 -- than the current position.
  641.               PRESENT_STATE := DELIMITER_STATE; 
  642.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  643.               
  644.             elsif IS_IN (CHAR, LETTERS) then 
  645.               TOKEN.POSITION := CURRENT_POSITION - 1; 
  646.               TOKEN.CLASS := WORD; 
  647.               PRESENT_STATE := WORD_STATE; 
  648.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  649.               
  650.             elsif IS_IN (CHAR, NUMBERS) then 
  651.               TOKEN.POSITION := CURRENT_POSITION - 1; 
  652.               TOKEN.CLASS := NUMBER; 
  653.               PRESENT_STATE := NUMBER_STATE; 
  654.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  655.               
  656.             elsif CHAR = END_FILE then
  657.               TOKEN.CLASS := end_of_file; 
  658.               if TOKEN.STR_ZERO = END_FILE then -- If the procedure gets to this
  659.                 raise END_ERROR;                -- point (two end-of-file indi-
  660.               end if;                           -- cators in a row), the program
  661.                                                 -- being scanned has an error in
  662.                                                 -- it somewhere, so an error is
  663.               PRESENT_STATE := FINAL_STATE;     -- propogated.
  664.               
  665.             elsif CHAR = DOUBLE_PERIOD then            -- This is needed because
  666.               TOKEN.STR (1..2) := "..";                -- if the current token
  667.               TOKEN.LENGTH := 2;                       -- is a number, then when
  668.               GET_CHAR (CHAR, INPUT_FILE);  -- it finds a period, it
  669.               PRESENT_STATE := FINAL_STATE;            -- needs to look ahead to
  670.                                                        -- see if the next char-
  671.                                                        -- acter is a period or
  672.                                                        -- the rest of a decimal
  673.                                                        -- number.  This is the
  674.                                                        -- only time I could not
  675.                                                        -- work around the look-
  676.                                                        -- ahead requirement.
  677.             else     -- space or end-of-line
  678.               
  679.               GET_CHAR (CHAR, INPUT_FILE); 
  680.             end if; 
  681.             
  682.             
  683.           when WORD_STATE => 
  684.             
  685.             --    word ::= letter {[under-score] letter|digit}
  686.             
  687.             if IS_IN (CHAR, LETTERS) or else (IS_IN (CHAR, NUMBERS) and
  688.                      CHAR /= '.') then 
  689.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  690.             else                             -- Please note that the algorithm
  691.               PRESENT_STATE := FINAL_STATE;  -- does not check to make sure the
  692.             end if;                          -- under-scores are isolated, since
  693.                                              -- it is assumed that the program
  694.                                              -- being scanned is syntactically
  695.                                              -- correct.
  696.           when NUMBER_STATE => 
  697.             
  698.             --   number ::= decimal_number | based_number
  699.             --   decimal_number ::= integer [.integer] [E{+|-}integer]
  700.             --   integer ::= digit {[under-score] digit}   -- see note above
  701.             --   based_number ::= integer # GARBAGE # [E{+|-}integer]
  702.             --     GARBAGE ::= anything, for all I care.
  703.  
  704.             if IS_IN (CHAR, NUMBERS) then 
  705.               if CHAR = '.' then 
  706.                 GET_CHAR (CHAR, INPUT_FILE); 
  707.                 if CHAR = '.' then          -- see explanation in START_STATE
  708.                   CHAR := DOUBLE_PERIOD;
  709.                   PRESENT_STATE := FINAL_STATE; 
  710.                 else 
  711.                   TOKEN.LENGTH := TOKEN.LENGTH + 1; 
  712.                   TOKEN.STR (TOKEN.LENGTH) := '.'; 
  713.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  714.                 end if; 
  715.               else 
  716.                 ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  717.               end if; 
  718.               
  719.             elsif CHAR = '#' then                          -- based number
  720.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  721.               while CHAR /= '#' loop 
  722.                 ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  723.               end loop; 
  724.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  725.               
  726.             elsif CHAR = 'E' then                          -- exponent
  727.               ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  728.               if CHAR = '+' or CHAR = '-' then 
  729.                 ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  730.               end if; 
  731.               
  732.             else 
  733.               PRESENT_STATE := FINAL_STATE; 
  734.             end if; 
  735.             
  736.             
  737.           when DELIMITER_STATE =>           -- This part takes advantage of the
  738.             PRESENT_STATE := FINAL_STATE;   -- fact that any delimiter can be
  739.             case TOKEN.STR (1) is           -- identified by looking at the 
  740.                                             -- first two characters of the 
  741.                                             -- string -- the one that was added
  742.                                             -- to the token already (T.STR(1)),
  743.                                             -- and the current character.  
  744.                                             -- Again, nothing is lost.
  745.               when '<' => 
  746.                 if CHAR = '=' or CHAR = '<' or CHAR = '>' then 
  747.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  748.                 end if; 
  749.                 
  750.               when '>' => 
  751.                 if CHAR = '=' or CHAR = '>' then 
  752.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  753.                 end if; 
  754.                 
  755.               when '=' => 
  756.                 if CHAR = '>' then 
  757.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  758.                 end if; 
  759.                 
  760.               when '/' | ':' => 
  761.                 if CHAR = '=' then 
  762.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  763.                 end if; 
  764.                 
  765.               when '*' => 
  766.                 if CHAR = '*' then 
  767.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  768.                 end if; 
  769.                 
  770.               when '.' => 
  771.                 if CHAR = '.' then 
  772.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  773.                 end if; 
  774.                 
  775.               when ''' =>      -- attribute indicator or character
  776.                 ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  777.                 if CHAR /= ''' then               -- fortunately, no attributes
  778.                                                   -- have < 3 characters.
  779.                   PRESENT_STATE := START_STATE;
  780.                 end if;                           -- Note that I cheated a bit
  781.                                                   -- here.  The algorithm will
  782.                                                   -- now go back, and recog-
  783.                                                   -- nize the token as a word,
  784.                                                   -- since the ' has been added
  785.                                                   -- to the token already.
  786.                 ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  787.                 
  788.               when '-' => 
  789.                 if CHAR = '-' then 
  790.                   TOKEN.CLASS := COMMENT; 
  791. CURRENT_POSITION := CURRENT_POSITION - 1;         --  #####################
  792.                   while CHAR /= END_OF_LINE loop 
  793.                     ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  794.                   end loop; 
  795.                   TOKEN.STR (TOKEN.LENGTH + 1) := TOKEN.STR_ZERO; -- This tells
  796.                           -- the formatter if the comment is on its own line.
  797.                           -- See FORMAT_SUPPORT package for details. 
  798.                 end if;
  799.                 
  800.               when '"' =>            -- string ::= " {anything} "
  801.                 while CHAR /= '"' loop 
  802.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  803.                 end loop; 
  804.                 ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  805.                 
  806.                     -- All of this garbage is to take of double quotes inside
  807.                     -- strings, and null strings.
  808.                 while CHAR = '"' loop 
  809.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  810.                   while CHAR /= '"' loop 
  811.                     ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  812.                   end loop; 
  813.                   ADD_ON (CHAR, TOKEN, INPUT_FILE); 
  814.                 end loop; 
  815.                 
  816.               when others => 
  817.                 null; 
  818.             end case; 
  819.             
  820.             
  821.           when FINAL_STATE => 
  822.             null; 
  823.             
  824.         end case; 
  825.       end loop; 
  826.       
  827.       if TOKEN.CLASS = WORD then         -- Convert words to all upper-case
  828.         for I in 1..TOKEN.LENGTH loop 
  829.           if character'POS (TOKEN.STR (I)) in 97..122 then 
  830.             TOKEN.STR (I) := character'VAL (character'POS (TOKEN.STR (I)) - 32);
  831.           end if; 
  832.         end loop; 
  833.       end if; 
  834.       TOKEN.STR_ZERO := CHAR;    -- see first comment in this procedure
  835.  
  836.     exception
  837.       when others  =>
  838.         put("unexpected exception in GETTOKEN.GET_TOKEN"); NEW_LINE;
  839.         RAISE;
  840.     end GET_TOKEN; 
  841.     
  842.     
  843.   ----------------------------------------------------------------------
  844.   procedure GET_TOKEN (INPUT_FILE  : FILE_TYPE; 
  845.                        TOKEN       : in out STRING_RECORD) is 
  846.           ---------------------------------------------------------
  847.           --  This procedure is used when no echo-file is re-    --
  848.           --  quired.  In this case, it makes up an echo-file,   --
  849.           --  and call the other procedure GET_TOKEN.            --
  850.           ---------------------------------------------------------
  851.   
  852.     begin 
  853.       GET_TOKEN (INPUT_FILE, GARBAGE_FILE, TOKEN); 
  854.     end GET_TOKEN; 
  855.     
  856.     
  857.   ----------------------------------------------------------------------
  858.   begin   -- initializations
  859.     LOAD_RECORD (DELIMITERS, LETTERS, NUMBERS); 
  860.     TEXT_IO.create (GARBAGE_FILE, OUT_FILE, "GARBAGE.TXT");    -- see above
  861.     TOKEN_STORAGE.NUM := 0;
  862.   end GETTOKEN; 
  863. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  864. --stubsup.txt
  865. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  866. --                     package STUBBER_SUPPORT                        --
  867. --                                                                    --
  868. ------------------------------------------------------------------------
  869. ------------------------------------------------------------------------
  870. with TEXT_IO;   use TEXT_IO; 
  871. with GETTOKEN;  use GETTOKEN; 
  872. package STUBBER_SUPPORT is 
  873.   
  874.   
  875.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  876.   --                                                                  --
  877.   --    Package STUBBER_SUPPORT is the support package for package    --
  878.   --    STUBBER (You wouldn't have guessed that by the title, now,    --
  879.   --    would you?).  It contains the procedures that initialize &    --
  880.   --    finalize things and the procedures that do the interaction    --
  881.   --    with the input_file.                                          --
  882.   --                                                                  --
  883.   --    All of the peculiarities that are due to the editor or the    --
  884.   --    filer have been moved to the ROS_DEPENDENCIES package. One    --
  885.   --    must also note that this set of packages was written using    --
  886.   --    a non ANSI-standard 1982 Ada compiler.  Also, the compiler    --
  887.   --    used did not implement many of the "nifty" things that Ada    --
  888.   --    supports, so this solution is not the most elegent one.       --
  889.   --                                                                  --
  890.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  891.   --    Date  :  15 July 1983                                         --
  892.   --                                                                  --
  893.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  894.   
  895.   
  896.   
  897.   type KEY_WORDS is (KW_PACKAGE,   KW_FUNCTION,  KW_PROCEDURE, 
  898.                      KW_BODY,      KW_ACCEPT,    KW_BEGIN,     
  899.                      KW_CASE,      KW_IF,        KW_LOOP,      
  900.                      KW_END,       KW_TYPE,      KW_FOR,       
  901.                      KW_USE,       KW_NEW,       KW_SEPARATE,  
  902.                      KW_IS,        KW_RECORD,    NOT_KW            ); 
  903.   
  904.   type BUFFER_TYPE;       
  905.   type BUFFER_PTR        is access BUFFER_TYPE; 
  906.   type BUFFER_TYPE       is record 
  907.     BUFFER_STRING  : GETTOKEN.STRING_RECORD; 
  908.     NEXT_ONE       : BUFFER_PTR := null; 
  909.   end record; 
  910.   
  911.   subtype DEC_TYPE       is KEY_WORDS range KW_PACKAGE..KW_PROCEDURE; 
  912.   
  913.   type DECLARATION_BUFF;  
  914.   type DECLARATION_PTR   is access DECLARATION_BUFF; 
  915.   type DECLARATION_BUFF  is record 
  916.     TYPE_OF_DEC    : DEC_TYPE; 
  917.     DEC_NAME       : STRING_RECORD; 
  918.     FORMAL_PART    : BUFFER_PTR      := null;   -- not used for packages
  919.     RETURN_TYPE    : STRING_RECORD;            -- used only for functions
  920.     INTERNAL_DECS  : DECLARATION_PTR := null; 
  921.     NEXT_DEC       : DECLARATION_PTR := null;    -- I explain all of this
  922.   end record;                                   -- nonsense in STUBBER.
  923.   
  924.   TOKEN        : STRING_RECORD; 
  925.   INPUT_FILE   : FILE_TYPE; 
  926.   OUTPUT_FILE  : FILE_TYPE; 
  927.   
  928.   function CONVERT (STR1  : STRING_RECORD) return KEY_WORDS; 
  929.   
  930.   procedure GET_ONE_TOKEN (INF    : FILE_TYPE; 
  931.                            OUTF   : FILE_TYPE; 
  932.                            TOKEN  : in out STRING_RECORD); 
  933.   
  934.   procedure INITIALIZE (OUTFILE_ID  : out STRING_RECORD); 
  935.   
  936.   procedure DUMP (FILE_ID  : STRING_RECORD); 
  937.   
  938.   procedure STUB (SPECIFICATION  : DECLARATION_PTR); 
  939.   
  940.   procedure GET_PAST_END;
  941.   
  942. end STUBBER_SUPPORT; 
  943.  
  944.  
  945. ------------------- package body STUBBER_SUPPORT -----------------------
  946. ------------------------------------------------------------------------
  947. with ROS_DEPENDENCIES;  use ROS_DEPENDENCIES; 
  948. package body STUBBER_SUPPORT is 
  949.   use ROS_FILE_OPS; 
  950.   
  951.   type KEYW_TYPE  is array (KW_PACKAGE..NOT_KW) of string (1..10); 
  952.   KW  : KEYW_TYPE; 
  953.  
  954.   FIRST_TIME_THROUGH_STUB : BOOLEAN;
  955.   
  956.   
  957.   ----------------------------------------------------------------------
  958.   procedure GET_ONE_TOKEN (INF    : FILE_TYPE; 
  959.                            OUTF   : FILE_TYPE; 
  960.                            TOKEN  : in out STRING_RECORD) is 
  961.           ---------------------------------------------------------
  962.           --  This procedure gets one token from the input file, --
  963.           --  making sure that it is not a comment or a blank    --
  964.           --  line (which would mix up the stubber itself).      --
  965.           ---------------------------------------------------------
  966.   
  967.     begin 
  968.       GET_TOKEN (INF, OUTF, TOKEN);   -- not much to it; just a call to
  969.                                       -- GET_TOKEN until its not a comment
  970.                                       -- or a blank line
  971.       while TOKEN.CLASS = COMMENT or TOKEN.STR (1) = GETTOKEN.BLANK_LINE loop
  972.         GET_TOKEN (INF, OUTF, TOKEN); 
  973.       end loop; 
  974.     end GET_ONE_TOKEN; 
  975.     
  976.     
  977.   ----------------------------------------------------------------------
  978.   procedure INITIALIZE (OUTFILE_ID  : out STRING_RECORD) is 
  979.           ---------------------------------------------------------
  980.           --  This procedure sets everything up for the STUBBER  --
  981.           --  procedure.  It saves the name of the input file    --
  982.           --  for future reference (OUTFILE_ID).                 --
  983.           ---------------------------------------------------------
  984.   
  985.     FILENAME    : ROS_FILE_OPS.LONG_FILE_NAME; 
  986.     
  987.     begin 
  988.       new_line; new_line; new_line; new_line; new_line; new_line;
  989.       new_line; new_line; new_line; new_line; new_line; new_line;
  990.       put ("                           STUBBER");
  991.       new_line; new_line;
  992.       put ("This program stubs anything in your program that needs to be");
  993.       new_line;
  994.       put ("stubbed.  You need do nothing to tell the stubber what needs");
  995.       new_line;
  996.       put ("to be stubbed; it figures it out by itself. It is imperative");
  997.       new_line; 
  998.       put ("that the program being stubbed is syntactically correct,  at");
  999.       new_line; 
  1000.       put ("least to the point that each 'if' has and 'end if', etc.  If");
  1001.       new_line;
  1002.       put ("this is not the case, then the stubber will self-destruct or");
  1003.       new_line;
  1004.       put ("worse than that, it will miss-stub your program.  This stub-");
  1005.       new_line;
  1006.       put ("ber will also keep you informed as to where it is and what's");
  1007.       new_line;
  1008.       put ("being stubbed.");
  1009.       new_line; new_line; new_line; new_line; new_line; new_line;
  1010.       GET_FILENAME (FILENAME); 
  1011.       ROS_FILE_OPS.open (INPUT_FILE, FILENAME, ""); 
  1012.       OUTFILE_ID.LENGTH := FILENAME.LENGTH; 
  1013.       OUTFILE_ID.STR (1..OUTFILE_ID.LENGTH) := FILENAME.NAME
  1014.                 (1..OUTFILE_ID.LENGTH); 
  1015.       ROS_FILE_OPS.create (OUTPUT_FILE, FILENAME, "2"); 
  1016. --  ####      PUT_NEW_LINE (OUTPUT_FILE, 0); 
  1017.       TOKEN.LENGTH := STRING_LENGTH - 1;       -- this will force a blank-out
  1018.       TOKEN.STR_ZERO:= GETTOKEN.END_OF_LINE; 
  1019.  
  1020. exception
  1021.   when others  =>
  1022.     put("Unhandled exception in STUBBER_SUPPORT.INITIALIZE"); new_line;
  1023.     raise;
  1024.     end INITIALIZE; 
  1025.     
  1026.     
  1027.   ----------------------------------------------------------------------
  1028.   procedure DUMP (FILE_ID  : STRING_RECORD) is 
  1029.           ---------------------------------------------------------
  1030.           --  This procedure finishes everything up.  It is the  --
  1031.           --  epitome of making procedures for the sole purpose  --
  1032.           --  of modularization.                                 --
  1033.           ---------------------------------------------------------
  1034.   
  1035.     begin 
  1036.       new_line; new_line; 
  1037.       put ("Your stubbed version is under "); 
  1038.       put (FILE_ID.STR (1..FILE_ID.LENGTH)); 
  1039.       put ("2.TXT;"); 
  1040.       new_line; 
  1041.       put ("Be sure to edit and save the file before printing it. "); 
  1042.       new_line; 
  1043.       put ("It is also recommended that you use the FORMAT set of ");
  1044.       new_line;
  1045.       put ("packages to format the stubbed version, once it is    ");
  1046.       new_line;
  1047.       put ("synactically perfect.");
  1048.       new_line;
  1049.       CLOSE_UP (OUTPUT_FILE); 
  1050.     end DUMP; 
  1051.     
  1052.     
  1053.   ----------------------------------------------------------------------
  1054.   procedure STUB (SPECIFICATION  : DECLARATION_PTR) is 
  1055.           ---------------------------------------------------------
  1056.           --  This procedure is the actual stub generator. Given --
  1057.           --  a specification, or set of specifications, as de-  --
  1058.           --  termined by SPECIFICATION, the procedure will      --
  1059.           --  generate the appropriate stub.                     --
  1060.           ---------------------------------------------------------
  1061.   
  1062.     CURRENT_DEC   : DECLARATION_PTR; 
  1063.     CURRENT_BUFF  : BUFFER_PTR; 
  1064.     
  1065.     
  1066.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1067.     procedure WRITE_ID (FILE  : FILE_TYPE; 
  1068.                         ID    : in STRING_RECORD) is 
  1069.                     ------------------------------------------
  1070.                     --  This procedure writes out an iden-  --
  1071.                     --  tifier when it is in a string.  It  --
  1072.                     --  is necessary for the case of over-  --
  1073.                     --  loaded operators, that have a '"'   --
  1074.                     --  as part of the name, so this has to --
  1075.                     --  be taken care of.                   --
  1076.                     ------------------------------------------
  1077.     
  1078.       begin 
  1079.         if ID.STR (1) = '"' then 
  1080.           put (FILE, '"');
  1081.           put (FILE, ID.STR (1..ID.LENGTH)); 
  1082.           put (FILE, '"');
  1083.         else
  1084.           put (FILE, ID.STR (1..ID.LENGTH)); 
  1085.         end if; 
  1086.       end WRITE_ID; 
  1087.       
  1088.       
  1089.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1090.     begin   -- STUB
  1091.       CURRENT_DEC := SPECIFICATION; 
  1092.       new_line (OUTPUT_FILE);
  1093.       new_line (OUTPUT_FILE);
  1094.       if FIRST_TIME_THROUGH_STUB  then
  1095.         FIRST_TIME_THROUGH_STUB := FALSE;
  1096.         put ( OUTPUT_FILE, "with TEXT_IO;  use TEXT_IO;");
  1097.         new_line (OUTPUT_FILE);
  1098.       end if;
  1099.       while CURRENT_DEC.NEXT_DEC /= null loop 
  1100.         new_line; 
  1101.         put ("Now stubbing "); 
  1102.         put (CURRENT_DEC.DEC_NAME.STR (1..CURRENT_DEC.DEC_NAME.LENGTH)); 
  1103.         case CURRENT_DEC.TYPE_OF_DEC is 
  1104.           when KW_PROCEDURE => 
  1105.             put (OUTPUT_FILE, "  procedure "); 
  1106.           when KW_FUNCTION => 
  1107.             put (OUTPUT_FILE, "  function "); 
  1108.           when KW_PACKAGE => 
  1109.             put (OUTPUT_FILE, "package body "); 
  1110.         end case; 
  1111.         
  1112.         put (OUTPUT_FILE, CURRENT_DEC.DEC_NAME.STR 
  1113.                   (1..CURRENT_DEC.DEC_NAME.LENGTH)); 
  1114.         
  1115.         if CURRENT_DEC.TYPE_OF_DEC = KW_PACKAGE then    -- stubbing a package
  1116.           put (OUTPUT_FILE, " is");                         --           body
  1117.           new_line (OUTPUT_FILE); 
  1118.           STUB (CURRENT_DEC.INTERNAL_DECS);   -- recursive call to handle the
  1119.                                               -- internal specifications
  1120.           new_line (OUTPUT_FILE); 
  1121.           put (OUTPUT_FILE, "end "); 
  1122.           put (OUTPUT_FILE, CURRENT_DEC.DEC_NAME.STR 
  1123.                     (1..CURRENT_DEC.DEC_NAME.LENGTH)); 
  1124.           put (OUTPUT_FILE, ";  -- body"); 
  1125.           new_line (OUTPUT_FILE); 
  1126.           
  1127.         else 
  1128.           CURRENT_BUFF := CURRENT_DEC.FORMAL_PART; 
  1129.           while CURRENT_BUFF /= null loop 
  1130.             put (OUTPUT_FILE, CURRENT_BUFF.BUFFER_STRING.STR 
  1131.                       (1..CURRENT_BUFF.BUFFER_STRING.LENGTH)); 
  1132.             CURRENT_BUFF := CURRENT_BUFF.NEXT_ONE; 
  1133.             if CURRENT_BUFF /= null then 
  1134.               new_line (OUTPUT_FILE); 
  1135.             end if; 
  1136.           end loop; 
  1137.           if CURRENT_DEC.TYPE_OF_DEC = KW_FUNCTION then 
  1138.             put (OUTPUT_FILE, " return "); 
  1139.             put (OUTPUT_FILE, CURRENT_DEC.RETURN_TYPE.STR 
  1140.                       (1..CURRENT_DEC.RETURN_TYPE.LENGTH)); 
  1141.           end if; 
  1142.           put (OUTPUT_FILE, " is"); 
  1143.           new_line (OUTPUT_FILE); 
  1144.           new_line (OUTPUT_FILE); 
  1145.           
  1146.           if CURRENT_DEC.TYPE_OF_DEC = KW_FUNCTION then      -- all functions
  1147.             put (OUTPUT_FILE, "  DUMMY : ");                 -- require a return
  1148.             put (OUTPUT_FILE, CURRENT_DEC.RETURN_TYPE.STR    -- statement to
  1149.                       (1..CURRENT_DEC.RETURN_TYPE.LENGTH));  -- compile, so to
  1150.  
  1151.           --  An attempt to put in default values for STANDARD types
  1152.           --  Ought to be done for derived types and composites of STANDARD
  1153.             if   CURRENT_DEC.RETURN_TYPE.STR
  1154.                     (1..CURRENT_DEC.RETURN_TYPE.LENGTH) = "INTEGER"  then
  1155.               put (OUTPUT_FILE, " := 1");
  1156.             elsif CURRENT_DEC.RETURN_TYPE.STR
  1157.                     (1..CURRENT_DEC.RETURN_TYPE.LENGTH) = "FLOAT"    then
  1158.               put (OUTPUT_FILE, " := 1.0");
  1159.             elsif    CURRENT_DEC.RETURN_TYPE.STR
  1160.                     (1..CURRENT_DEC.RETURN_TYPE.LENGTH) = "BOOLEAN"  then
  1161.               put (OUTPUT_FILE, " := TRUE");
  1162.             elsif    CURRENT_DEC.RETURN_TYPE.STR
  1163.                     (1..CURRENT_DEC.RETURN_TYPE.LENGTH) = "STRING"   then
  1164.               put (OUTPUT_FILE, " := ""STRING""");
  1165.             elsif    CURRENT_DEC.RETURN_TYPE.STR
  1166.                     (1..CURRENT_DEC.RETURN_TYPE.LENGTH) = "CHARACTER"  then
  1167.               put (OUTPUT_FILE, " := 'C'");
  1168.             end if;
  1169.  
  1170.             put (OUTPUT_FILE, ';');                         -- guarantee that
  1171.             new_line (OUTPUT_FILE);                        -- all types are
  1172.             new_line (OUTPUT_FILE);
  1173.           end if;                                         -- accounted for, a
  1174.                                                          -- dummy variable is
  1175.                                                         -- created and returned.
  1176.                                                        -- One must note that one
  1177.                                                       -- cannot run this func-
  1178.                                                      -- tion, since dummy is
  1179.                                                     -- never initialized (and 
  1180.                                                    -- for the same reasons it
  1181.                                                   -- was created, couldn't be),
  1182.                                                  -- but it will compile.
  1183.           put (OUTPUT_FILE, "  begin"); 
  1184.           new_line (OUTPUT_FILE); 
  1185.           put (OUTPUT_FILE, "    put (""I AM NOW IN "); 
  1186.           WRITE_ID (OUTPUT_FILE, CURRENT_DEC.DEC_NAME); 
  1187.           put (OUTPUT_FILE, """);"); 
  1188.           new_line (OUTPUT_FILE); 
  1189.           put (OUTPUT_FILE, "    new_line;"); 
  1190.           new_line (OUTPUT_FILE); 
  1191.  
  1192.           if CURRENT_DEC.TYPE_OF_DEC = KW_FUNCTION then 
  1193.             put (OUTPUT_FILE, "    return DUMMY;"); 
  1194.             new_line (OUTPUT_FILE); 
  1195.           end if; 
  1196.  
  1197.           new_line (OUTPUT_FILE); 
  1198.           put (OUTPUT_FILE, "  exception"); 
  1199.           new_line (OUTPUT_FILE); 
  1200.           put (OUTPUT_FILE, "    when others  =>"); 
  1201.           new_line (OUTPUT_FILE); 
  1202.           put (OUTPUT_FILE, "      put(""Unhandled exception in "); 
  1203.           put (OUTPUT_FILE, CURRENT_DEC.DEC_NAME.STR 
  1204.                     (1..CURRENT_DEC.DEC_NAME.LENGTH)); 
  1205.           put (OUTPUT_FILE, """);"); 
  1206.           new_line (OUTPUT_FILE); 
  1207.           put (OUTPUT_FILE, "      raise;"); 
  1208.           new_line (OUTPUT_FILE); 
  1209.  
  1210.           put (OUTPUT_FILE, "  end "); 
  1211.           put (OUTPUT_FILE, CURRENT_DEC.DEC_NAME.STR 
  1212.                     (1..CURRENT_DEC.DEC_NAME.LENGTH)); 
  1213.           put (OUTPUT_FILE, ';'); 
  1214.           new_line (OUTPUT_FILE); 
  1215.         end if; 
  1216.         CURRENT_DEC := CURRENT_DEC.NEXT_DEC; 
  1217.         new_line (OUTPUT_FILE);
  1218.         new_line (OUTPUT_FILE);
  1219.       end loop; 
  1220.  
  1221. exception
  1222.   when others  =>
  1223.     put("Unhandled exception in STUBBER_SUPPORT.STUB"); new_line;
  1224.     raise;
  1225.     end STUB; 
  1226.     
  1227.     
  1228.   ----------------------------------------------------------------------
  1229.   procedure GET_PAST_END is 
  1230.           ---------------------------------------------------------
  1231.           --  This procedure is designed to skip past tokens     --
  1232.           --  until it finds the word "end".  However, it must   --
  1233.           --  find the "end" that goes with the token that       --
  1234.           --  forced the procedure call in the first place.  So  --
  1235.           --  when it comes upon a word that will also have an   --
  1236.           --  "end" associated with it, it must get past that    --
  1237.           --  one, too.                                          --
  1238.           ---------------------------------------------------------
  1239.   
  1240.     begin 
  1241.       GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1242.       while CONVERT (TOKEN) /= KW_END loop 
  1243.         case CONVERT (TOKEN) is 
  1244.             
  1245.           when KW_ACCEPT | KW_BEGIN | KW_CASE | KW_IF | KW_LOOP | KW_RECORD => 
  1246.             GET_PAST_END; 
  1247.                                 -- This is a rather ingenious method of getting
  1248.                                -- through the body of a subprogram, record, or
  1249.                               -- whatever.  Every time a word is found that has
  1250.                              -- and "end" associated with it, the procedure
  1251.                             -- calls itself.
  1252.           when others => 
  1253.             null;
  1254.         end case; 
  1255.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1256.       end loop; 
  1257.       GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- This last GET_ONE is
  1258.                                                        -- to eliminate the 
  1259.                                                       -- possibility of the 
  1260.                                                      -- procedure finding the
  1261.                                                     -- "if" of an "end if", etc.
  1262.     end GET_PAST_END; 
  1263.     
  1264.     
  1265.   ----------------------------------------------------------------------
  1266.   procedure LOAD_KEY_WORDS is
  1267.           ---------------------------------------------------------
  1268.           --  This procedure loads the key words (the words that --
  1269.           --  the stubber cares about) into the key words array, --
  1270.           --  to be used by the function CONVERT.                --
  1271.           ---------------------------------------------------------
  1272.   
  1273.     begin
  1274.       KW (KW_PACKAGE)    := "PACKAGE   ";
  1275.       KW (KW_FUNCTION)   := "FUNCTION  ";
  1276.       KW (KW_PROCEDURE)  := "PROCEDURE ";
  1277.       KW (KW_BODY)       := "BODY      ";
  1278.       KW (KW_ACCEPT)     := "ACCEPT    ";
  1279.       
  1280.       KW (KW_BEGIN)      := "BEGIN     ";
  1281.       KW (KW_CASE)       := "CASE      ";
  1282.       KW (KW_IF)         := "IF        ";
  1283.       KW (KW_LOOP)       := "LOOP      ";
  1284.       KW (KW_END)        := "END       ";
  1285.       
  1286.       KW (KW_TYPE)       := "TYPE      ";
  1287.       KW (KW_FOR)        := "FOR       ";
  1288.       KW (KW_USE)        := "USE       ";
  1289.       KW (KW_RECORD)     := "RECORD    ";
  1290.       
  1291.       KW (KW_NEW)        := "NEW       ";
  1292.       KW (KW_SEPARATE)   := "SEPARATE  ";
  1293.       KW (KW_IS)         := "IS        ";
  1294.       KW (NOT_KW)        := "NOT A KW  ";
  1295.     end LOAD_KEY_WORDS;
  1296.     
  1297.   
  1298.   ----------------------------------------------------------------------
  1299.   function CONVERT (STR1  : STRING_RECORD) return KEY_WORDS is 
  1300.           ---------------------------------------------------------
  1301.           --  This function determines if an identifier is a key --
  1302.           --  word. If not, the function returns the value       --
  1303.           --  NOT_KW.                                            --
  1304.           ---------------------------------------------------------
  1305.   
  1306.     CONV  : KEY_WORDS := KW_PACKAGE; 
  1307.     
  1308.     begin 
  1309.       while CONV < NOT_KW loop 
  1310.         if KW (CONV) = STR1.STR (1..10) then    -- your basic sentinel search
  1311.           exit; 
  1312.         end if; 
  1313.         CONV := KEY_WORDS'SUCC (CONV); 
  1314.       end loop; 
  1315.       return CONV; 
  1316.     end CONVERT; 
  1317.     
  1318.     
  1319.   ----------------------------------------------------------------------
  1320.   begin   -- initializations
  1321.     LOAD_KEY_WORDS; 
  1322.     FIRST_TIME_THROUGH_STUB := TRUE;
  1323.   end STUBBER_SUPPORT; 
  1324.   
  1325. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1326. --stubber.txt
  1327. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1328. --                                                                    --  
  1329. --                        procedure STUBBER                           --
  1330. --                                                                    --
  1331. ------------------------------------------------------------------------
  1332. ------------------------------------------------------------------------
  1333. with GETTOKEN;         use GETTOKEN;
  1334. with STUBBER_SUPPORT;  use STUBBER_SUPPORT; 
  1335. with TEXT_IO;          use TEXT_IO; 
  1336.  
  1337. procedure STUBBER is 
  1338.   
  1339.   
  1340.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  1341.   --                                                                  --
  1342.   --    Procedure STUBBER is the main procedure for the STUBBER set   --
  1343.   --    of packages.  It walks through the input file, one token at   --
  1344.   --    a time, storing specifications as it finds them, and taking   --
  1345.   --    care bodies, stubbing where necessary.                        --
  1346.   --                                                                  --
  1347.   --    All operating system dependencies, editor dependencies, and   --
  1348.   --    a few compiler dependencies can be found in the file called   --
  1349.   --    ROS_DEPENDENCIES (that STUBBER_SUPPORT uses).  The compiler   --
  1350.   --    used to write these programs was a 1982 (non ANSI standard)   --
  1351.   --    Ada compiler, so these packages will need to be updated be-   --
  1352.   --    fore they will run on a Mil Std 1815A Ada compiler.  Please   --
  1353.   --    also note that the compiler used (Telesoft) couldn't handle   --
  1354.   --    many of the Ada constructs, so the solution here is not the   --
  1355.   --    most elegant one that the user could think of.  (NOTE:  the   --
  1356.   --    STUBBER does handle all cases, even though the compiler did   --
  1357.   --    not.)                                                         --
  1358.   --                                                                  --
  1359.   --                    PACKAGE SET DEPENDENCE:                       --
  1360.   --                                                                  --
  1361.   --    >STUBBER                                                      --
  1362.   --       |  |                                                       --
  1363.   --       |  \___>STUBBER_SUPPORT                                    --
  1364.   --       |         |   |                                            --
  1365.   --       |         |   \_______________________>ROS_DEPENDENCIES    --
  1366.   --       |         |                     /                          --
  1367.   --       |         \_________>GETTOKEN   |                          --
  1368.   --       \______________/        \_______/                          --
  1369.   --                                                                  --
  1370.   --                                                                  --
  1371.   --    Author:  Steven E. Nameroff, C1C, USAF                        --
  1372.   --    Date  :  15 July 1983                                         --
  1373.   --                                                                  --
  1374.   --||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||--
  1375.   
  1376.   
  1377.           ---------------------------------------------------------
  1378.           --  The stubber stubs anything in a program that needs --
  1379.           --  to be stubbed.  It needs no assistance in deter-   --
  1380.           --  mining what needs to be stubbed, and there is no   --
  1381.           --  way of stopping it from stubbing everything that   --
  1382.           --  needs to be stubbed.  It is imperative that the    --
  1383.           --  program is syntactically correct to the point of   --
  1384.           --  having all "if"s with matching "end if"s, etc.     --
  1385.           --  Failure to follow this simple and straight-forward --
  1386.           --  requirement may result in the stubber producing    --
  1387.           --  garbage.                                           --
  1388.           ---------------------------------------------------------
  1389.   
  1390.   SPECS       : DECLARATION_PTR; 
  1391.   NEWFILE_ID  : GETTOKEN.STRING_RECORD; 
  1392.   
  1393.   
  1394.   ----------------------------------------------------------------------
  1395.   function FORMAL_PARTS_MATCH (FIRST_ONE, SECOND_ONE  : DECLARATION_PTR) 
  1396.             return boolean is 
  1397.           ---------------------------------------------------------
  1398.           --  This function determines if the formal parts of    --
  1399.           --  two declarations match.                            --
  1400.           ---------------------------------------------------------
  1401.   
  1402.     FPM             : boolean := true; 
  1403.     TEMP_1, TEMP_2  : BUFFER_PTR; 
  1404.     
  1405.     begin 
  1406.       TEMP_1 := FIRST_ONE.FORMAL_PART; 
  1407.       TEMP_2 := SECOND_ONE.FORMAL_PART; 
  1408.       while TEMP_1 /= null and TEMP_2 /= null loop 
  1409.         if TEMP_1.BUFFER_STRING /= TEMP_2.BUFFER_STRING then 
  1410.           FPM := false; 
  1411.           exit;                       -- Requirement 1:  all of the declarations
  1412.         end if;                       -- of the one have to match that of the 
  1413.                                       -- other.
  1414.         TEMP_1 := TEMP_1.NEXT_ONE; 
  1415.         TEMP_2 := TEMP_2.NEXT_ONE; 
  1416.       end loop; 
  1417.       if TEMP_1 /= null or TEMP_2 /= null then 
  1418.         FPM := false;                 -- Requirment 2:  both have to have the
  1419.       end if;                         -- same number of declarations in their
  1420.                                       -- formal parts.
  1421.       return FPM; 
  1422.  
  1423. exception
  1424.   when others  =>
  1425.     PUT("Unhandled exception in STUBBER.FORMAL_PARTS_MATCH"); new_line;
  1426.     raise;
  1427.     end FORMAL_PARTS_MATCH; 
  1428.     
  1429.     
  1430.   ----------------------------------------------------------------------
  1431.   procedure DO_FORMAL_PART (CURRENT_DEC  : in out DECLARATION_PTR) is 
  1432.           ---------------------------------------------------------
  1433.           --  This procedure creates the formal-part buffer for  --
  1434.           --  a subprogram specification.                        --
  1435.           ---------------------------------------------------------
  1436.     
  1437.     TEMP_DEC           : BUFFER_PTR; 
  1438.     PARENTHESIS_COUNT  : GETTOKEN.LENGTH_TYPE := 1;   -- used to keep track of
  1439.                                                       -- internal parentheses
  1440.     TEMP_INDENT        : LENGTH_TYPE := 11;    -- used to indent multiple
  1441.                                                -- declarations inside the 
  1442.                                                -- formal part
  1443.     
  1444.     begin 
  1445.       if TOKEN.STR (1) = '(' then 
  1446.         CURRENT_DEC.FORMAL_PART := new BUFFER_TYPE; 
  1447.         CURRENT_DEC.FORMAL_PART.BUFFER_STRING.STR (1..2) := " ("; 
  1448.         CURRENT_DEC.FORMAL_PART.BUFFER_STRING.LENGTH := 2; 
  1449.         TEMP_DEC := CURRENT_DEC.FORMAL_PART; 
  1450.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1451.         
  1452.         while TOKEN.STR (1) /= ')' loop 
  1453.           
  1454.           -- add tokens to the buffer string until a ")" or a ";" is found
  1455.           
  1456.           while PARENTHESIS_COUNT > 0 and TOKEN.STR (1) /= ';' loop 
  1457.             TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH + 
  1458.                       1..TEMP_DEC.BUFFER_STRING.LENGTH + TOKEN.LENGTH) := 
  1459.                       TOKEN.STR (1..TOKEN.LENGTH); 
  1460.             TEMP_DEC.BUFFER_STRING.LENGTH := TEMP_DEC.BUFFER_STRING.LENGTH + 
  1461.                       TOKEN.LENGTH + 1; 
  1462.             TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH) := ' '; 
  1463.             GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1464.             if TOKEN.STR (1) = '(' then 
  1465.               PARENTHESIS_COUNT := PARENTHESIS_COUNT + 1; 
  1466.             elsif TOKEN.STR (1) = ')' then 
  1467.               PARENTHESIS_COUNT := PARENTHESIS_COUNT - 1; 
  1468.             end if; 
  1469.           end loop; 
  1470.           
  1471.           if TOKEN.STR (1) = ';' then     -- create a new buffer string
  1472.           
  1473.             TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH) := ';'; 
  1474.             GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1475.             
  1476.             TEMP_DEC.NEXT_ONE := new BUFFER_TYPE; 
  1477.             TEMP_DEC := TEMP_DEC.NEXT_ONE; 
  1478.             for I in 1..TEMP_INDENT loop 
  1479.               TEMP_DEC.BUFFER_STRING.STR (I) := ' '; 
  1480.             end loop; 
  1481.             TEMP_DEC.BUFFER_STRING.LENGTH := TEMP_INDENT; 
  1482.           end if; 
  1483.         end loop; 
  1484.         
  1485.         TEMP_DEC.BUFFER_STRING.STR (TEMP_DEC.BUFFER_STRING.LENGTH) := ')'; 
  1486.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1487.       end if; 
  1488. exception
  1489.   when others  =>
  1490.     PUT("Unhandled exception in STUBBER.DO_FORMAL_PART"); new_line;
  1491.     raise;
  1492.     end DO_FORMAL_PART; 
  1493.     
  1494.     
  1495.   ----------------------------------------------------------------------
  1496.   procedure DO_SPEC (FIRST_SPEC  : in out DECLARATION_PTR) is 
  1497.           ---------------------------------------------------------
  1498.           --  This procedure is the meat of the STUBBER set of   --
  1499.           --  packages.  It walks through the input file, finds  --
  1500.           --  all of the package/subprogram specifications and   --
  1501.           --  bodies, and takes appropriate action.              --
  1502.           ---------------------------------------------------------
  1503.   
  1504.     CURRENT_SPEC, 
  1505.     TEMP_SPEC  : DECLARATION_PTR; 
  1506.     
  1507.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1508.     procedure CLOSE_OFF (LOSING_SPEC, MAIN_SPEC  : in out DECLARATION_PTR) is 
  1509.                     ------------------------------------------
  1510.                     --  This procedure eliminates one spe-  --
  1511.                     --  cification (LOSING_SPEC) from a     --
  1512.                     --  linked list of specifications       --
  1513.                     --  (MAIN_SPEC).                        --
  1514.                     ------------------------------------------
  1515.     
  1516.       TEMP_DEC  : DECLARATION_PTR; 
  1517.       
  1518.       begin 
  1519.         if LOSING_SPEC = MAIN_SPEC then       -- if the LOSING_SPEC is the first
  1520.           MAIN_SPEC := MAIN_SPEC.NEXT_DEC;   -- spec in the linked list, then
  1521.                                             -- the pointer to the first spec now
  1522.                                            -- points to the second spec.
  1523.         
  1524.         else                                           -- Otherwise, TEMP_DEC 
  1525.           TEMP_DEC := MAIN_SPEC;                       -- goes through the
  1526.           while TEMP_DEC.NEXT_DEC /= LOSING_SPEC loop  -- list until it finds
  1527.             TEMP_DEC := TEMP_DEC.NEXT_DEC;             -- the spec that points
  1528.           end loop;                                    -- to LOSING_SPEC,
  1529.           
  1530.           TEMP_DEC.NEXT_DEC := LOSING_SPEC.NEXT_DEC;   -- at which point, it is
  1531.         end if;                                       -- changed so that it now
  1532.                                                      -- points to what LOSING_
  1533.                                                     -- SPEC pointed to.
  1534.  
  1535. exception
  1536.   when others  =>
  1537.     PUT("Unhandled exception in STUBBER.DO_SPEC.CLOSE_OFF"); new_line;
  1538.     raise;
  1539.       end CLOSE_OFF;
  1540.       
  1541.       
  1542.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1543.     procedure FOUND_WORD_PACKAGE is
  1544.                     ------------------------------------------
  1545.                     --  This procedure, called when the re- --
  1546.                     --  served word "package" is found,     --
  1547.                     --  determines if the structure found   --
  1548.                     --  is a package body or package spec., --
  1549.                     --  and takes appropriate action.       --
  1550.                     ------------------------------------------
  1551.     
  1552.       begin
  1553.         CURRENT_SPEC.TYPE_OF_DEC := KW_PACKAGE; 
  1554.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1555.         if CONVERT (TOKEN) = KW_BODY then 
  1556.           GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- id
  1557.           CURRENT_SPEC.DEC_NAME := TOKEN; 
  1558.           GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- 'IS'
  1559.           
  1560.           if CONVERT (TOKEN) /= KW_SEPARATE then   -- found a package body
  1561.             new_line; 
  1562.             put ("Found package body "); 
  1563.             put (CURRENT_SPEC.DEC_NAME.STR 
  1564.                       (1..CURRENT_SPEC.DEC_NAME.LENGTH)); 
  1565.             TEMP_SPEC := FIRST_SPEC; 
  1566.             
  1567.        -- search for a matching specification (EXAXT match)
  1568.             
  1569.             while TEMP_SPEC.TYPE_OF_DEC /= CURRENT_SPEC.TYPE_OF_DEC or 
  1570.                       else TEMP_SPEC.DEC_NAME.STR /= 
  1571.                       CURRENT_SPEC.DEC_NAME.STR loop 
  1572.               TEMP_SPEC := TEMP_SPEC.NEXT_DEC; 
  1573.             end loop; 
  1574.             
  1575.             if TEMP_SPEC = CURRENT_SPEC then   -- no matching spec.
  1576.               put (" (no matching spec.)"); 
  1577.               TEMP_SPEC.INTERNAL_DECS := new DECLARATION_BUFF; 
  1578.             
  1579.             else                               -- found matching spec.
  1580.               put (" (with matching spec.)"); 
  1581.               CLOSE_OFF (TEMP_SPEC, FIRST_SPEC); -- the spec is no longer saved 
  1582.             end if; 
  1583.             DO_SPEC (TEMP_SPEC.INTERNAL_DECS); 
  1584.             
  1585.             STUB (TEMP_SPEC.INTERNAL_DECS); 
  1586.             
  1587.             if CONVERT (TOKEN) = KW_BEGIN then 
  1588.               GET_PAST_END;                      -- get through initializations
  1589.             end if; 
  1590.           end if;       -- when a package body is found, there is no reason
  1591.                          -- to save anything, because all work has been done
  1592.                           -- on it, so a new storage buffer is not made.
  1593.         else 
  1594.           CURRENT_SPEC.DEC_NAME := TOKEN; 
  1595.           GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- 'IS' | 'RENAMES'
  1596.           if CONVERT (TOKEN) = KW_IS then 
  1597.             GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1598.             
  1599.             if CONVERT (TOKEN) /= KW_NEW then   -- found package spec.
  1600.               new_line; 
  1601.               put ("Found package spec. "); 
  1602.               put (CURRENT_SPEC.DEC_NAME.STR 
  1603.                         (1..CURRENT_SPEC.DEC_NAME.LENGTH)); 
  1604.               CURRENT_SPEC.INTERNAL_DECS := new DECLARATION_BUFF; 
  1605.               
  1606.          -- recursive call to save internal specifications
  1607.               
  1608.               DO_SPEC (CURRENT_SPEC.INTERNAL_DECS); 
  1609.               CURRENT_SPEC.NEXT_DEC := new DECLARATION_BUFF; 
  1610.               CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC; 
  1611.             end if; 
  1612.           end if; 
  1613.         end if; 
  1614.  
  1615. exception
  1616.   when others  =>
  1617.     PUT("Unhandled exception in STUBBER.DO_SPEC.FOUND_WORD_PACKAGE"); new_line;
  1618.     raise;
  1619.       end FOUND_WORD_PACKAGE;
  1620.       
  1621.       
  1622.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1623.     procedure FOUND_SUBPROGRAM is
  1624.                     ------------------------------------------
  1625.                     --  This procedure, called when the re- --
  1626.                     --  served word "procedure" or the re-  --
  1627.                     --  served word "function" is found,    --
  1628.                     --  determines if the structure is a    --
  1629.                     --  subprogram specification or body,   --
  1630.                     --  and takes appropriate action.       --
  1631.                     ------------------------------------------
  1632.                     
  1633.       begin
  1634.         
  1635.             -- store everything, whether it'll be used or not
  1636.             
  1637.         CURRENT_SPEC.TYPE_OF_DEC := CONVERT (TOKEN); 
  1638.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- id
  1639.         CURRENT_SPEC.DEC_NAME := TOKEN; 
  1640.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1641.         DO_FORMAL_PART (CURRENT_SPEC); 
  1642.         if CURRENT_SPEC.TYPE_OF_DEC = KW_FUNCTION then 
  1643.           GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- id
  1644.           CURRENT_SPEC.RETURN_TYPE := TOKEN; 
  1645.           GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1646.         end if; 
  1647.         
  1648.         if TOKEN.STR (1) = ';' then     -- found subprogram spec.
  1649.           
  1650.           CURRENT_SPEC.NEXT_DEC := new DECLARATION_BUFF;    -- nothing to do 
  1651.           CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;             -- but move on
  1652.           
  1653.         elsif CONVERT (TOKEN) = KW_IS then 
  1654.           GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1655.           
  1656.           if CONVERT (TOKEN) /= KW_NEW and 
  1657.                   CONVERT (TOKEN) /= KW_SEPARATE then   -- found subprogram body
  1658.             new_line; 
  1659.             put ("Found subprogram body "); 
  1660.             put (CURRENT_SPEC.DEC_NAME.STR 
  1661.                       (1..CURRENT_SPEC.DEC_NAME.LENGTH)); 
  1662.             
  1663.        -- check for matching spec.
  1664.        
  1665.             TEMP_SPEC := FIRST_SPEC; 
  1666.             while TEMP_SPEC.TYPE_OF_DEC /= CURRENT_SPEC.TYPE_OF_DEC or else 
  1667.                       TEMP_SPEC.DEC_NAME.STR /= CURRENT_SPEC.DEC_NAME.STR or 
  1668.                       else TEMP_SPEC.RETURN_TYPE /= CURRENT_SPEC.RETURN_TYPE
  1669.                       or else not FORMAL_PARTS_MATCH (TEMP_SPEC, CURRENT_SPEC) 
  1670.                       loop 
  1671.               TEMP_SPEC := TEMP_SPEC.NEXT_DEC; 
  1672.             end loop; 
  1673.             
  1674.             if TEMP_SPEC = CURRENT_SPEC then 
  1675.               put (" (no matching spec)"); 
  1676.             else 
  1677.               put (" (with matching spec)"); 
  1678.               CLOSE_OFF (TEMP_SPEC, FIRST_SPEC); 
  1679.             end if; 
  1680.             CURRENT_SPEC.INTERNAL_DECS := new DECLARATION_BUFF; 
  1681.             DO_SPEC (CURRENT_SPEC.INTERNAL_DECS); 
  1682.             
  1683.             STUB (CURRENT_SPEC.INTERNAL_DECS); 
  1684.             
  1685.             GET_PAST_END;       -- get through the subprogram seq-of-stmts.
  1686.           end if; 
  1687.         end if;            -- procedure bodies are never needed for future
  1688.                           -- reference and cannot be stubbed, so a new
  1689.                          -- storage location is not made.
  1690.  
  1691. exception
  1692.   when others  =>
  1693.     PUT("Unhandled exception in STUBBER.DO_SPEC.FOUND_SUBPROGRAM"); new_line;
  1694.     raise;
  1695.       end FOUND_SUBPROGRAM;
  1696.       
  1697.   
  1698.     -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1699.     begin   -- DO_SPEC
  1700.       CURRENT_SPEC := FIRST_SPEC; 
  1701.       while CURRENT_SPEC.NEXT_DEC /= null loop   -- see main procedure 
  1702.         CURRENT_SPEC := CURRENT_SPEC.NEXT_DEC;   -- for explanation of
  1703.       end loop;                                  -- the basic logic
  1704.       
  1705.       while TOKEN.STR_ZERO /= GETTOKEN.END_FILE and CONVERT (TOKEN) /= KW_END 
  1706.                 and CONVERT (TOKEN) /= KW_BEGIN loop 
  1707.         case CONVERT (TOKEN) is 
  1708.         
  1709.           when KW_PACKAGE => 
  1710.             FOUND_WORD_PACKAGE;
  1711.             
  1712.           when KW_PROCEDURE | KW_FUNCTION => 
  1713.             FOUND_SUBPROGRAM;
  1714.             
  1715.           when KW_TYPE =>      -- find records, and get past the "end record",
  1716.                                -- so that the "end" of a record does not get
  1717.                                -- me out of this procedure
  1718.           
  1719.             while CONVERT (TOKEN) /= KW_IS and TOKEN.STR (1) /= ';' loop 
  1720.               GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1721.               if TOKEN.STR (1) = '(' then 
  1722.                 while TOKEN.STR (1) /= ')' loop 
  1723.                   GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1724.                 end loop; 
  1725.               end if; 
  1726.             end loop; 
  1727.             
  1728.             if CONVERT (TOKEN) = KW_IS then 
  1729.               GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1730.               if CONVERT (TOKEN) = KW_RECORD then 
  1731.                 GET_PAST_END; 
  1732.               end if; 
  1733.             end if; 
  1734.             
  1735.           when KW_FOR =>       -- find representation records, and get past
  1736.                                -- the "end record"
  1737.             while CONVERT (TOKEN) /= KW_USE loop 
  1738.               GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1739.             end loop; 
  1740.             GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1741.             if CONVERT (TOKEN) = KW_RECORD then 
  1742.               GET_PAST_END; 
  1743.             end if; 
  1744.             
  1745.           when others => 
  1746.             null; 
  1747.             
  1748.         end case; 
  1749.         
  1750.         GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN);   -- anything
  1751.       end loop; 
  1752.       CURRENT_SPEC := null; 
  1753.  
  1754. exception
  1755.   when others  =>
  1756.     PUT("Unhandled exception in STUBBER.DO_SPEC"); new_line;
  1757.     raise;
  1758.     end DO_SPEC; 
  1759.     
  1760.     
  1761.   ----------------------------------------------------------------------
  1762.   begin   -- stubber
  1763.     INITIALIZE (NEWFILE_ID); 
  1764.     GET_ONE_TOKEN (INPUT_FILE, OUTPUT_FILE, TOKEN); 
  1765.     SPECS := new DECLARATION_BUFF; 
  1766.     
  1767.     -- At this point, let me try to explain the system I used.  Every-
  1768.     -- thing revolves around the data structure, "DECLARATION_BUFF" (I
  1769.     -- hope that you are now grabbing the package "STUBBER_SUPPORT",
  1770.     -- which contains the type declaration, so that you can follow what
  1771.     -- I am about to say).  All declaration buffers have two pointers 
  1772.     -- to other declaration buffers:  INTERNAL_DECS points to the first
  1773.     -- of those declarations which are one lexical level inside the dec-
  1774.     -- laration being looked at.  In other words, if a given declaration
  1775.     -- buffer is for a package specification, INTERNAL_DECS points to the
  1776.     -- first package/subprogram specification found within that package
  1777.     -- specification.  NEXT_DEC points to the next declaration on the same
  1778.     -- lexical level as the given declaration.  Still confused?  Well, let's
  1779.     -- walk through an example.  Since package STUBBER_SUPPORT is already
  1780.     -- right there in front of you we'll use it.  When the word "package"
  1781.     -- is found by procedure DO_SPEC, it calls FOUND_PACKAGE.  This pro-
  1782.     -- cedure will determine that it found a package specification, and
  1783.     -- get ready to accept specifications inside package STUBBER_SUPPORT
  1784.     -- by creating a new declaration storage buffer, and pointing to it with
  1785.     -- its INTERNAL_DECS buffer.  Then DO_SPEC will be called recursively,
  1786.     -- to start a new set (horizontally speaking) of specifications.
  1787.     -- When it gets to the function CONVERT declaration, it saves it by
  1788.     -- creating a new storage location, pointing to it with its NEXT_DEC
  1789.     -- pointer, and moving to the new storage buffer.  When DO_SPEC reaches
  1790.     -- the word "end", it will leave the procedure, which will take us back
  1791.     -- to where it was called in FOUND_PACKAGE, which, in turn, will save
  1792.     -- everything by creating a new storage buffer, pointing to it with its
  1793.     -- NEXT_DEC pointer, and moving to the new storage buffer.  still con-
  1794.     -- fused?  Reread this paragraph.  STILL confused?  Tough.
  1795.     
  1796.   DO_SPEC (SPECS); 
  1797.                               -- the main procedure just initiates the
  1798.   STUB (SPECS);               -- pointers, calls DO_SPEC, and calls STUB
  1799.                               -- to stub anything left.
  1800.   DUMP (NEWFILE_ID); 
  1801.  
  1802. exception
  1803.   when others  =>
  1804.     PUT("Unhandled exception in STUBBER"); new_line;
  1805.     raise;
  1806. end STUBBER; 
  1807.   
  1808.  
  1809.