summaryrefslogtreecommitdiff
path: root/gcc/ada/gprcmd.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gprcmd.adb')
-rw-r--r--gcc/ada/gprcmd.adb423
1 files changed, 423 insertions, 0 deletions
diff --git a/gcc/ada/gprcmd.adb b/gcc/ada/gprcmd.adb
new file mode 100644
index 00000000000..3d5766df703
--- /dev/null
+++ b/gcc/ada/gprcmd.adb
@@ -0,0 +1,423 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- G P R C M D --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2002-2003 Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 2, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING. If not, write --
+-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
+-- MA 02111-1307, USA. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- A utility used by Makefile.generic to handle multi-language builds.
+-- gprcmd provides a set of commands so that the makefiles do not need
+-- to depend on unix utilities not available on all targets.
+
+-- The list of commands recognized by gprcmd are:
+
+-- pwd display current directory
+-- to_lower display next argument in lower case
+-- to_absolute convert pathnames to absolute directories when needed
+-- cat dump contents of a given file
+-- extend handle recursive directories ("/**" notation)
+-- deps post process dependency makefiles
+-- stamp copy file time stamp from file1 to file2
+
+with Ada.Characters.Handling; use Ada.Characters.Handling;
+with Ada.Command_Line; use Ada.Command_Line;
+with Ada.Text_IO; use Ada.Text_IO;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+with GNAT.Regpat; use GNAT.Regpat;
+with Gnatvsn;
+
+procedure Gprcmd is
+
+ -- ??? comments are thin throughout this unit
+
+ Version : constant String :=
+ "GPRCMD " & Gnatvsn.Gnat_Version_String &
+ " Copyright 2002-2003, Ada Core Technologies Inc.";
+
+ procedure Cat (File : String);
+ -- Print the contents of file on standard output.
+ -- If the file cannot be read, exit the process with an error code.
+
+ procedure Check_Args (Condition : Boolean);
+ -- If Condition is false, print the usage, and exit the process.
+
+ procedure Deps (Objext : String; File : String; GCC : Boolean);
+ -- Process $(CC) dependency file. If GCC is True, add a rule so that make
+ -- will not complain when a file is removed/added. If GCC is False, add a
+ -- rule to recompute the dependency file when needed
+
+ procedure Extend (Dir : String);
+ -- If Dir ends with /**, Put all subdirs recursively on standard output,
+ -- otherwise put Dir.
+
+ procedure Usage;
+ -- Display the command line options and exit the process.
+
+ procedure Copy_Time_Stamp (From, To : String);
+ -- Copy file time stamp from file From to file To.
+
+ ---------
+ -- Cat --
+ ---------
+
+ procedure Cat (File : String) is
+ FD : File_Descriptor;
+ Buffer : String_Access;
+ Length : Integer;
+
+ begin
+ FD := Open_Read (File, Fmode => Binary);
+
+ if FD = Invalid_FD then
+ OS_Exit (2);
+ end if;
+
+ Length := Integer (File_Length (FD));
+ Buffer := new String (1 .. Length);
+ Length := Read (FD, Buffer.all'Address, Length);
+ Close (FD);
+ Put (Buffer.all);
+ Free (Buffer);
+ end Cat;
+
+ ----------------
+ -- Check_Args --
+ ----------------
+
+ procedure Check_Args (Condition : Boolean) is
+ begin
+ if not Condition then
+ Usage;
+ end if;
+ end Check_Args;
+
+ ---------------------
+ -- Copy_Time_Stamp --
+ ---------------------
+
+ procedure Copy_Time_Stamp (From, To : String) is
+ function Copy_Attributes
+ (From, To : String;
+ Mode : Integer) return Integer;
+ pragma Import (C, Copy_Attributes, "__gnat_copy_attribs");
+ -- Mode = 0 - copy only time stamps.
+ -- Mode = 1 - copy time stamps and read/write/execute attributes
+
+ FD : File_Descriptor;
+
+ begin
+ if not Is_Regular_File (From) then
+ return;
+ end if;
+
+ FD := Create_File (To, Fmode => Binary);
+
+ if FD = Invalid_FD then
+ OS_Exit (2);
+ end if;
+
+ Close (FD);
+
+ if Copy_Attributes (From & ASCII.NUL, To & ASCII.NUL, 0) /= 0 then
+ OS_Exit (2);
+ end if;
+ end Copy_Time_Stamp;
+
+ ----------
+ -- Deps --
+ ----------
+
+ procedure Deps (Objext : String; File : String; GCC : Boolean) is
+ Colon : constant String := ':' & ASCII.LF;
+ NL : constant String := (1 => ASCII.LF);
+ Base : constant String := ' ' & Base_Name (File) & ": ";
+ FD : File_Descriptor;
+ Buffer : String_Access;
+ Length : Integer;
+ Obj_Regexp : constant Pattern_Matcher :=
+ Compile ("^.*\" & Objext & ": ");
+ Matched : Match_Array (0 .. 0);
+ Start : Natural;
+ First : Natural;
+ Last : Natural;
+
+ begin
+ FD := Open_Read_Write (File, Fmode => Binary);
+
+ if FD = Invalid_FD then
+ return;
+ end if;
+
+ Length := Integer (File_Length (FD));
+ Buffer := new String (1 .. Length);
+ Length := Read (FD, Buffer.all'Address, Length);
+
+ if GCC then
+ Lseek (FD, 0, Seek_End);
+ else
+ Close (FD);
+ FD := Create_File (File, Fmode => Binary);
+ end if;
+
+ Start := Buffer'First;
+
+ while Start <= Buffer'Last loop
+
+ -- Parse Buffer line by line
+
+ while Start < Buffer'Last
+ and then (Buffer (Start) = ASCII.CR
+ or else Buffer (Start) = ASCII.LF)
+ loop
+ Start := Start + 1;
+ end loop;
+
+ Last := Start;
+
+ while Last < Buffer'Last
+ and then Buffer (Last + 1) /= ASCII.CR
+ and then Buffer (Last + 1) /= ASCII.LF
+ loop
+ Last := Last + 1;
+ end loop;
+
+ Match (Obj_Regexp, Buffer (Start .. Last), Matched);
+
+ if GCC then
+ if Matched (0) = No_Match then
+ First := Start;
+ else
+ First := Matched (0).Last + 1;
+ end if;
+
+ Length := Write (FD, Buffer (First)'Address, Last - First + 1);
+
+ if Start = Last or else Buffer (Last) = '\' then
+ Length := Write (FD, NL (1)'Address, NL'Length);
+ else
+ Length := Write (FD, Colon (1)'Address, Colon'Length);
+ end if;
+
+ else
+ if Matched (0) = No_Match then
+ First := Start;
+ else
+ Length :=
+ Write (FD, Buffer (Start)'Address,
+ Matched (0).Last - Start - 1);
+ Length := Write (FD, Base (Base'First)'Address, Base'Length);
+ First := Matched (0).Last + 1;
+ end if;
+
+ Length := Write (FD, Buffer (First)'Address, Last - First + 1);
+ Length := Write (FD, NL (1)'Address, NL'Length);
+ end if;
+
+ Start := Last + 1;
+ end loop;
+
+ Close (FD);
+ Free (Buffer);
+ end Deps;
+
+ ------------
+ -- Extend --
+ ------------
+
+ procedure Extend (Dir : String) is
+
+ procedure Recursive_Extend (D : String);
+ -- Recursively display all subdirectories of D.
+
+ ----------------------
+ -- Recursive_Extend --
+ ----------------------
+
+ procedure Recursive_Extend (D : String) is
+ Iter : Dir_Type;
+ Buffer : String (1 .. 8192);
+ Last : Natural;
+
+ begin
+ Open (Iter, D);
+
+ loop
+ Read (Iter, Buffer, Last);
+
+ exit when Last = 0;
+
+ if Buffer (1 .. Last) /= "."
+ and then Buffer (1 .. Last) /= ".."
+ then
+ declare
+ Abs_Dir : constant String := D & Buffer (1 .. Last);
+
+ begin
+ if Is_Directory (Abs_Dir)
+ and then not Is_Symbolic_Link (Abs_Dir)
+ then
+ Put (' ' & Abs_Dir);
+ Recursive_Extend (Abs_Dir & '/');
+ end if;
+ end;
+ end if;
+ end loop;
+
+ Close (Iter);
+
+ exception
+ when Directory_Error =>
+ null;
+ end Recursive_Extend;
+
+ -- Start of processing for Extend
+
+ begin
+ if Dir'Length < 3
+ or else (Dir (Dir'Last - 2) /= '/'
+ and then Dir (Dir'Last - 2) /= Directory_Separator)
+ or else Dir (Dir'Last - 1 .. Dir'Last) /= "**"
+ then
+ Put (Dir);
+ return;
+ end if;
+
+ declare
+ D : constant String := Dir (Dir'First .. Dir'Last - 2);
+ begin
+ Put (D);
+ Recursive_Extend (D);
+ end;
+ end Extend;
+
+ -----------
+ -- Usage --
+ -----------
+
+ procedure Usage is
+ begin
+ Put_Line (Standard_Error, "usage: gprcmd cmd [arguments]");
+ Put_Line (Standard_Error, "where cmd is one of the following commands:");
+ Put_Line (Standard_Error, " pwd " &
+ "display current directory");
+ Put_Line (Standard_Error, " to_lower " &
+ "display next argument in lower case");
+ Put_Line (Standard_Error, " to_absolute " &
+ "convert pathnames to absolute " &
+ "directories when needed");
+ Put_Line (Standard_Error, " cat " &
+ "dump contents of a given file");
+ Put_Line (Standard_Error, " extend " &
+ "handle recursive directories " &
+ "(""/**"" notation)");
+ Put_Line (Standard_Error, " deps " &
+ "post process dependency makefiles");
+ Put_Line (Standard_Error, " stamp " &
+ "copy file time stamp from file1 to file2");
+ OS_Exit (1);
+ end Usage;
+
+-- Start of processing for Gprcmd
+
+begin
+ Check_Args (Argument_Count > 0);
+
+ declare
+ Cmd : constant String := Argument (1);
+
+ begin
+ if Cmd = "-v" then
+ Put_Line (Standard_Error, Version);
+ Usage;
+
+ elsif Cmd = "pwd" then
+ Put (Format_Pathname (Get_Current_Dir, UNIX));
+
+ elsif Cmd = "cat" then
+ Check_Args (Argument_Count = 2);
+ Cat (Argument (2));
+
+ elsif Cmd = "to_lower" then
+ Check_Args (Argument_Count >= 2);
+
+ for J in 2 .. Argument_Count loop
+ Put (To_Lower (Argument (J)));
+
+ if J < Argument_Count then
+ Put (' ');
+ end if;
+ end loop;
+
+ elsif Cmd = "to_absolute" then
+ Check_Args (Argument_Count > 2);
+
+ declare
+ Dir : constant String := Argument (2);
+
+ begin
+ for J in 3 .. Argument_Count loop
+ if Is_Absolute_Path (Argument (J)) then
+ Put (Format_Pathname (Argument (J), UNIX));
+ else
+ Put (Format_Pathname (Normalize_Pathname (Argument (J), Dir),
+ UNIX));
+ end if;
+
+ if J < Argument_Count then
+ Put (' ');
+ end if;
+ end loop;
+ end;
+
+ elsif Cmd = "extend" then
+ Check_Args (Argument_Count >= 2);
+
+ declare
+ Dir : constant String := Argument (2);
+
+ begin
+ for J in 3 .. Argument_Count loop
+ if Is_Absolute_Path (Argument (J)) then
+ Extend (Format_Pathname (Argument (J), UNIX));
+ else
+ Extend
+ (Format_Pathname (Normalize_Pathname (Argument (J), Dir),
+ UNIX));
+ end if;
+
+ if J < Argument_Count then
+ Put (' ');
+ end if;
+ end loop;
+ end;
+
+ elsif Cmd = "deps" then
+ Check_Args (Argument_Count in 3 .. 4);
+ Deps (Argument (2), Argument (3), GCC => Argument_Count = 4);
+
+ elsif Cmd = "stamp" then
+ Check_Args (Argument_Count = 3);
+ Copy_Time_Stamp (Argument (2), Argument (3));
+ end if;
+ end;
+end Gprcmd;