diff -uNr a/vtools/manifest b/vtools/manifest --- a/vtools/manifest 7a44b950832602e9d82b261bfa48709b8ff406950ad9ebf9ba1702cb1dc9a8e2e5e7b6affed5f936b4f1a29aa7fe674bf6796e7417e10cb5f410ada892c08875 +++ b/vtools/manifest fda2f695d7a689f09b2bca11b4baef63236a2e786db9ff81c91da47a0ccef55a10951fe4eb7f48a02394aa78f49c35e9cb20a6b892e78153451787f8cd4219f6 @@ -12,3 +12,4 @@ 589066 bvt vtools_fixes_rootdir_files Fix creation of files in the vtree root. Fix handling of empty vpatches. 615541 bvt vtools_small_fixes Fix vdiff gprbuild and remove useless variable from ksum. 615544 bvt vtools_add_vsh Add shell v-presser implementation. +615638 bvt vtools_add_vsh_utils Add utilities required by v-presser. diff -uNr a/vtools/src/vflow.adb b/vtools/src/vflow.adb --- a/vtools/src/vflow.adb false +++ b/vtools/src/vflow.adb f5e2f12ccf90384a05790422cf8909d988991ca0f1c5b711557e3b44b3987628ce8f8968b82618545bb6353466eaf6bf9e21bdcdec28cbba7572c0ef0fec89b1 @@ -0,0 +1,248 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; +with Ada.Command_Line; use Ada.Command_Line; +with Ada.Containers.Generic_Sort; + +procedure Vflow is + type Hunk_State is (Unsatisfied, Satisfied); + Empty_Hash : constant := 0; + type Hunk is record + Vpatch: Natural; + In_File: Natural; + Out_File: Natural; + In_Hash: Natural; + Out_Hash: Natural; + State: Hunk_State; + end record; + + Num_Hunks : Integer := Integer'Value(Argument(1)); + Num_Vpatches : Integer := Integer'Value(Argument(2)); + + subtype Hunk_Index is Natural range 1..Num_Hunks; + type Hunk_Array is array (Hunk_Index range <>) of Hunk; + All_Hunks : Hunk_Array(Hunk_Index'Range); + + subtype Vpatch_Index is Natural range 0..Num_Vpatches - 1; + type Vpatch_Hunks is array (Vpatch_Index'Range) of Hunk_Index; + VH_Low : Vpatch_Hunks := (others => Hunk_Index'First); + VH_High: Vpatch_Hunks := (others => Hunk_Index'First); + + type Vpatch_Relationship is array (Vpatch_Index'Range, Vpatch_Index'Range) of Boolean; + Vpatch_Dependencies: Vpatch_Relationship := (others => (others => False)); + Vpatch_Conflicts : Vpatch_Relationship := (others => (others => False)); + + function Get_Hunk return Hunk is + H: Hunk; + begin + Get(H.Vpatch); + Get(H.In_File); + Get(H.Out_File); + Get(H.In_Hash); + Get(H.Out_Hash); + H.State := Unsatisfied; + return H; + end Get_Hunk; + + procedure Read_Hunks is + I: Natural := All_Hunks'First; + begin + Read_Loop: + loop + exit Read_Loop when End_Of_File; + All_Hunks(I) := Get_Hunk; + I := I + 1; + end loop Read_Loop; + end Read_Hunks; + + procedure Init_Vpatch_Hunk_Bounds is + begin + for I in All_Hunks'Range loop + declare + V : Integer := All_Hunks(I).Vpatch; + begin + if VH_Low(V) > I or All_Hunks(VH_Low(V)).Vpatch /= V then + VH_Low(V) := I; + end if; + VH_High(V) := I; + end; + end loop; + end Init_Vpatch_Hunk_Bounds; + + procedure Populate_Conflicts is + function Conflicts(I: Vpatch_Index; J: Vpatch_Index) return Boolean is + begin + for A in VH_Low(I)..VH_High(I) loop + for B in VH_Low(J)..VH_High(J) loop + if (All_Hunks(A).In_File = All_Hunks(B).In_File) and + (All_Hunks(A).In_Hash = All_Hunks(B).In_Hash) then + return True; + end if; + end loop; + end loop; + return False; + end Conflicts; + begin + for I in Vpatch_Index'Range loop + for J in Vpatch_Index'Range loop + if I < J and then Conflicts(I,J) then + Vpatch_Conflicts(I,J) := True; + Vpatch_Conflicts(J,I) := True; + end if; + end loop; + end loop; + end Populate_Conflicts; + + procedure Solve is + Input_Hunks : Hunk_Array := All_Hunks; + Output_Hunks: Hunk_Array renames All_Hunks; + Finished : Boolean := False; + + -- Start of sorting boilerplate + -- + function Input_Before(A: Positive; B: Positive) return Boolean is + begin + return Input_Hunks(A).In_File < Input_Hunks(B).In_File; + end Input_Before; + + function Output_Before(A: Positive; B: Positive) return Boolean is + begin + return Output_Hunks(A).Out_File < Output_Hunks(B).Out_File; + end Output_Before; + + procedure Input_Swap(A: Positive; B: Positive) is + Tmp : Hunk; + begin + Tmp := Input_Hunks(B); + Input_Hunks(B) := Input_Hunks(A); + Input_Hunks(A) := Tmp; + end Input_Swap; + + procedure Output_Swap(A: Positive; B: Positive) is + Tmp : Hunk; + begin + Tmp := Output_Hunks(B); + Output_Hunks(B) := Output_Hunks(A); + Output_Hunks(A) := Tmp; + end Output_Swap; + + procedure Input_Sort is + new Ada.Containers.Generic_Sort (Positive, Input_Before, Input_Swap); + procedure Output_Sort is + new Ada.Containers.Generic_Sort (Positive, Output_Before, Output_Swap); + -- + -- End of sorting boilerplate + + function Check_Genesis(Input: in out Hunk_Array) return Boolean is + Is_Genesis : Boolean := True; + Vpatch: Vpatch_Index := Input(Input'First).Vpatch; + begin + for I in Input'Range loop + Is_Genesis := Is_Genesis and (Input(I).In_Hash = Empty_Hash); + end loop; + return Is_Genesis; + end Check_Genesis; + + function Try_Connect(Input: in out Hunk_Array; + Output: in out Hunk_Array) return Boolean is + I : Positive := Input'First; + J : Positive := Output'First; + All_Marked: Boolean := True; + begin + while I <= Input'Last and J <= Output'Last loop + if Input(I).State /= Unsatisfied or + Input(I).In_File < Output(J).Out_File then + I := I + 1; + elsif Input(I).In_File > Output(J).Out_File then + J := J + 1; + else + if Input(I).In_Hash = Output(J).Out_Hash and + Input(I).In_Hash /= Empty_Hash then + Input(I).State := Satisfied; + Vpatch_Dependencies(Input(Input'First).Vpatch, + Output(Output'First).Vpatch) := True; + end if; + I := I + 1; + end if; + end loop; + + for I in Input'Range loop + All_Marked := All_Marked and Input(I).State = Satisfied; + end loop; + return All_Marked; + end Try_Connect; + + begin + for I in Vpatch_Index'Range loop + Output_Sort(VH_Low(I), VH_High(I)); + Input_Sort(VH_Low(I), VH_High(I)); + end loop; + + for I in Vpatch_Index'Range loop + declare + Hunks_In : Hunk_Array renames Input_Hunks(VH_Low(I)..VH_High(I)); + begin + Finished := False; + + for J in Vpatch_Index'Range loop + if J /= I then + declare + Hunks_Out : Hunk_Array renames + Output_Hunks(VH_Low(J)..VH_High(J)); + begin + Finished := Try_Connect(Hunks_In, Hunks_Out); + exit when Finished; + end; + else + Finished := Check_Genesis(Hunks_In); + exit when Finished; + end if; + end loop; + + -- Looped through all vpatches, there are hunks without matched inputs: + if not Finished then + -- Check if the remaining hunks are file creations: + declare + OK : Boolean := True; + begin + for I in Hunks_In'Range loop + if Hunks_In(I).In_Hash = Empty_Hash and + Hunks_In(I).State = Unsatisfied then + Hunks_In(I).State := Satisfied; + end if; + OK := OK and (Hunks_In(I).State = Satisfied); + end loop; + if not OK then + raise Constraint_Error with "Unsatisfied hunks."; + end if; + end; + end if; + end; + end loop; + end Solve; + + procedure Produce_Output is + begin + Put_Line("v " & Integer'Image(Num_Vpatches)); + for I in Vpatch_Dependencies'Range(1) loop + for J in Vpatch_Dependencies'Range(2) loop + if Vpatch_Dependencies(I,J) then + Put_Line("d " & Integer'Image(I) & " " & Integer'Image(J)); + end if; + end loop; + end loop; + for I in Vpatch_Conflicts'Range(1) loop + for J in Vpatch_Conflicts'Range(2) loop + if Vpatch_Conflicts(I,J) then + Put_Line("c " & Integer'Image(I) & " " & Integer'Image(J)); + end if; + end loop; + end loop; + end Produce_Output; + +begin + Read_Hunks; + Init_Vpatch_Hunk_Bounds; + Populate_Conflicts; + Solve; + Produce_Output; +end Vflow; diff -uNr a/vtools/src/vsimplify.adb b/vtools/src/vsimplify.adb --- a/vtools/src/vsimplify.adb false +++ b/vtools/src/vsimplify.adb 9500518e8785191de23f54fe3b7fc69da03bc65473022a04e91764ab5cfe5092df794a2a6d3d429e65c000d9731c80bb802e32d40c4b770a2aa04484cea1a046 @@ -0,0 +1,109 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; + +procedure Vsimplify is + + Command : Character; + Num_Vpatches : Integer; + + procedure Simplify(Num_Vpatches : Integer) is + subtype Vpatch_Index is Natural range 0..Num_Vpatches - 1; + type Vpatch_Set is array (Vpatch_Index'Range) of Boolean; + type Vpatch_List is array (Vpatch_Index'Range) of Vpatch_Index; + type Vpatch_Relationship is array (Vpatch_Index'Range, Vpatch_Index'Range) of Boolean; + + Vpatch_Dependencies: Vpatch_Relationship := (others => (others => False)); + Vpatch_TC_Indirect : Vpatch_Relationship := (others => (others => False)); + Vpatch_Order : Vpatch_List := (others => 0); + Free_Vpatches : Vpatch_Set := (others => False); + N_Selected : Natural := 0; + + procedure Read_Commands is + I: Vpatch_Index; + J: Vpatch_Index; + begin + Read_Loop: + loop + exit Read_Loop when End_Of_File; + Get(Command); + if Command = 'd' then + Get(I); + Get(J); + Vpatch_Dependencies(I,J) := True; + elsif Command = 'C' then + -- Ignore conflicts in this tool, but consume the command + Get(I); + elsif Command = 'L' then + raise Constraint_Error with "Cannot simplify loops"; + elsif Command = 'P' then + Get(I); + Vpatch_Order(N_Selected) := I; + N_Selected := N_Selected + 1; + end if; + end loop Read_Loop; + + if N_Selected - 1 /= Vpatch_Order'Last then + raise Constraint_Error with "Not all vpatches present in the press order"; + end if; + + end Read_Commands; + + procedure Simplify_Inner is + begin + -- Fill Vpatch_TC_Indirect + for I in Vpatch_Order'Range loop + declare + N : Vpatch_Index := Vpatch_Order(I); + begin + for J in Vpatch_Dependencies'Range(2) loop + if Vpatch_Dependencies(N,J) then + for K in Vpatch_Dependencies'Range(2) loop + Vpatch_TC_Indirect(N,K) := Vpatch_TC_Indirect(N,K) or + Vpatch_Dependencies(J,K) or + Vpatch_TC_Indirect(J,K); + end loop; + end if; + end loop; + end; + end loop; + + -- Output Vpatch_TC_Indirect + for I in Vpatch_TC_Indirect'Range(1) loop + for J in Vpatch_TC_Indirect'Range(2) loop + if Vpatch_TC_Indirect(I,J) then + Put_Line("I " & Integer'Image(I) & " " & Integer'Image(J)); + end if; + end loop; + end loop; + + -- Remove redundant connections from Vpatch_Dependencies + for I in Vpatch_Dependencies'Range(1) loop + for J in Vpatch_TC_Indirect'Range(2) loop + Vpatch_Dependencies(I,J) := Vpatch_Dependencies(I,J) and + not Vpatch_TC_Indirect(I,J); + end loop; + end loop; + + -- Output filtered out Vpatch_Dependencies + for I in Vpatch_Dependencies'Range(1) loop + for J in Vpatch_TC_Indirect'Range(2) loop + if Vpatch_Dependencies(I,J) then + Put_Line("d " & Integer'Image(I) & " " & Integer'Image(J)); + end if; + end loop; + end loop; + end Simplify_Inner; + + begin + Read_Commands; + Simplify_Inner; + end Simplify; + +begin + Get(Command); + if Command /= 'v' then + raise Constraint_Error with "Expected 'v' command."; + end if; + Get(Num_Vpatches); + Simplify(Num_Vpatches); +end Vsimplify; diff -uNr a/vtools/src/vtoposort.adb b/vtools/src/vtoposort.adb --- a/vtools/src/vtoposort.adb false +++ b/vtools/src/vtoposort.adb 214030a75aac2bf72eed4688f78cae7b4c507e727e5fca2d49234778421a4bdb8c5c7c850f5379946244ac6919541154b256a4cbe8e05c53c253b0d0ea466eec @@ -0,0 +1,142 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; + +procedure Vtoposort is + + Command : Character; + Num_Vpatches : Integer; + + procedure Toposort(Num_Vpatches : Integer) is + subtype Vpatch_Index is Natural range 0..Num_Vpatches - 1; + type Vpatch_Set is array (Vpatch_Index'Range) of Boolean; + type Vpatch_List is array (Vpatch_Index'Range) of Vpatch_Index; + type Vpatch_Relationship is array + (Vpatch_Index'Range, Vpatch_Index'Range) of Boolean; + + Vpatch_Dependencies: Vpatch_Relationship := (others => (others => False)); + Vpatch_Conflicts : Vpatch_Relationship := (others => (others => False)); + Free_Vpatches : Vpatch_Set := (others => False); + + procedure Read_Commands is + I: Vpatch_Index; + J: Vpatch_Index; + begin + Read_Loop: + loop + exit Read_Loop when End_Of_File; + Get(Command); + if Command = 'd' then + Get(I); + Get(J); + Vpatch_Dependencies(I,J) := True; + elsif Command = 'c' then + Get(I); + Get(J); + Vpatch_Conflicts(I,J) := True; + elsif Command = 's' then + Get(I); + Free_Vpatches(I) := True; + else + raise Constraint_Error with "Unknown Command"; + end if; + end loop Read_Loop; + end Read_Commands; + + procedure Add_Dependencies is + Finish : Boolean := False; + begin + while not Finish loop + Finish := True; + for I in Free_Vpatches'Range loop + if Free_Vpatches(I) then + for J in Vpatch_Dependencies'Range(2) loop + if Vpatch_Dependencies(I,J) and not Free_Vpatches(J) then + Finish := False; + Free_Vpatches(J) := True; + end if; + end loop; + end if; + end loop; + end loop; + end Add_Dependencies; + + procedure Report_Conflicts is + begin + for I in Free_Vpatches'Range loop + if Free_Vpatches(I) then + for J in Vpatch_Conflicts'Range(2) loop + if Vpatch_Conflicts(I,J) and Free_Vpatches(J) then + Put_Line("C " & Integer'Image(I)); + Put_Line("C " & Integer'Image(J)); + end if; + end loop; + end if; + end loop; + end Report_Conflicts; + + procedure Sort is + Added_Vpatches : Vpatch_Set := (others => False); + Vpatch_Order : Vpatch_List := (others => 0); + N_Selected : Natural := 0; + Finished : Boolean := False; + Has_Loops : Boolean := False; + begin + while not Finished loop + Finished := True; + for I in Free_Vpatches'Range loop + if Free_Vpatches(I) then + declare + All_Satisfied : Boolean := True; + begin + + -- Check if all dependencies are already in the press order + for J in Vpatch_Dependencies'Range(2) loop + if Vpatch_Dependencies(I,J) then + All_Satisfied := All_Satisfied and Added_Vpatches(J); + end if; + end loop; + + -- All dependencies present, can add this vpatch: + if All_Satisfied then + Free_Vpatches(I) := False; + Added_Vpatches(I) := True; + Vpatch_Order(N_Selected) := I; + N_Selected := N_Selected + 1; + Finished := False; + end if; + end; + end if; + end loop; + end loop; + + -- Check if there are still free vpatches (there is a loop): + for I in Free_Vpatches'Range loop + if Free_Vpatches(I) then + Put_Line("L " & Integer'Image(I)); + Has_Loops := True; + end if; + end loop; + + -- Print vpatches in press order: + if not Has_Loops then + for I in Vpatch_Order'First..N_Selected - 1 loop + Put_Line("P " & Integer'Image(Vpatch_Order(I))); + end loop; + end if; + end Sort; + + begin + Read_Commands; + Add_Dependencies; + Report_Conflicts; + Sort; + end Toposort; + +begin + Get(Command); + if Command /= 'v' then + raise Constraint_Error with "Expected 'v' command."; + end if; + Get(Num_Vpatches); + Toposort(Num_Vpatches); +end Vtoposort; diff -uNr a/vtools/v.sh b/vtools/v.sh --- a/vtools/v.sh f33146be83aca8ebb2e0c75f69599985aeba8597ca79d00a2ed60b613147a48794ba4917edecac44920ead6d308c341c9b8b9531dd440d62f14f5f1a1a951a5b +++ b/vtools/v.sh 24defb473835e2980044a9bb526d2133f3056f62109b3a8136cb168019889f3c94bb721362cffcdb6df2ac52bbc6c111a680d9ba22b759ea676e7ddff7082fa1 @@ -89,6 +89,14 @@ done } +vfilter() { + awk -v N="$1" ' +BEGIN {r=0;} +$0 ~ /^diff -uNr/ {r=1;} +r == 1 && $1 == "---" {sub("[^/]*/", "", $2); ip=$2; ih=$3} +r == 1 && $1 == "+++" {sub("[^/]*/", "", $2); print N,ip,$2,ih,$3; r=0;}' +} + filterall() { n=0 diff -uNr a/vtools/vdiff.gpr b/vtools/vdiff.gpr --- a/vtools/vdiff.gpr b53569ef0e9899d5df98c9122ae62d980ed91cc03e9bf94a64cdcb99c1f0b540ae29e94835a6c96779bedcb8bef46d3927ac43dc794b697d04a391db0f4ee255 +++ b/vtools/vdiff.gpr 0406532e11310fe740c484d7c5b82e84c6f59d782eb2a695a773d509f61c5a57a3992c82b4ac5ed5f11bc4ab300ecc689988faa5f3c7d383f3b96639ce04ce85 @@ -4,7 +4,8 @@ for Object_Dir use "obj"; for Exec_Dir use "."; for Main use ("diff.c"); - for Excluded_Source_Files use ("vpatch.adb", "ksum.adb"); + for Excluded_Source_Files use ("vpatch.adb", "ksum.adb", "vflow.adb", + "vtoposort.adb", "vsimplify.adb"); package Builder is for Executable ("diff.c") use "vdiff"; end Builder; diff -uNr a/vtools/vflow.gpr b/vtools/vflow.gpr --- a/vtools/vflow.gpr false +++ b/vtools/vflow.gpr f9f7ce7f9def005d0a8872621043b8ed64ebd41344b966e370cbdf8ec4a1feaa881ae89b81db5b4322b650f9aef115ff111338701dabc91c8bfa8cb832ff0b44 @@ -0,0 +1,21 @@ +project Vflow is + for Languages use ("Ada"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Main use ("vflow.adb"); + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "debug"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O0", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + end case; + end Compiler; +end Vflow; diff -uNr a/vtools/vsimplify.gpr b/vtools/vsimplify.gpr --- a/vtools/vsimplify.gpr false +++ b/vtools/vsimplify.gpr c87b11449cf3c22505b950ab9482b91bcd2d3f590caf7c37705127dbb6e742f1a4c2ea6a2ad07b4ab45b7b22046a06832df3910548261393f2d3e999206d7c3c @@ -0,0 +1,21 @@ +project Vsimplify is + for Languages use ("Ada"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Main use ("vsimplify.adb"); + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "debug"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O0", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + end case; + end Compiler; +end Vsimplify; diff -uNr a/vtools/vtoposort.gpr b/vtools/vtoposort.gpr --- a/vtools/vtoposort.gpr false +++ b/vtools/vtoposort.gpr 257ecf6bf76e5db7b4bb9c4bce74e4b78674b557ff12b7064635d019f955f192599f84e8efac38b967c011e34590576738b949a6908557b021b139a6f11de379 @@ -0,0 +1,21 @@ +project Vtoposort is + for Languages use ("Ada"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Main use ("vtoposort.adb"); + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "debug"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O0", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + end case; + end Compiler; +end Vtoposort;