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

  1.  
  2. -------- SIMTEL20 Ada Software Repository Prologue ------------
  3. --                                                           -*
  4. -- Unit name    : generic package Context_Directed_Update_Utilities
  5. -- Version      : 1.1 (FRAN246)
  6. -- Author       : Geoffrey O. Mendal
  7. --              : Stanford University
  8. --              : Computer Systems Laboratory
  9. --              : Stanford, CA  94305
  10. --              : (415) 723-1414 or 723-1175
  11. -- DDN Address  : Mendal@SU-SIERRA.ARPA
  12. -- Copyright    : (c) 1985, 1986 Geoffrey O. Mendal
  13. -- Date created : Sat 28 Dec 85
  14. -- Release date : Sun 29 Dec 85
  15. -- Last update  : MENDAL Fri 24 Jan 86
  16. -- Machine/System Compiled/Run on : DG MV10000, ROLM ADE
  17. --                                  VAX 11/780, DEC ACS
  18. --                                  RATIONAL R1000
  19. -- Dependent Units : package TEXT_IO
  20. --                                                           -*
  21. ---------------------------------------------------------------
  22. --                                                           -*
  23. -- Keywords     :  REVISION CONTROL
  24. ----------------:  CDUPDATE
  25. --
  26. -- Abstract     :  This generic package contains routines to
  27. ----------------:  perform file revision control. Given a
  28. ----------------:  baseline ASCII file, and one or more
  29. ----------------:  update decks stored in a single file, it
  30. ----------------:  generates an updated or downdated version of
  31. ----------------:  the baseline. The update decks can be generated
  32. ----------------:  automatically by the package File_Compare_Utilities
  33. --                                                           -*
  34. ------------------ Revision history ---------------------------
  35. --                                                           -*
  36. -- DATE         VERSION              AUTHOR     HISTORY
  37. -- 12/29/85     1.0 (SAEC285)     Mendal     Initial Release
  38. -- 01/24/86     1.1 (FRAN246)     Mendal     Bug fixes, enhancements
  39. --                                                           -*
  40. ------------------ Distribution and Copyright -----------------
  41. --                                                           -*
  42. -- This prologue must be included in all copies of this software.
  43. --
  44. -- This software is copyright by the author.
  45. --
  46. -- This software is released to the Ada community.
  47. -- This software is released to the Public Domain (note:
  48. --   software released to the Public Domain is not subject
  49. --   to copyright protection).
  50. -- Restrictions on use or distribution:  NONE
  51. --                                                           -*
  52. ------------------ Disclaimer ---------------------------------
  53. --                                                           -*
  54. -- This software and its documentation are provided "AS IS" and
  55. -- without any expressed or implied warranties whatsoever.
  56. -- No warranties as to performance, merchantability, or fitness
  57. -- for a particular purpose exist.
  58. --
  59. -- Because of the diversity of conditions and hardware under
  60. -- which this software may be used, no warranty of fitness for
  61. -- a particular purpose is offered.  The user is advised to
  62. -- test the software thoroughly before relying on it.  The user
  63. -- must assume the entire risk and liability of using this
  64. -- software.
  65. --
  66. -- In no event shall any person or organization of people be
  67. -- held responsible for any direct, indirect, consequential
  68. -- or inconsequential damages or lost profits.
  69. --                                                           -*
  70. -------------------END-PROLOGUE--------------------------------
  71.  
  72. -- Context_Directed_Update_Utilities is an implementation independent
  73. -- revision control facility for ASCII files. It takes a baseline
  74. -- file and context directed update deck as input and produces a new
  75. -- file which is the result of the mapping between the baseline file
  76. -- and the CDUPDATE deck.
  77.  
  78. -- This utility is best used in conjunction with File_Compare_Utilities
  79. -- which itself can generate CDUPDATE decks. Of course, a user can
  80. -- construct and/or edit such CDUPDATE decks himself. The CDUPDATE
  81. -- decks are also ASCII files and hence can be ported between Ada
  82. -- environments and different machines.
  83.  
  84. -- Many CDUPDATE decks can be chained together in one file, one
  85. -- after the other. Context_Directed_Update_Utilities will
  86. -- then perform repeated updates until all decks have been
  87. -- exhausted. This achieves the same semantics as running
  88. -- Context_Directed_Update_Utilities subprograms once per
  89. -- CDUPDATE deck, where each CDUPDATE deck is in its own file.
  90.  
  91. -- This package requires the use of temporary ASCII files,
  92. -- generated according to the Ada Reference Manual's TEXT_IO.CREATE
  93. -- semantics for null file names. An implementation must also be
  94. -- able to support various "reset" and "rewrite" operations on
  95. -- ASCII files (see below for details).
  96.  
  97. generic
  98.   Maximum_File_Name_Length : in     POSITIVE := 100;
  99.   Maximum_Line_Length      : in     POSITIVE := 256;
  100.  
  101.   -- The above values are used to specify the maximum length
  102.   -- of strings. Such strings are used in the package body.
  103. package Context_Directed_Update_Utilities is
  104.   Context_Directed_Update_Utilities_Version : constant STRING := "1.1 (FRAN246)";
  105.  
  106.   -- The following type can be used to retrieve statistics generated
  107.   -- by the first Cdupdate subprogram below.
  108.  
  109.   type Statistics_Type is
  110.     record
  111.       Number_Base_Lines,                  -- number of lines in the base file
  112.       Number_Deck_Lines,                  -- number of lines in the deck file
  113.       Number_New_Lines,                   -- number of lines in the new file
  114.       Total_Begin_Commands,               -- number of Begin commands
  115.       Total_Comment_Commands,             -- number of Comment commands
  116.       Total_Copy_Commands,                -- number of Copy commands
  117.       Total_Delete_Commands,              -- number of Delete commands
  118.       Total_Echo_Commands,                -- number of Echo commands
  119.       Total_Edit_Commands,                -- number of Edit commands
  120.       Total_End_Commands,                 -- number of End commands
  121.       Total_Error_Commands,               -- number of commands in error
  122.       Total_Insertions,                   -- number of insertions
  123.       Total_Decks             : NATURAL;  -- number of CDUPDATE decks
  124.     end record;
  125.  
  126.   -- The following type can be used to specify options to the
  127.   -- Cdupdate subprograms. Note that a default options record
  128.   -- is provided below.
  129.  
  130.   type Options_Type is
  131.     record
  132.       Print_Errors,
  133.       Case_Sensitive      : BOOLEAN;
  134.     end record;
  135.  
  136.   Default_Options : Options_Type :=
  137.     (Print_Errors         => TRUE,
  138.      Case_Sensitive       => TRUE);
  139.  
  140.   -- Notes on the options:
  141.   --   (1) Print_Errors will cause all commands that are in error
  142.   --       to be reported on the error file. If this option is
  143.   --       set to FALSE, no error messages will be generated and
  144.   --       the error file itself will not be created. Hence, when
  145.   --       this option is set to FALSE, a user need only provide
  146.   --       a null string literal as the error file name. (Any value
  147.   --       provided when this option is FALSE will be ignored.)
  148.   --   (2) Case_Sensitive causes lines to be analyzed with regard
  149.   --       for upper and lower case. If a case insensitive analysis
  150.   --       is desired, this option should be set to FALSE. This option
  151.   --       only has an effect for Edit commands. If this option is
  152.   --       set to FALSE, Edit commands will still be processed
  153.   --       with case sensitivity. Thus, this option has the effect
  154.   --       of only analyzing a substitution pattern without regard
  155.   --       to upper and lower case; the replacement pattern will
  156.   --       always be output with case sensitivity.
  157.  
  158.   File_Name_Length_Error,
  159.   Base_File_Open_Error,
  160.   Deck_File_Open_Error,
  161.   New_File_Create_Error,
  162.   New_File_Reset_Error,
  163.   New_File_Rewrite_Error,
  164.   Error_File_Create_Error,
  165.   Temporary_File_Create_Error,
  166.   Temporary_File_Reset_Error,
  167.   Temporary_File_Rewrite_Error : exception;
  168.  
  169.   -- Notes on the exceptions:
  170.   --   (1) The "Open_Error" exceptions are propagated when the
  171.   --       subprograms perform TEXT_IO.OPENs on the base and
  172.   --       deck files as TEXT_IO.IN_FILEs but a TEXT_IO exception
  173.   --       was raised. The most probable error is that the file
  174.   --       doesn't exist or access to it is not allowed.
  175.   --   (2) The "Create_Error" exceptions are propagated when the
  176.   --       subprograms perform TEXT_IO.CREATEs on the list and
  177.   --       deck files as TEXT_IO.OUT_FILEs but a TEXT_IO exception was
  178.   --       raised.
  179.   --   (3) The "Reset_Error" and "Rewrite_Error" exceptions are
  180.   --       propagated when the subprograms perform successive
  181.   --       TEXT_IO file operations. Such operations attempt to
  182.   --       change the mode of the file from OUT_FILE to IN_FILE
  183.   --       (resets), and from IN_FILE to OUT_FILE (rewrites).
  184.   --       For a reset operation, TEXT_IO.CLOSE and TEXT_IO.OPEN are
  185.   --       used. For a rewrite operation, TEXT_IO.CLOSE and
  186.   --       TEXT_IO.CREATE are used. For the temporary file,
  187.   --       TEXT_IO.RESET is used for reset operations since a
  188.   --       TEXT_IO.CLOSE followed by a TEXT_IO.OPEN cannot work.
  189.   --   (4) The File_Name_Length_Error exception is propagated by a
  190.   --       subprogram when the length of a passed file name is
  191.   --       greater than Maximum_File_Name_Length.
  192.  
  193.   -- The following character is used to denote the command code
  194.   -- for CDUPDATE commands. Its default is the same as the
  195.   -- File_Compare_Utilities package's default. The subtype allows
  196.   -- for only non-blank printable characters.
  197.  
  198.   subtype Code_Character_Type is CHARACTER range '!' .. '~';
  199.  
  200.   Command_Code : Code_Character_Type := '/';
  201.  
  202.   -- The following subprogram takes a base, deck, new, and error
  203.   -- file as input, and (depending on the options set), returns
  204.   -- statistics, a new file, and an error file. The base and
  205.   -- deck files will be OPENed, the error file will CREATed,
  206.   -- and the new file will be CREATed, and possibly "reset" and
  207.   -- "rewritten". All files will be CLOSEd upon normal termination.
  208.  
  209.   procedure Cdupdate (
  210.     Base_File_Name,
  211.     Deck_File_Name,
  212.     New_File_Name,
  213.     Error_File_Name : in     STRING;
  214.     Statistics      :    out Statistics_Type;
  215.     Options         : in     Options_Type := Default_Options);
  216.  
  217.   -- The following overloading should be used when no statistics
  218.   -- are required. See above for detailed semantics on the
  219.   -- on the file operations.
  220.  
  221.   procedure Cdupdate (
  222.     Base_File_Name,
  223.     Deck_File_Name,
  224.     New_File_Name,
  225.     Error_File_Name : in     STRING;
  226.     Options         : in     Options_Type := Default_Options);
  227. end Context_Directed_Update_Utilities;
  228. ------------------------------------------------------------------------
  229. -- Example uses:
  230.  
  231. -- Example #1: Update a base file
  232. -- with Context_Directed_Update_Utilities;
  233. -- procedure Main is
  234. --   package Cdupdate_Utilities is new Context_Directed_Update_Utilities;
  235. -- begin
  236. --   Cdupdate_Utilities.Cdupdate ("Base.Ada","Deck","New.Ada","Errors");
  237. -- end Main;
  238. -- ---------------------------------------------------------------------
  239. -- Example #2: Update a base file and generate all possible output
  240. -- with Context_Directed_Update_Utilities;
  241. -- procedure Main is
  242. --   package Cdupdate_Utilities is new Context_Directed_Update_Utilities;
  243. --   Statistics : Cdupdate_Utilities.Statistics_Type;
  244. -- begin
  245. --   Cdupdate_Utilities.Cdupdate ("Base.Ada","Deck","New.Ada","Errors",
  246. --     Statistics);
  247. -- end Main;
  248. -- ---------------------------------------------------------------------
  249. -- Example #3: Update a base file, and alter the maximum line length,
  250. --             the command code character, and options.
  251. -- procedure Main is
  252. --   package Cdupdate_Utilities is new Context_Directed_Update_Utilities (
  253. --                                       Maximum_Line_Length => 80);
  254. -- begin
  255. --   Cdupdate_Utilities.Command_Code := '#';
  256. --   Cdupdate_Utilities.Default_Options.Print_Errors := FALSE;
  257. --   Cdupdate_Utilities.Default_Options.Case_Sensitive := FALSE;
  258. --   Cdupdate_Utilities.Cdupdate ("Base.Ada","Deck","New.Ada","");
  259. -- end Main;
  260.  
  261. with TEXT_IO;  -- predefined I/O package
  262.  
  263. package body Context_Directed_Update_Utilities is
  264.   -- Global constants, types, and objects used throughout the
  265.   -- package body follow below. The constants eliminate the use
  266.   -- of "magic numbes" in the code, thus increasing readability
  267.   -- and reliability.
  268.  
  269.   Number_of_Command_Forms : constant POSITIVE  :=  30;
  270.   Squote                  : constant CHARACTER := ''';
  271.   Dquote                  : constant CHARACTER := '"';
  272.   Blank                   : constant CHARACTER := ' ';
  273.   Period                  : constant CHARACTER := '.';
  274.   Uc_Lc_Offset            : constant POSITIVE  :=
  275.     CHARACTER'POS (ASCII.LC_A) - CHARACTER'POS ('A');
  276.  
  277.   Terminate_Abnormally : exception;  -- Used as an error escape in the
  278.                                      -- processing routines below.
  279.  
  280.   subtype Set_of_Lower_Case_Letters is CHARACTER range
  281.     ASCII.LC_A .. ASCII.LC_Z;
  282.  
  283.   subtype File_Name_Type is STRING (1 .. Maximum_File_Name_Length);
  284.  
  285.   type Files_Type is
  286.     record
  287.       Base_File_Name,
  288.       Deck_File_Name,
  289.       New_File_Name,
  290.       Error_File_Name   : File_Name_Type;
  291.       Base_File_Length,
  292.       Deck_File_Length,
  293.       New_File_Length,
  294.       Error_File_Length : NATURAL;
  295.       Base_File,
  296.       Deck_File,
  297.       New_File,
  298.       Error_File,
  299.       Temporary_File    : TEXT_IO.FILE_TYPE;
  300.     end record;
  301.  
  302.   subtype Line_Type is STRING (1 .. Maximum_Line_Length);
  303.  
  304.   type Data_Line_Type is
  305.     record
  306.       Line   : Line_Type;
  307.       Length : NATURAL;
  308.     end record;
  309.  
  310.   type Type_of_Error_Type is (Invalid_Command, Missing_Begin,
  311.     Extra_Begin, Unsequenced, End_of_File, Invalid_Parameter,
  312.     Nonexistant_Column, Pattern_Failure, Missing_Parameter,
  313.     Extra_Parameter, Resultant_Overflow);
  314.  
  315.   type Deck_Info_Type is
  316.     record
  317.       Deck_Line         : Data_Line_Type;
  318.       Deck_Line_Number,
  319.       Column            : NATURAL;
  320.     end record;
  321.  
  322.   Curr_Base_Line_Number : POSITIVE;
  323.   Read_From_Temp_File   : BOOLEAN;
  324.   Expecting_Begin       : BOOLEAN;
  325.  
  326.   type Command_Forms_Array_Type is array (POSITIVE range <>) of Data_Line_Type;
  327.   Command_Forms_Array : Command_Forms_Array_Type (1 .. Number_of_Command_Forms);
  328.  
  329.   subtype Begin_Range is POSITIVE range 1 .. 5;
  330.   subtype Comment_Range is POSITIVE range 6 .. 12;
  331.   subtype Copy_Range is POSITIVE range 13 .. 16;
  332.   subtype Delete_Range is POSITIVE range 17 .. 22;
  333.   subtype Echo_Range is POSITIVE range 23 .. 25;
  334.   subtype Edit_Range is POSITIVE range 26 .. 28;
  335.   -- The following procedure takes a data record and converts all
  336.   -- lower case characters to upper case.
  337.  
  338.   procedure Convert_to_Upper_Case (Line : in out Data_Line_Type) is
  339.   begin
  340.     for I in 1 .. Line.Length loop
  341.       if Line.Line (I) in Set_of_Lower_Case_Letters then
  342.         Line.Line (I) := CHARACTER'VAL (CHARACTER'POS (Line.Line (I)) -
  343.           Uc_Lc_Offset);
  344.       end if;
  345.     end loop;
  346.   end Convert_to_Upper_Case;
  347.   ----------------------------------------------------------------------
  348.  
  349.   -- The following procedure reads the next line in the CDUPDATE deck
  350.   -- file and returns it in a data record.
  351.  
  352.   procedure Read_a_Line (
  353.     Input_File   : in out TEXT_IO.FILE_TYPE;
  354.     Number_Lines : in out NATURAL;
  355.     Output_Line  :    out Data_Line_Type) is
  356.   begin
  357.     TEXT_IO.GET_LINE (Input_File,Output_Line.Line,Output_Line.Length);
  358.  
  359.     Number_Lines := Number_Lines + 1;
  360.   end Read_a_Line;
  361.   ----------------------------------------------------------------------
  362.  
  363.   -- The following procedure grabs the next parameter off the current
  364.   -- CDUPDATE command line being processed. Several options are
  365.   -- specified to check for the command name itself, and delimiters
  366.   -- in the case of the EDIT command.
  367.  
  368.   procedure Get_Next_Word (
  369.     Command_Word : in     BOOLEAN;
  370.     Line         : in     Data_Line_Type;
  371.     Delimiter1,
  372.     Delimiter2   : in     CHARACTER;
  373.     Line_Pointer : in out POSITIVE;
  374.     Word         :    out Data_Line_Type) is
  375.  
  376.     Word_Pointer : POSITIVE := 1;
  377.     Delimiter    : CHARACTER;
  378.   begin
  379.     Word := (Line => (others => Blank), Length => 0);
  380.  
  381.     -- Skip over initial blanks, unless we are looking for a CDUPDATE
  382.     -- command (which must start in column 1).
  383.  
  384.     if not Command_Word then
  385.       while (Line_Pointer <= Line.Length) and then
  386.             (Line.Line (Line_Pointer) = Blank) loop
  387.         Line_Pointer := Line_Pointer + 1;
  388.       end loop;
  389.     end if;
  390.  
  391.     -- Store the delimiter we are currently at.
  392.  
  393.     if (Line_Pointer <= Line.Length) and then
  394.        (((Delimiter1 /= Blank) or (Delimiter2 /= Blank)) and
  395.         ((Line.Line (Line_Pointer) = Delimiter1) or
  396.          (Line.Line (Line_Pointer) = Delimiter2))
  397.        ) then  -- EDIT pattern parameters
  398.         Word.Line (Word_Pointer) := Line.Line (Line_Pointer);
  399.         Delimiter := Line.Line (Line_Pointer);
  400.         Word_Pointer := Word_Pointer + 1;
  401.         Line_Pointer := Line_Pointer + 1;
  402.     else  -- all other parameters
  403.       Delimiter := Blank;
  404.     end if;
  405.  
  406.     -- Store the parameter.
  407.  
  408.     while (Line_Pointer <= Line.Length) and then
  409.           (Line.Line (Line_Pointer) /= Delimiter) loop
  410.         Word.Line (Word_Pointer) := Line.Line (Line_Pointer);
  411.         Word_Pointer := Word_Pointer + 1;
  412.         Line_Pointer := Line_Pointer + 1;
  413.     end loop;
  414.  
  415.     -- Special case check for EDIT pattern parameters.
  416.  
  417.     if (Line_Pointer <= Line.Length) and then
  418.        ((Delimiter /= Blank) and
  419.         (Line.Line (Line_Pointer) = Delimiter)
  420.        ) then
  421.         Word.Line (Word_Pointer) := Line.Line (Line_Pointer);
  422.         Word_Pointer := Word_Pointer + 1;
  423.         Line_Pointer := Line_Pointer + 1;
  424.     end if;
  425.  
  426.     Word.Length := Word_Pointer - 1;
  427.   end Get_Next_Word;
  428.   ----------------------------------------------------------------------
  429.  
  430.   -- The following procedure handles the printing of all error messages
  431.   -- to the error file.
  432.  
  433.   procedure Print_Error (
  434.     Deck_Info            : in     Deck_Info_Type;
  435.     Type_of_Error        : in     Type_of_Error_Type;
  436.     Options              : in     Options_Type;
  437.     Error_File           : in out TEXT_IO.FILE_TYPE;
  438.     Total_Error_Commands : in out NATURAL) is
  439.   begin
  440.     Total_Error_Commands := Total_Error_Commands + 1;
  441.  
  442.     if Options.Print_Errors then
  443.       case Type_of_Error is
  444.         when Invalid_Command =>
  445.           TEXT_IO.PUT (Error_File,"--> Invalid CDUPDATE command");
  446.         when Missing_Begin =>
  447.           TEXT_IO.PUT (Error_File,"--> Missing " & Command_Code &
  448.             "BEGIN command");
  449.         when Extra_Begin =>
  450.           TEXT_IO.PUT (Error_File,"--> Extra " & Command_Code &
  451.             "BEGIN command (ignored)");
  452.         when Unsequenced =>
  453.           TEXT_IO.PUT (Error_File,"--> Unsequenced line number parameter");
  454.         when End_of_File =>
  455.           TEXT_IO.PUT (Error_File,"--> Line specified beyond EOF(baseline)");
  456.         when Invalid_Parameter =>
  457.           TEXT_IO.PUT (Error_File,"--> Invalid parameter encountered");
  458.         when Nonexistant_Column =>
  459.           TEXT_IO.PUT (Error_File,"--> Column specified beyond line length");
  460.         when Pattern_Failure =>
  461.           TEXT_IO.PUT (Error_File,"--> Substitution pattern not found");
  462.         when Missing_Parameter =>
  463.           TEXT_IO.PUT (Error_File,"--> Expecting to find another parameter");
  464.         when Extra_Parameter =>
  465.           TEXT_IO.PUT (Error_File,"--> Extra parameter (ignored)");
  466.         when Resultant_Overflow =>
  467.           TEXT_IO.PUT (Error_File,"--> New pattern causes overflow of maximum line length");
  468.       end case;
  469.  
  470.       TEXT_IO.PUT_LINE (Error_File," at line" &
  471.         NATURAL'IMAGE (Deck_Info.Deck_Line_Number) & Period);
  472.  
  473.       TEXT_IO.PUT_LINE (Error_File,
  474.         Deck_Info.Deck_Line.Line (1 .. Deck_Info.Deck_Line.Length));
  475.  
  476.       for I in 1 .. Deck_Info.Column - 2 loop
  477.         TEXT_IO.PUT (Error_File,Period);
  478.       end loop;
  479.  
  480.       TEXT_IO.PUT (Error_File,ASCII.CIRCUMFLEX);
  481.       TEXT_IO.NEW_LINE (Error_File);
  482.       TEXT_IO.NEW_LINE (Error_File);
  483.     end if;
  484.   end Print_Error;
  485.   -- The following procedure processes all BEGIN commands.
  486.  
  487.   procedure Process_Begin (
  488.     Options         : in     Options_Type;
  489.     Deck_Info       : in     Deck_Info_Type;
  490.     Expecting_Begin : in out BOOLEAN;
  491.     Files           : in out Files_Type;
  492.     Statistics      : in out Statistics_Type) is
  493.   begin
  494.     if not Expecting_Begin then  -- A BEGIN command has already appeared.
  495.       Print_Error (Deck_Info,Extra_Begin,Options,Files.Error_File,
  496.         Statistics.Total_Error_Commands);
  497.     else
  498.       begin
  499.         TEXT_IO.CLOSE (Files.New_File);
  500.         TEXT_IO.CREATE (Files.New_File,TEXT_IO.OUT_FILE,
  501.           Files.New_File_Name (1 .. Files.New_File_Length));
  502.       exception
  503.         when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  504.           raise New_File_Rewrite_Error;
  505.       end;
  506.  
  507.       Statistics.Number_New_Lines := 0;
  508.       Statistics.Total_Begin_Commands := Statistics.Total_Begin_Commands + 1;
  509.       Statistics.Total_Decks := Statistics.Total_Decks + 1;
  510.  
  511.       Expecting_Begin := FALSE;
  512.     end if;
  513.   end Process_Begin;
  514.   ----------------------------------------------------------------------
  515.  
  516.   -- The following procedure processes all COPY commands.
  517.  
  518.   procedure Process_Copy (
  519.     Options               : in     Options_Type;
  520.     Read_From_Temp_File,
  521.     Expecting_Begin       : in     BOOLEAN;
  522.     Deck_Info             : in out Deck_Info_Type;
  523.     Curr_Base_Line_Number : in out POSITIVE;
  524.     Files                 : in out Files_Type;
  525.     Statistics            : in out Statistics_Type) is
  526.  
  527.     Line,
  528.     Par1,
  529.     Par2,
  530.     Par3,
  531.     Par4          : Data_Line_Type;
  532.     Par1_Column,
  533.     Par3_Column,
  534.     First_Line,
  535.     Last_Line     : POSITIVE;
  536.   begin
  537.     if Expecting_Begin then  -- BEGIN command is required first
  538.       Print_Error (Deck_Info,Missing_Begin,Options,Files.Error_File,
  539.         Statistics.Total_Error_Commands);
  540.       raise Terminate_Abnormally;
  541.     end if;
  542.  
  543.     -- Get and check for validity all parameters.
  544.  
  545.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  546.       Deck_Info.Column,Par1);
  547.     Par1_Column := Deck_Info.Column;
  548.  
  549.     if Par1.Length = 0 then
  550.       Print_Error(Deck_Info,Missing_Parameter,Options,Files.Error_File,
  551.         Statistics.Total_Error_Commands);
  552.       raise Terminate_Abnormally;
  553.     end if;
  554.  
  555.     begin
  556.       First_Line := POSITIVE'VALUE (Par1.Line (1 .. Par1.Length));
  557.     exception
  558.       when CONSTRAINT_ERROR =>
  559.         Print_Error (Deck_Info,Invalid_Parameter,Options,
  560.           Files.Error_File,Statistics.Total_Error_Commands);
  561.         raise Terminate_Abnormally;
  562.     end;
  563.  
  564.     if First_Line < Curr_Base_Line_Number then
  565.       Print_Error (Deck_Info,Unsequenced,Options,Files.Error_File,
  566.         Statistics.Total_Error_Commands);
  567.       raise Terminate_Abnormally;
  568.     end if;
  569.  
  570.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  571.       Deck_Info.Column,Par2);
  572.     Convert_to_Upper_Case (Par2);
  573.  
  574.     if Par2.Length = 0 then
  575.       Par3 := Par1;
  576.     elsif (Par2.Line (1 .. Par2.Length) /= "THROUGH") and
  577.           (Par2.Line (1 .. Par2.Length) /= "TO") and
  578.           (Par2.Line (1 .. Par2.Length) /= "THRU") and
  579.           (Par2.Line (1 .. Par2.Length) /= "..") then
  580.       Par3 := Par2;
  581.     else
  582.       Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  583.         Deck_Info.Column,Par3);
  584.     end if;
  585.  
  586.     Par3_Column := Deck_Info.Column;
  587.  
  588.     begin
  589.       Last_Line := POSITIVE'VALUE (Par3.Line (1 .. Par3.Length));
  590.     exception
  591.       when CONSTRAINT_ERROR =>
  592.         Print_Error (Deck_Info,Invalid_Parameter,Options,
  593.           Files.Error_File,Statistics.Total_Error_Commands);
  594.         raise Terminate_Abnormally;
  595.     end;
  596.  
  597.     if Last_Line < First_Line then
  598.       Print_Error(Deck_Info,Unsequenced,Options,Files.Error_File,
  599.         Statistics.Total_Error_Commands);
  600.       raise Terminate_Abnormally;
  601.     end if;
  602.  
  603.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  604.       Deck_Info.Column,Par4);
  605.  
  606.     if Par4.Length /= 0 then
  607.       Print_Error (Deck_Info,Extra_Parameter,Options,
  608.         Files.Error_File,Statistics.Total_Error_Commands);
  609.     end if;
  610.  
  611.     -- Delete all lines not explicitly accounted for thus far.
  612.     -- (This can happen if no DELETE commands appear in the
  613.     -- CDUPDATE deck.)
  614.  
  615.     for I in Curr_Base_Line_Number .. First_Line - 1 loop
  616.       if Read_From_Temp_File then
  617.         if TEXT_IO.END_OF_FILE (Files.Temporary_File) then
  618.           Deck_Info.Column := Par1_Column;
  619.           Print_Error (Deck_Info,End_of_File,Options,
  620.             Files.Error_File,Statistics.Total_Error_Commands);
  621.           Curr_Base_Line_Number := I;
  622.           raise Terminate_Abnormally;
  623.         end if;
  624.  
  625.         TEXT_IO.SKIP_LINE (Files.Temporary_File);
  626.       else
  627.         if TEXT_IO.END_OF_FILE (Files.Base_File) then
  628.           Deck_Info.Column := Par1_Column;
  629.           Print_Error (Deck_Info,End_of_File,Options,
  630.             Files.Error_File,Statistics.Total_Error_Commands);
  631.           Curr_Base_Line_Number := I;
  632.           raise Terminate_Abnormally;
  633.         end if;
  634.  
  635.         TEXT_IO.SKIP_LINE (Files.Base_File);
  636.       end if;
  637.     end loop;
  638.  
  639.     -- Copy the lines specified.
  640.  
  641.     for I in First_Line .. Last_Line loop
  642.       if Read_From_Temp_File then
  643.         if TEXT_IO.END_OF_FILE (Files.Temporary_File) then
  644.           Deck_Info.Column := Par3_Column;
  645.  
  646.           Print_Error (Deck_Info,End_of_File,Options,
  647.             Files.Error_File,Statistics.Total_Error_Commands);
  648.  
  649.           Last_Line := I - 1;
  650.           exit;
  651.         end if;
  652.  
  653.         TEXT_IO.GET_LINE (Files.Temporary_File,Line.Line,Line.Length);
  654.         TEXT_IO.PUT_LINE (Files.New_File,Line.Line (1 .. Line.Length));
  655.       else
  656.         if TEXT_IO.END_OF_FILE (Files.Base_File) then
  657.           Deck_Info.Column := Par3_Column;
  658.  
  659.           Print_Error (Deck_Info,End_of_File,Options,
  660.             Files.Error_File,Statistics.Total_Error_Commands);
  661.  
  662.           Last_Line := I - 1;
  663.           exit;
  664.         end if;
  665.  
  666.         TEXT_IO.GET_LINE (Files.Base_File,Line.Line,Line.Length);
  667.         TEXT_IO.PUT_LINE (Files.New_File,Line.Line (1 .. Line.Length));
  668.       end if;
  669.     end loop;
  670.  
  671.     Statistics.Number_New_Lines := Statistics.Number_New_Lines +
  672.       (Last_Line - First_Line + 1);
  673.     Curr_Base_Line_Number := Last_Line + 1;
  674.     Statistics.Total_Copy_Commands := Statistics.Total_Copy_Commands + 1;
  675.     Statistics.Number_Base_Lines := Statistics.Number_Base_Lines +
  676.       (Last_Line - Curr_Base_Line_Number + 1);
  677.   exception
  678.     when Terminate_Abnormally =>
  679.       null;  -- Simply exit this subprogram.
  680.   end Process_Copy;
  681.   ----------------------------------------------------------------------
  682.  
  683.   -- The following procedure processes all DELETE commands.
  684.  
  685.   procedure Process_Deletion (
  686.     Options               : in     Options_Type;
  687.     Read_From_Temp_File,
  688.     Expecting_Begin       : in     BOOLEAN;
  689.     Deck_Info             : in out Deck_Info_Type;
  690.     Curr_Base_Line_Number : in out NATURAL;
  691.     Files                 : in out Files_Type;
  692.     Statistics            : in out Statistics_Type) is
  693.  
  694.     Par1,
  695.     Par2,
  696.     Par3,
  697.     Par4          : Data_Line_Type;
  698.     Par3_Column,
  699.     First_Line,
  700.     Last_Line     : POSITIVE;
  701.   begin
  702.     if Expecting_Begin then  -- A BEGIN command is required first.
  703.       Print_Error (Deck_Info,Missing_Begin,Options,Files.Error_File,
  704.         Statistics.Total_Error_Commands);
  705.       raise Terminate_Abnormally;
  706.     end if;
  707.  
  708.     -- Get and check for validity all parameters.
  709.  
  710.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  711.       Deck_Info.Column,Par1);
  712.  
  713.     if Par1.Length = 0 then
  714.       Print_Error (Deck_Info,Missing_Parameter,Options,
  715.         Files.Error_File,Statistics.Total_Error_Commands);
  716.       raise Terminate_Abnormally;
  717.     end if;
  718.  
  719.     begin
  720.       First_Line := POSITIVE'VALUE (Par1.Line (1 .. Par1.Length));
  721.     exception
  722.       when CONSTRAINT_ERROR =>
  723.         Print_Error (Deck_Info,Invalid_Parameter,Options,
  724.           Files.Error_File,Statistics.Total_Error_Commands);
  725.         raise Terminate_Abnormally;
  726.     end;
  727.  
  728.     if First_Line < Curr_Base_Line_Number then
  729.       Print_Error (Deck_Info,Unsequenced,Options,
  730.         Files.Error_File,Statistics.Total_Error_Commands);
  731.       raise Terminate_Abnormally;
  732.     end if;
  733.     
  734.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  735.       Deck_Info.Column,Par2);
  736.     Convert_to_Upper_Case (Par2);
  737.  
  738.     if Par2.Length = 0 then
  739.       Par3 := Par1;
  740.     elsif (Par2.Line (1 .. Par2.Length) /= "THROUGH") and
  741.           (Par2.Line (1 .. Par2.Length) /= "TO") and
  742.           (Par2.Line (1 .. Par2.Length) /= "THRU") and
  743.           (Par2.Line (1 .. Par2.Length) /= "..") then
  744.       Par3 := Par2;
  745.     else
  746.       Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  747.         Deck_Info.Column,Par3);
  748.     end if;
  749.  
  750.     Par3_Column := Deck_Info.Column;
  751.  
  752.     begin
  753.       Last_Line := POSITIVE'VALUE (Par3.Line (1 .. Par3.Length));
  754.     exception
  755.       when CONSTRAINT_ERROR =>
  756.         Print_Error (Deck_Info,Invalid_Parameter,Options,
  757.           Files.Error_File,Statistics.Total_Error_Commands);
  758.         raise Terminate_Abnormally;
  759.     end;
  760.  
  761.     if Last_Line < First_Line then
  762.       Print_Error (Deck_Info,Unsequenced,Options,
  763.         Files.Error_File,Statistics.Total_Error_Commands);
  764.       raise Terminate_Abnormally;
  765.     end if;
  766.  
  767.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  768.       Deck_Info.Column,Par4);
  769.  
  770.     if Par4.Length /= 0 then
  771.       Print_Error (Deck_Info,Extra_Parameter,Options,
  772.         Files.Error_File,Statistics.Total_Error_Commands);
  773.     end if;
  774.  
  775.     -- Delete any lines not explicitly accounted for thus far.
  776.  
  777.     if First_Line > Curr_Base_Line_Number then
  778.       First_Line := Curr_Base_Line_Number;
  779.     end if;
  780.  
  781.     -- Delete the lines specified.
  782.  
  783.     for I in First_Line .. Last_Line loop
  784.       if Read_From_Temp_File then
  785.         if TEXT_IO.END_OF_FILE (Files.Temporary_File) then
  786.           Deck_Info.Column := Par3_Column;
  787.  
  788.           Print_Error (Deck_Info,End_of_File,Options,
  789.             Files.Error_File,Statistics.Total_Error_Commands);
  790.  
  791.           Last_Line := I - 1;
  792.           exit;
  793.         end if;
  794.  
  795.         TEXT_IO.SKIP_LINE (Files.Temporary_File);
  796.       else
  797.         if TEXT_IO.END_OF_FILE (Files.Base_File) then
  798.           Deck_Info.Column := Par3_Column;
  799.  
  800.           Print_Error(Deck_Info,End_of_File,Options,
  801.             Files.Error_File,Statistics.Total_Error_Commands);
  802.  
  803.           Last_Line := I - 1;
  804.           exit;
  805.         end if;
  806.  
  807.         TEXT_IO.SKIP_LINE (Files.Base_File);
  808.       end if;
  809.     end loop;
  810.  
  811.     Curr_Base_Line_Number := Last_Line + 1;
  812.     Statistics.Total_Delete_Commands := Statistics.Total_Delete_Commands + 1;
  813.     Statistics.Number_Base_Lines := Statistics.Number_Base_Lines +
  814.       (Last_Line - First_Line + 1);
  815.   exception
  816.     when Terminate_Abnormally =>
  817.       null;  -- Simply exit this subprogram.
  818.   end Process_Deletion;
  819.   ----------------------------------------------------------------------
  820.  
  821.   -- The following procedure processes ECHO commands.
  822.  
  823.   procedure Process_Echo (
  824.     Options       : in     Options_Type;
  825.     Deck_Info     : in out Deck_Info_Type;
  826.     Files         : in out Files_Type;
  827.     Statistics    : in out Statistics_Type) is
  828.  
  829.     Column        : POSITIVE := Deck_Info.Column;
  830.     Par1          : Data_Line_Type;
  831.   begin
  832.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  833.       Deck_Info.Column,Par1);
  834.  
  835.     if Par1.Length = 0 then  -- At least one parameter is required.
  836.       Print_Error (Deck_Info,Missing_Parameter,Options,Files.Error_File,
  837.         Statistics.Total_Error_Commands);
  838.     else
  839.       -- Echo the command line on the current TEXT_IO output file.
  840.  
  841.       TEXT_IO.PUT_LINE (TEXT_IO.CURRENT_OUTPUT,
  842.         Deck_Info.Deck_Line.Line (Column + 1 ..
  843.         Deck_Info.Deck_Line.Length));
  844.  
  845.       Statistics.Total_Echo_Commands := Statistics.Total_Echo_Commands + 1;
  846.     end if;
  847.   end Process_Echo;
  848.   ----------------------------------------------------------------------
  849.  
  850.   -- The following procedure processes EDIT commands.
  851.  
  852.   procedure Process_Edit (
  853.     Options               : in     Options_Type;
  854.     Read_From_Temp_File,
  855.     Expecting_Begin       : in     BOOLEAN;
  856.     Deck_Info             : in out Deck_Info_Type;
  857.     Curr_Base_Line_Number : in out NATURAL;
  858.     Files                 : in out Files_Type;
  859.     Statistics            : in out Statistics_Type) is
  860.  
  861.     Line,
  862.     Line_Copy,
  863.     Editted_Line,
  864.     Par1,
  865.     Par2,
  866.     Par3,
  867.     Par4,
  868.     Par5,
  869.     Par5_Copy,
  870.     Par6,
  871.     Par7           : Data_Line_Type;
  872.     Par1_Column,
  873.     Par3_Column,
  874.     Par4_Column,
  875.     Line_Number,
  876.     Line_Start,
  877.     Edit_Start,
  878.     Column_Number  : POSITIVE;
  879.     Found_Pattern  : BOOLEAN := TRUE;
  880.   begin
  881.     if Expecting_Begin then  -- A BEGIN command is required first.
  882.       Print_Error (Deck_Info,Missing_Begin,Options,Files.Error_File,
  883.         Statistics.Total_Error_Commands);
  884.       raise Terminate_Abnormally;
  885.     end if;
  886.  
  887.     -- Get and check for validity all parameters.
  888.  
  889.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  890.       Deck_Info.Column,Par1);
  891.     Par1_Column := Deck_Info.Column;
  892.  
  893.     if Par1.Length = 0 then
  894.       Print_Error (Deck_Info,Missing_Parameter,Options,
  895.         Files.Error_File,Statistics.Total_Error_Commands);
  896.       raise Terminate_Abnormally;
  897.     end if;
  898.  
  899.     begin
  900.       Line_Number := POSITIVE'VALUE (Par1.Line (1 .. Par1.Length));
  901.     exception
  902.       when CONSTRAINT_ERROR =>
  903.         Print_Error (Deck_Info,Invalid_Parameter,Options,
  904.           Files.Error_File,Statistics.Total_Error_Commands);
  905.         raise Terminate_Abnormally;
  906.     end;
  907.  
  908.     if Line_Number < Curr_Base_Line_Number then
  909.       Print_Error (Deck_Info,Unsequenced,Options,
  910.         Files.Error_File,Statistics.Total_Error_Commands);
  911.       raise Terminate_Abnormally;
  912.     end if;
  913.  
  914.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  915.       Deck_Info.Column,Par2);
  916.     Convert_to_Upper_Case(Par2);
  917.  
  918.     if Par2.Length = 0 then
  919.       Print_Error (Deck_Info,Missing_Parameter,Options,
  920.         Files.Error_File,Statistics.Total_Error_Commands);
  921.       raise Terminate_Abnormally;
  922.     elsif Par2.Line (1 .. Par2.Length) /= "AT" then
  923.       Par3 := Par2;
  924.     else
  925.       Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  926.         Deck_Info.Column,Par3);
  927.     end if;
  928.  
  929.     Par3_Column := Deck_Info.Column;
  930.  
  931.     if Par3.Length = 0 then
  932.       Print_Error (Deck_Info,Missing_Parameter,Options,
  933.         Files.Error_File,Statistics.Total_Error_Commands);
  934.       raise Terminate_Abnormally;
  935.     end if;
  936.  
  937.     begin
  938.       Column_Number := POSITIVE'VALUE (Par3.Line (1 .. Par3.Length));
  939.     exception
  940.       when CONSTRAINT_ERROR =>
  941.         Print_Error (Deck_Info,Invalid_Parameter,Options,
  942.           Files.Error_File,Statistics.Total_Error_Commands);
  943.         raise Terminate_Abnormally;
  944.     end;
  945.  
  946.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Squote,Dquote,
  947.       Deck_Info.Column,Par4);
  948.     Par4_Column := Deck_Info.Column;
  949.  
  950.     if Par4.Length = 0 then
  951.       Print_Error (Deck_Info,Missing_Parameter,Options,
  952.         Files.Error_File,Statistics.Total_Error_Commands);
  953.       raise Terminate_Abnormally;
  954.     elsif ((Par4.Line (1) /= Squote) and (Par4.Line (1) /= Dquote)) or
  955.           ((Par4.Line (Par4.Length) /= Squote) and
  956.            (Par4.Line (Par4.Length) /= Dquote)) or
  957.           (Par4.Line (1) /= Par4.Line (Par4.Length)) then
  958.       Print_Error (Deck_Info,Invalid_Parameter,Options,
  959.         Files.Error_File,Statistics.Total_Error_Commands);
  960.       raise Terminate_Abnormally;
  961.     end if;
  962.  
  963.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Squote,Dquote,
  964.       Deck_Info.Column,Par5);
  965.     Par5_Copy := Par5;
  966.     Convert_to_Upper_Case (Par5);
  967.  
  968.     if Par5.Length = 0 then
  969.       Print_Error (Deck_Info,Missing_Parameter,Options,
  970.         Files.Error_File,Statistics.Total_Error_Commands);
  971.       raise Terminate_Abnormally;
  972.     elsif (Par5.Line (1 .. Par5.Length) /= "BECOMES") and
  973.           (Par5.Line (1 .. Par5.Length) /= "TO") then
  974.       Par6 := Par5_Copy;
  975.     else
  976.       Get_Next_Word (FALSE,Deck_Info.Deck_Line,Squote,Dquote,
  977.         Deck_Info.Column,Par6);
  978.     end if;
  979.  
  980.     if ((Par6.Line (1) /= Squote) and (Par6.Line (1) /= Dquote)) or
  981.        ((Par6.Line (Par6.Length) /= Squote) and
  982.         (Par6.Line (Par6.Length) /= Dquote)) or
  983.         (Par6.Line (1) /= Par6.Line (Par6.Length)) then
  984.       Print_Error (Deck_Info,Invalid_Parameter,Options,
  985.         Files.Error_File,Statistics.Total_Error_Commands);
  986.       raise Terminate_Abnormally;
  987.     end if;
  988.  
  989.     Get_Next_Word (FALSE,Deck_Info.Deck_Line,Blank,Blank,
  990.       Deck_Info.Column,Par7);
  991.  
  992.     if Par7.Length /= 0 then
  993.       Print_Error (Deck_Info,Extra_Parameter,Options,
  994.         Files.Error_File,Statistics.Total_Error_Commands);
  995.     end if;
  996.  
  997.     -- Delete any lines not explicitly accounted for thus far.
  998.  
  999.     for I in Curr_Base_Line_Number .. Line_Number - 1 loop
  1000.       if Read_From_Temp_File then
  1001.         if TEXT_IO.END_OF_FILE (Files.Temporary_File) then
  1002.           Deck_Info.Column := Par1_Column;
  1003.           Print_Error (Deck_Info,End_of_File,Options,
  1004.             Files.Error_File,Statistics.Total_Error_Commands);
  1005.           Curr_Base_Line_Number := I;
  1006.           raise Terminate_Abnormally;
  1007.         end if;
  1008.  
  1009.         TEXT_IO.SKIP_LINE (Files.Temporary_File);
  1010.       else
  1011.         if TEXT_IO.END_OF_FILE (Files.Base_File) then
  1012.           Deck_Info.Column := Par1_Column;
  1013.           Print_Error (Deck_Info,End_of_File,Options,
  1014.             Files.Error_File,Statistics.Total_Error_Commands);
  1015.           Curr_Base_Line_Number := I;
  1016.           raise Terminate_Abnormally;
  1017.         end if;
  1018.  
  1019.         TEXT_IO.SKIP_LINE (Files.Base_File);
  1020.       end if;
  1021.     end loop;
  1022.  
  1023.     -- Read in the line to edit.
  1024.  
  1025.     if Read_From_Temp_File then
  1026.       if TEXT_IO.END_OF_FILE (Files.Temporary_File) then
  1027.         Deck_Info.Column := Par1_Column;
  1028.         Print_Error (Deck_Info,End_of_File,Options,
  1029.           Files.Error_File,Statistics.Total_Error_Commands);
  1030.         raise Terminate_Abnormally;
  1031.       end if;
  1032.  
  1033.       TEXT_IO.GET_LINE (Files.Temporary_File,Line.Line,Line.Length);
  1034.     else
  1035.       if TEXT_IO.END_OF_FILE (Files.Base_File) then
  1036.         Deck_Info.Column := Par1_Column;
  1037.         Print_Error(Deck_Info,End_of_File,Options,
  1038.           Files.Error_File,Statistics.Total_Error_Commands);
  1039.         raise Terminate_Abnormally;
  1040.       end if;
  1041.  
  1042.       TEXT_IO.GET_LINE (Files.Base_File,Line.Line,Line.Length);
  1043.     end if;
  1044.  
  1045.     -- Perform error checking on this line and the EDIT command
  1046.     -- parameters specified.
  1047.  
  1048.     if Column_Number > Line.Length then
  1049.       Deck_Info.Column := Par3_Column;
  1050.       Print_Error (Deck_Info,Nonexistant_Column,Options,
  1051.         Files.Error_File,Statistics.Total_Error_Commands);
  1052.       Curr_Base_Line_Number := Line_Number + 1;
  1053.       raise Terminate_Abnormally;
  1054.     end if;
  1055.  
  1056.     Editted_Line := (Line => (others => Blank), Length => 0);
  1057.  
  1058.     for I in 1 .. Column_Number - 1 loop
  1059.       Editted_Line.Line (I) := Line.Line (I);
  1060.     end loop;
  1061.  
  1062.     -- Try to match the specified substitution pattern.
  1063.  
  1064.     if Options.Case_Sensitive then
  1065.       for I in 1 .. Par4.Length - 2 loop
  1066.         if Par4.Line (I+1) /= Line.Line (Column_Number+I-1) then
  1067.           Found_Pattern := FALSE;
  1068.         end if;
  1069.       end loop;
  1070.     else
  1071.       Line_Copy := Line;
  1072.       Convert_to_Upper_Case (Line_Copy);
  1073.       Convert_to_Upper_Case (Par4);
  1074.  
  1075.       for I in 1 .. Par4.Length - 2 loop
  1076.         if Par4.Line (I+1) /= Line_Copy.Line (Column_Number+I-1) then
  1077.           Found_Pattern := FALSE;
  1078.         end if;
  1079.       end loop;
  1080.     end if;
  1081.  
  1082.     if not Found_Pattern then
  1083.       Deck_Info.Column := Par4_Column;
  1084.       Print_Error (Deck_Info,Pattern_Failure,Options,
  1085.         Files.Error_File,Statistics.Total_Error_Commands);
  1086.       Curr_Base_Line_Number := Line_Number + 1;
  1087.       raise Terminate_Abnormally;
  1088.     end if;
  1089.  
  1090.     if (Column_Number + Par6.Length - 3) > Maximum_Line_Length then
  1091.       Print_Error (Deck_Info,Resultant_Overflow,Options,
  1092.         Files.Error_File,Statistics.Total_Error_Commands);
  1093.       Curr_Base_Line_Number := Line_Number + 1;
  1094.       raise Terminate_Abnormally;
  1095.     end if;
  1096.  
  1097.     -- Make the replacement, checking for length errors.
  1098.  
  1099.     for I in 1 .. Par6.Length - 2 loop
  1100.       Editted_Line.Line (Column_Number+I-1) := Par6.Line (I+1);
  1101.     end loop;
  1102.  
  1103.     Edit_Start := Column_Number + Par6.Length - 2;
  1104.     Line_Start := Column_Number + Par4.Length - 2;
  1105.  
  1106.     if (Edit_Start + Line.Length - Line_Start) > Maximum_Line_Length then
  1107.       Print_Error (Deck_Info,Resultant_Overflow,Options,
  1108.         Files.Error_File,Statistics.Total_Error_Commands);
  1109.       Curr_Base_Line_Number := Line_Number + 1;
  1110.       raise Terminate_Abnormally;
  1111.     end if;
  1112.  
  1113.     for I in 1 .. Line.Length + 1 - Line_Start loop
  1114.       Editted_Line.Line (Edit_Start+I-1) := Line.Line (Line_Start+I-1);
  1115.     end loop;
  1116.  
  1117.     Editted_Line.Length := Edit_Start + Line.Length - Line_Start;
  1118.  
  1119.     TEXT_IO.PUT_LINE (Files.New_File,Editted_Line.Line (1 .. Editted_Line.Length));
  1120.  
  1121.     Statistics.Total_Edit_Commands := Statistics.Total_Edit_Commands + 1;
  1122.     Statistics.Number_Base_Lines := Statistics.Number_Base_Lines +
  1123.       Line_Number - Curr_Base_Line_Number + 1;
  1124.     Statistics.Number_New_Lines := Statistics.Number_New_Lines + 1;
  1125.     Curr_Base_Line_Number := Line_Number + 1;
  1126.   exception
  1127.     when Terminate_Abnormally =>
  1128.       null;  -- Simply exit this subprogram.
  1129.   end Process_Edit;
  1130.   ----------------------------------------------------------------------
  1131.  
  1132.   -- The following procedure processes all END commands.
  1133.  
  1134.   procedure Process_End (
  1135.     Options               : in     Options_Type;
  1136.     Deck_Info             : in     Deck_Info_Type;
  1137.     Read_From_Temp_File,
  1138.     Expecting_Begin       : in out BOOLEAN;
  1139.     Curr_Base_Line_Number : in out NATURAL;
  1140.     Files                 : in out Files_Type;
  1141.     Statistics            : in out Statistics_Type) is
  1142.  
  1143.     Line : Data_Line_Type;
  1144.   begin
  1145.     if Expecting_Begin then  -- A BEGIN command is required first.
  1146.       Print_Error (Deck_Info,Missing_Begin,Options,Files.Error_File,
  1147.         Statistics.Total_Error_Commands);
  1148.       raise Terminate_Abnormally;
  1149.     end if;
  1150.  
  1151.     begin
  1152.       TEXT_IO.CLOSE (Files.New_File);
  1153.       TEXT_IO.OPEN (Files.New_File,TEXT_IO.IN_FILE,
  1154.         Files.New_File_Name (1 .. Files.New_File_Length));
  1155.     exception
  1156.       when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1157.         raise New_File_Reset_Error;
  1158.     end;
  1159.  
  1160.     begin
  1161.       TEXT_IO.DELETE (Files.Temporary_File);
  1162.       TEXT_IO.CREATE (Files.Temporary_File,TEXT_IO.OUT_FILE);
  1163.     exception
  1164.       when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1165.         raise Temporary_File_Rewrite_Error;
  1166.     end;
  1167.  
  1168.     while not TEXT_IO.END_OF_FILE (Files.New_File) loop
  1169.       TEXT_IO.GET_LINE (Files.New_File,Line.Line,Line.Length);
  1170.       TEXT_IO.PUT_LINE (Files.Temporary_File,Line.Line (1 .. Line.Length));
  1171.     end loop;
  1172.  
  1173.     begin
  1174.       TEXT_IO.RESET (Files.Temporary_File,TEXT_IO.IN_FILE);
  1175.     exception
  1176.       when TEXT_IO.STATUS_ERROR | TEXT_IO.USE_ERROR =>
  1177.         raise Temporary_File_Reset_Error;
  1178.     end;
  1179.  
  1180.     Read_From_Temp_File := TRUE;
  1181.     Expecting_Begin := TRUE;
  1182.     Curr_Base_Line_Number := 1;
  1183.     Statistics.Total_End_Commands := Statistics.Total_End_Commands + 1;
  1184.   exception
  1185.     when Terminate_Abnormally =>
  1186.       null;  -- Simply exit this subprogram.
  1187.   end Process_End;
  1188.   ----------------------------------------------------------------------
  1189.  
  1190.   -- The following procedure processes all insertions.
  1191.  
  1192.   procedure Process_Insertion (
  1193.     Options         : in     Options_Type;
  1194.     Deck_Info       : in     Deck_Info_Type;
  1195.     Expecting_Begin : in     BOOLEAN;
  1196.     Files           : in out Files_Type;
  1197.     Statistics      : in out Statistics_Type) is
  1198.  
  1199.     Deck_Line_Copy : Data_Line_Type;
  1200.   begin
  1201.     if Expecting_Begin then  -- A BEGIN command is required first.
  1202.       Print_Error (Deck_Info,Missing_Begin,Options,Files.Error_File,
  1203.         Statistics.Total_Error_Commands);
  1204.       raise Terminate_Abnormally;
  1205.     end if;
  1206.  
  1207.     -- Check for the special case of two adjacent command code
  1208.     -- characters, and a line <= 1 character.
  1209.  
  1210.     if Deck_Info.Deck_Line.Length <= 1 then
  1211.       TEXT_IO.PUT_LINE (Files.New_File,
  1212.         Deck_Info.Deck_Line.Line (1 .. Deck_Info.Deck_Line.Length));
  1213.     elsif (Deck_Info.Deck_Line.Line (1) = Command_Code) and
  1214.           (Deck_Info.Deck_Line.Line (2) = Command_Code) then
  1215.       for I in 2 .. Deck_Info.Deck_Line.Length loop
  1216.         Deck_Line_Copy.Line (I-1) := Deck_Info.Deck_Line.Line (I);
  1217.         Deck_Line_Copy.Length := Deck_Info.Deck_Line.Length - 1;
  1218.  
  1219.         TEXT_IO.PUT_LINE (Files.New_File,
  1220.           Deck_Line_Copy.Line (1 .. Deck_Line_Copy.Length));
  1221.       end loop;
  1222.     else
  1223.       TEXT_IO.PUT_LINE (Files.New_File,
  1224.         Deck_Info.Deck_Line.Line (1 .. Deck_Info.Deck_Line.Length));
  1225.     end if;
  1226.  
  1227.     Statistics.Number_New_Lines := Statistics.Number_New_Lines + 1;
  1228.     Statistics.Total_Insertions := Statistics.Total_Insertions + 1;
  1229.   exception
  1230.     when Terminate_Abnormally =>
  1231.       null;  -- Simply exit this subprogram.
  1232.   end Process_Insertion;
  1233.   ----------------------------------------------------------------------
  1234.  
  1235.   -- The following subprogram analyzes all CDUPDATE deck lines, and
  1236.   -- calls the appropriate processing routine above.
  1237.  
  1238.   procedure Analyze_and_Process (
  1239.     Options    : in     Options_Type;
  1240.     Deck_Line  : in     Data_Line_Type;
  1241.     Files      : in out Files_Type;
  1242.     Statistics : in out Statistics_Type) is
  1243.  
  1244.     type Type_of_Command_Type is (Begn,Comment,Copy,Delete,Echo,
  1245.       Edit,En,Error,Insert);
  1246.  
  1247.     Command              : Data_Line_Type;
  1248.     Column,
  1249.     Deck_Line_Pointer    : NATURAL;
  1250.     Deck_Info            : Deck_Info_Type;
  1251.  
  1252.     -- The following inner function returns the command name matched
  1253.     -- (if any).
  1254.  
  1255.     function Find_Command (Command_Name : in Data_Line_Type)
  1256.       return Type_of_Command_Type is
  1257.  
  1258.       Index : POSITIVE := Command_Forms_Array'FIRST;
  1259.     begin
  1260.       loop
  1261.         exit when (Index >= Command_Forms_Array'LAST) or else
  1262.                   (Command_Forms_Array (Index).Line
  1263.                     (1 .. Command_Forms_Array (Index).Length) =
  1264.                    Command_Name.Line (1 .. Command_Name.Length));
  1265.         Index := Index + 1;
  1266.       end loop;
  1267.  
  1268.       if Command_Forms_Array (Index).Line
  1269.            (1 .. Command_Forms_Array (Index).Length) =
  1270.          Command_Name.Line (1 .. Command_Name.Length) then
  1271.         if Index in Begin_Range then
  1272.           return Begn;
  1273.         elsif Index in Comment_Range then
  1274.           return Comment;
  1275.         elsif Index in Copy_Range then
  1276.           return Copy;
  1277.         elsif Index in Delete_Range then
  1278.           return Delete;
  1279.         elsif Index in Echo_Range then
  1280.           return Echo;
  1281.         elsif Index in Edit_Range then
  1282.           return Edit;
  1283.         else
  1284.           return En;
  1285.         end if;
  1286.       elsif Command_Name.Length = 0 then
  1287.         return Insert;
  1288.       elsif (Command_Name.Length = 1) and (Command_Name.Line (1) = Command_Code) then
  1289.         return Error;
  1290.       elsif (Command_Name.Line (1) = Command_Code) and (Command_Name.Line (2) = Command_Code) then
  1291.         return Insert;
  1292.       elsif Command_Name.Line (1) = Command_Code then
  1293.         return Error;
  1294.       else
  1295.         return Insert;
  1296.       end if;
  1297.     end Find_Command;
  1298.   begin  -- Analyze_and_Process
  1299.     Deck_Info.Column := 1;
  1300.     Deck_Info.Deck_Line := Deck_Line;
  1301.     Deck_Info.Deck_Line_Number := Statistics.Number_Deck_Lines;
  1302.  
  1303.     Get_Next_Word (TRUE,Deck_Line,Blank,Blank,Deck_Info.Column,Command);
  1304.  
  1305.     Convert_to_Upper_Case (Command);
  1306.  
  1307.     case Find_Command (Command) is
  1308.       when Begn =>
  1309.         Process_Begin (Options,Deck_Info,Expecting_Begin,Files,Statistics);
  1310.       when Comment =>
  1311.         Statistics.Total_Comment_Commands := Statistics.Total_Comment_Commands + 1;
  1312.       when Copy =>
  1313.         Process_Copy (Options,Read_From_Temp_File,Expecting_Begin,
  1314.           Deck_Info,Curr_Base_Line_Number,Files,Statistics);
  1315.       when Delete =>
  1316.         Process_Deletion (Options,Read_From_Temp_File,Expecting_Begin,
  1317.           Deck_Info,Curr_Base_Line_Number,Files,Statistics);
  1318.       when Echo =>
  1319.         Process_Echo (Options,Deck_Info,Files,Statistics);
  1320.       when Edit =>
  1321.         Process_Edit (Options,Read_From_Temp_File,Expecting_Begin,
  1322.           Deck_Info,Curr_Base_Line_Number,Files,Statistics);
  1323.       when En =>
  1324.         Process_End (Options,Deck_Info,Read_From_Temp_File,
  1325.           Expecting_Begin,Curr_Base_Line_Number,Files,Statistics);
  1326.       when Error =>
  1327.         Print_Error (Deck_Info,Invalid_Command,Options,
  1328.           Files.Error_File,Statistics.Total_Error_Commands);
  1329.       when Insert =>
  1330.         Process_Insertion (Options,Deck_Info,Expecting_Begin,
  1331.           Files,Statistics);
  1332.     end case;
  1333.   end Analyze_and_Process;
  1334.   -- The following procedure is used to handle all special cases
  1335.   -- of assigning the file name parameters to the Files record.
  1336.  
  1337.   procedure Assign (
  1338.     In_File  : in     STRING;
  1339.     Out_File : in out STRING;
  1340.     Length   :    out NATURAL) is
  1341.   begin
  1342.     if In_File'LENGTH > Out_File'LENGTH then
  1343.       Out_File := In_File (In_File'FIRST .. In_File'FIRST +
  1344.         Out_File'LENGTH - 1);
  1345.       Length := Out_File'LENGTH;
  1346.     else
  1347.       Out_File (1 .. In_File'LENGTH) := In_File;
  1348.       Length := In_File'LENGTH;
  1349.     end if;
  1350.   end Assign;
  1351.   ----------------------------------------------------------------------
  1352.  
  1353.   -- The following visible procedure is a driver for the package
  1354.   -- body.
  1355.  
  1356.   procedure Cdupdate (
  1357.     Base_File_Name,
  1358.     Deck_File_Name,
  1359.     New_File_Name,
  1360.     Error_File_Name : in     STRING;
  1361.     Statistics      :    out Statistics_Type;
  1362.     Options         : in     Options_Type := Default_Options) is
  1363.  
  1364.     Deck_Line  : Data_Line_Type;
  1365.     Stats      : Statistics_Type := (others => 0);
  1366.     Files      : Files_Type;
  1367.   begin
  1368.     if (Base_File_Name'LENGTH  > Maximum_File_Name_Length) or
  1369.        (Deck_File_Name'LENGTH  > Maximum_File_Name_Length) or
  1370.        (New_File_Name'LENGTH   > Maximum_File_Name_Length) or
  1371.        (Error_File_Name'LENGTH > Maximum_File_Name_Length) then
  1372.       raise File_Name_Length_Error;
  1373.     end if;
  1374.  
  1375.     Command_Forms_Array ( 1).Line (1..2) := Command_Code & "B";
  1376.     Command_Forms_Array ( 1).Length      := 2;
  1377.     Command_Forms_Array ( 2).Line (1..3) := Command_Code & "BE";
  1378.     Command_Forms_Array ( 2).Length      := 3;
  1379.     Command_Forms_Array ( 3).Line (1..4) := Command_Code & "BEG";
  1380.     Command_Forms_Array ( 3).Length      := 4;
  1381.     Command_Forms_Array ( 4).Line (1..5) := Command_Code & "BEGI";
  1382.     Command_Forms_Array ( 4).Length      := 5;
  1383.     Command_Forms_Array ( 5).Line (1..6) := Command_Code & "BEGIN";
  1384.     Command_Forms_Array ( 5).Length      := 6;
  1385.     Command_Forms_Array ( 6).Line (1..2) := Command_Code & "*";
  1386.     Command_Forms_Array ( 6).Length      := 2;
  1387.     Command_Forms_Array ( 7).Line (1..3) := Command_Code & "--";
  1388.     Command_Forms_Array ( 7).Length      := 3;
  1389.     Command_Forms_Array ( 8).Line (1..4) := Command_Code & "COM";
  1390.     Command_Forms_Array ( 8).Length      := 4;
  1391.     Command_Forms_Array ( 9).Line (1..5) := Command_Code & "COMM";
  1392.     Command_Forms_Array ( 9).Length      := 5;
  1393.     Command_Forms_Array (10).Line (1..6) := Command_Code & "COMME";
  1394.     Command_Forms_Array (10).Length      := 6;
  1395.     Command_Forms_Array (11).Line (1..7) := Command_Code & "COMMEN";
  1396.     Command_Forms_Array (11).Length      := 7;
  1397.     Command_Forms_Array (12).Line (1..8) := Command_Code & "COMMENT";
  1398.     Command_Forms_Array (12).Length      := 8;
  1399.     Command_Forms_Array (13).Line (1..2) := Command_Code & "C";
  1400.     Command_Forms_Array (13).Length      := 2;
  1401.     Command_Forms_Array (14).Line (1..3) := Command_Code & "CO";
  1402.     Command_Forms_Array (14).Length      := 3;
  1403.     Command_Forms_Array (15).Line (1..4) := Command_Code & "COP";
  1404.     Command_Forms_Array (15).Length      := 4;
  1405.     Command_Forms_Array (16).Line (1..5) := Command_Code & "COPY";
  1406.     Command_Forms_Array (16).Length      := 5;
  1407.     Command_Forms_Array (17).Line (1..2) := Command_Code & "D";
  1408.     Command_Forms_Array (17).Length      := 2;
  1409.     Command_Forms_Array (18).Line (1..3) := Command_Code & "DE";
  1410.     Command_Forms_Array (18).Length      := 3;
  1411.     Command_Forms_Array (19).Line (1..4) := Command_Code & "DEL";
  1412.     Command_Forms_Array (19).Length      := 4;
  1413.     Command_Forms_Array (20).Line (1..5) := Command_Code & "DELE";
  1414.     Command_Forms_Array (20).Length      := 5;
  1415.     Command_Forms_Array (21).Line (1..6) := Command_Code & "DELET";
  1416.     Command_Forms_Array (21).Length      := 6;
  1417.     Command_Forms_Array (22).Line (1..7) := Command_Code & "DELETE";
  1418.     Command_Forms_Array (22).Length      := 7;
  1419.     Command_Forms_Array (23).Line (1..3) := Command_Code & "EC";
  1420.     Command_Forms_Array (23).Length      := 3;
  1421.     Command_Forms_Array (24).Line (1..4) := Command_Code & "ECH";
  1422.     Command_Forms_Array (24).Length      := 4;
  1423.     Command_Forms_Array (25).Line (1..5) := Command_Code & "ECHO";
  1424.     Command_Forms_Array (25).Length      := 5;
  1425.     Command_Forms_Array (26).Line (1..3) := Command_Code & "ED";
  1426.     Command_Forms_Array (26).Length      := 3;
  1427.     Command_Forms_Array (27).Line (1..4) := Command_Code & "EDI";
  1428.     Command_Forms_Array (27).Length      := 4;
  1429.     Command_Forms_Array (28).Line (1..5) := Command_Code & "EDIT";
  1430.     Command_Forms_Array (28).Length      := 5;
  1431.     Command_Forms_Array (29).Line (1..3) := Command_Code & "EN";
  1432.     Command_Forms_Array (29).Length      := 3;
  1433.     Command_Forms_Array (30).Line (1..4) := Command_Code & "END";
  1434.     Command_Forms_Array (30).Length      := 4;
  1435.  
  1436.     Assign (Base_File_Name,Files.Base_File_Name,Files.Base_File_Length);
  1437.     Assign (Deck_File_Name,Files.Deck_File_Name,Files.Deck_File_Length);
  1438.     Assign (New_File_Name,Files.New_File_Name,Files.New_File_Length);
  1439.     Assign (Error_File_Name,Files.Error_File_Name,Files.Error_File_Length);
  1440.  
  1441.     begin
  1442.       TEXT_IO.OPEN (Files.Base_File,TEXT_IO.IN_FILE,
  1443.         Files.Base_File_Name (1 .. Files.Base_File_Length));
  1444.     exception
  1445.       when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1446.         raise Base_File_Open_Error;
  1447.     end;
  1448.  
  1449.     begin
  1450.       TEXT_IO.OPEN (Files.Deck_File,TEXT_IO.IN_FILE,
  1451.         Files.Deck_File_Name (1 .. Files.Deck_File_Length));
  1452.     exception
  1453.       when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1454.         raise Deck_File_Open_Error;
  1455.     end;
  1456.  
  1457.     begin
  1458.       TEXT_IO.CREATE (Files.New_File,TEXT_IO.OUT_FILE,
  1459.         Files.New_File_Name (1 .. Files.New_File_Length));
  1460.     exception
  1461.       when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1462.         raise New_File_Create_Error;
  1463.     end;
  1464.  
  1465.     begin
  1466.       TEXT_IO.CREATE (Files.Temporary_File,TEXT_IO.OUT_FILE);
  1467.     exception
  1468.       when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1469.         raise Temporary_File_Create_Error;
  1470.     end;
  1471.  
  1472.     if Options.Print_Errors then
  1473.       begin
  1474.         TEXT_IO.CREATE (Files.Error_File,TEXT_IO.OUT_FILE,
  1475.           Files.Error_File_Name (1 .. Files.Error_File_Length));
  1476.       exception
  1477.         when TEXT_IO.STATUS_ERROR | TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  1478.           raise Error_File_Create_Error;
  1479.       end;
  1480.     end if;
  1481.  
  1482.     Curr_Base_Line_Number := 1;
  1483.     Read_From_Temp_File := FALSE;
  1484.     Expecting_Begin := TRUE;
  1485.  
  1486.     -- Iterate over all CDUPDATE deck lines.
  1487.  
  1488.     while not TEXT_IO.END_OF_FILE (Files.Deck_File) loop
  1489.       Read_a_Line (Files.Deck_File,
  1490.         Stats.Number_Deck_Lines,Deck_Line);
  1491.  
  1492.       Analyze_and_Process (Options,Deck_Line,Files,Stats);
  1493.     end loop;
  1494.  
  1495.     TEXT_IO.CLOSE (Files.Base_File);
  1496.     TEXT_IO.CLOSE (Files.Deck_File);
  1497.     TEXT_IO.CLOSE (Files.New_File);
  1498.     TEXT_IO.CLOSE (Files.Temporary_File);
  1499.  
  1500.     if Options.Print_Errors then
  1501.       TEXT_IO.CLOSE (Files.Error_File);
  1502.     end if;
  1503.  
  1504.     Statistics := Stats;
  1505.   end Cdupdate;
  1506.   ----------------------------------------------------------------------
  1507.  
  1508.   -- The following visible procedure performs the same functions as
  1509.   -- the procedure above, except that it doesn not return a
  1510.   -- statistics record.
  1511.  
  1512.   procedure Cdupdate (
  1513.     Base_File_Name,
  1514.     Deck_File_Name,
  1515.     New_File_Name,
  1516.     Error_File_Name : in     STRING;
  1517.     Options         : in     Options_Type := Default_Options) is
  1518.  
  1519.     Dummy_Statistics : Statistics_Type;
  1520.   begin
  1521.     Cdupdate (Base_File_Name,Deck_File_Name,New_File_Name,
  1522.       Error_File_Name,Dummy_Statistics,Options);
  1523.   end Cdupdate;
  1524. end Context_Directed_Update_Utilities;
  1525.  
  1526.