diff mbox

[Ada] Implement compilation date and time output and functions

Message ID 20140730104556.GA16235@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet July 30, 2014, 10:45 a.m. UTC
This patch causes the compiler to print the compilation time in
-gnatv or -gnatl mode (suppressible with debug flag -gnatd7).

It also provides new functions in GNAT.Source_Info to obtain
the compilation date and time (in a form compatible with the
use of the C macros __DATE__ and __TIME__.

Finally a new function System.OS_Lib.Current_Time_String is
introduced (and used by the compiler to implement the above).

The following test is compiled with -gnatl:

Compiling: ctime.adb
Source file time stamp: 2014-04-04 14:00:32
Compiled at: 2014-04-04 10:03:24

     1. with Text_IO; use Text_IO;
     2. with GNAT.Source_Info; use GNAT.Source_Info;
     3. procedure Ctime is
     4. begin
     5.    Put_Line (Compilation_Date);
     6.    Put_Line (Compilation_Time);
     7. end;

When run, the output is:

Jul 30 2014
10:03:24

Note: by its very nature, the above test is not suitable as a standard
regression test since of course its output changes each time it is run.

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-07-30  Robert Dewar  <dewar@adacore.com>

	* debug.adb: Document that d7 suppresses compilation time output.
	* errout.adb (Write_Header): Include compilation time in
	header output.
	* exp_intr.adb (Expand_Intrinsic_Call): Add
	Compilation_Date/Compilation_Time (Expand_Source_Info): Expand
	Compilation_Date/Compilation_Time.
	* g-souinf.ads (Compilation_Date): New function
	(Compilation_Time): New function.
	* gnat1drv.adb (Gnat1drv): Set Opt.Compilation_Time.
	* gnat_rm.texi (Compilation_Date): New function
	(Compilation_Time): New function.
	* opt.ads (Compilation_Time): New variable.
	* s-os_lib.ads, s-os_lib.adb (Current_Time_String): New function.
	* sem_intr.adb (Compilation_Date): New function.
	(Compilation_Time): New function.
	* snames.ads-tmpl (Name_Compilation_Date): New entry.
	(Name_Compilation_Time): New entry.
diff mbox

Patch

Index: gnat_rm.texi
===================================================================
--- gnat_rm.texi	(revision 213242)
+++ gnat_rm.texi	(working copy)
@@ -14637,6 +14637,8 @@ 
 
 @menu
 * Intrinsic Operators::
+* Compilation_Date::
+* Compilation_Time::
 * Enclosing_Entity::
 * Exception_Information::
 * Exception_Message::
@@ -14694,12 +14696,34 @@ 
 It is also possible to specify such operators for private types, if the
 full views are appropriate arithmetic types.
 
+@node Compilation_Date
+@section Compilation_Date
+@cindex Compilation_Date
+@noindent
+This intrinsic subprogram is used in the implementation of the
+library package @code{GNAT.Source_Info}.  The only useful use of the
+intrinsic import in this case is the one in this unit, so an
+application program should simply call the function
+@code{GNAT.Source_Info.Compilation_Date} to obtain the date of
+the current compilation (in local time format MMM DD YYYY).
+
+@node Compilation_Time
+@section Compilation_Time
+@cindex Compilation_Time
+@noindent
+This intrinsic subprogram is used in the implementation of the
+library package @code{GNAT.Source_Info}.  The only useful use of the
+intrinsic import in this case is the one in this unit, so an
+application program should simply call the function
+@code{GNAT.Source_Info.Compilation_Time} to obtain the time of
+the current compilation (in local time format HH:MM:SS).
+
 @node Enclosing_Entity
 @section Enclosing_Entity
 @cindex Enclosing_Entity
 @noindent
 This intrinsic subprogram is used in the implementation of the
-library routine @code{GNAT.Source_Info}.  The only useful use of the
+library package @code{GNAT.Source_Info}.  The only useful use of the
 intrinsic import in this case is the one in this unit, so an
 application program should simply call the function
 @code{GNAT.Source_Info.Enclosing_Entity} to obtain the name of
@@ -14710,7 +14734,7 @@ 
 @cindex Exception_Information'
 @noindent
 This intrinsic subprogram is used in the implementation of the
-library routine @code{GNAT.Current_Exception}.  The only useful
+library package @code{GNAT.Current_Exception}.  The only useful
 use of the intrinsic import in this case is the one in this unit,
 so an application program should simply call the function
 @code{GNAT.Current_Exception.Exception_Information} to obtain
@@ -14721,7 +14745,7 @@ 
 @cindex Exception_Message
 @noindent
 This intrinsic subprogram is used in the implementation of the
-library routine @code{GNAT.Current_Exception}.  The only useful
+library package @code{GNAT.Current_Exception}.  The only useful
 use of the intrinsic import in this case is the one in this unit,
 so an application program should simply call the function
 @code{GNAT.Current_Exception.Exception_Message} to obtain
@@ -14732,7 +14756,7 @@ 
 @cindex Exception_Name
 @noindent
 This intrinsic subprogram is used in the implementation of the
-library routine @code{GNAT.Current_Exception}.  The only useful
+library package @code{GNAT.Current_Exception}.  The only useful
 use of the intrinsic import in this case is the one in this unit,
 so an application program should simply call the function
 @code{GNAT.Current_Exception.Exception_Name} to obtain
@@ -14743,7 +14767,7 @@ 
 @cindex File
 @noindent
 This intrinsic subprogram is used in the implementation of the
-library routine @code{GNAT.Source_Info}.  The only useful use of the
+library package @code{GNAT.Source_Info}.  The only useful use of the
 intrinsic import in this case is the one in this unit, so an
 application program should simply call the function
 @code{GNAT.Source_Info.File} to obtain the name of the current
@@ -14754,7 +14778,7 @@ 
 @cindex Line
 @noindent
 This intrinsic subprogram is used in the implementation of the
-library routine @code{GNAT.Source_Info}.  The only useful use of the
+library package @code{GNAT.Source_Info}.  The only useful use of the
 intrinsic import in this case is the one in this unit, so an
 application program should simply call the function
 @code{GNAT.Source_Info.Line} to obtain the number of the current
@@ -20172,7 +20196,9 @@ 
 
 @noindent
 Provides subprograms that give access to source code information known at
-compile time, such as the current file name and line number.
+compile time, such as the current file name and line number. Also provides
+subprograms yielding the date and time of the current compilation (like the
+C macros @code{__DATE__} and @code{__TIME__})
 
 @node GNAT.Spelling_Checker (g-speche.ads)
 @section @code{GNAT.Spelling_Checker} (@file{g-speche.ads})
Index: sem_intr.adb
===================================================================
--- sem_intr.adb	(revision 213201)
+++ sem_intr.adb	(working copy)
@@ -362,8 +362,12 @@ 
 
       --  Source_Location and navigation functions
 
-      elsif Nam_In (Nam, Name_File, Name_Line, Name_Source_Location,
-                         Name_Enclosing_Entity)
+      elsif Nam_In (Nam, Name_File,
+                         Name_Line,
+                         Name_Source_Location,
+                         Name_Enclosing_Entity,
+                         Name_Compilation_Date,
+                         Name_Compilation_Time)
       then
          null;
 
Index: g-souinf.ads
===================================================================
--- g-souinf.ads	(revision 213201)
+++ g-souinf.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 2000-2013, Free Software Foundation, Inc.         --
+--          Copyright (C) 2000-2014, 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- --
@@ -46,15 +46,18 @@ 
    --  Historical note: this used to be Pure, but that was when we marked all
    --  intrinsics as not Pure, even in Pure units, so no problems arose.
 
-   function File return String;
+   function File return String with
+     Import, Convention => Intrinsic;
    --  Return the name of the current file, not including the path information.
    --  The result is considered to be a static string constant.
 
-   function Line return Positive;
+   function Line return Positive with
+     Import, Convention => Intrinsic;
    --  Return the current input line number. The result is considered to be a
    --  static expression.
 
-   function Source_Location return String;
+   function Source_Location return String with
+     Import, Convention => Intrinsic;
    --  Return a string literal of the form "name:line", where name is the
    --  current source file name without path information, and line is the
    --  current line number. In the event that instantiations are involved,
@@ -62,7 +65,8 @@ 
    --  string " instantiated at ". The result is considered to be a static
    --  string constant.
 
-   function Enclosing_Entity return String;
+   function Enclosing_Entity return String with
+     Import, Convention => Intrinsic;
    --  Return the name of the current subprogram, package, task, entry or
    --  protected subprogram. The string is in exactly the form used for the
    --  declaration of the entity (casing and encoding conventions), and is
@@ -75,9 +79,14 @@ 
    --  package itself. This is useful in identifying and logging information
    --  from within generic templates.
 
-private
-   pragma Import (Intrinsic, File);
-   pragma Import (Intrinsic, Line);
-   pragma Import (Intrinsic, Source_Location);
-   pragma Import (Intrinsic, Enclosing_Entity);
+   function Compilation_Date return String with
+     Import, Convention => Intrinsic;
+   --  Returns date of compilation as a static string "mmm dd yyyy". This is
+   --  in local time form, and is exactly compatible with C macro __DATE__.
+
+   function Compilation_Time return String with
+     Import, Convention => Intrinsic;
+   --  Returns GMT time of compilation as a static string "hh:mm:ss". This is
+   --  in local time form, and is exactly compatible with C macro __TIME__.
+
 end GNAT.Source_Info;
Index: debug.adb
===================================================================
--- debug.adb	(revision 213205)
+++ debug.adb	(working copy)
@@ -151,7 +151,7 @@ 
    --  d4   Inhibit automatic krunch of predefined library unit files
    --  d5   Debug output for tree read/write
    --  d6   Default access unconstrained to thin pointers
-   --  d7   Do not output version & file time stamp in -gnatv or -gnatl mode
+   --  d7   Suppress version/source stamp/compilation time for -gnatv/-gnatl
    --  d8   Force opposite endianness in packed stuff
    --  d9   Allow lock free implementation
 
@@ -721,10 +721,11 @@ 
    --       implications of using thin pointers, and also to test that the
    --       compiler functions correctly with this choice.
 
-   --  d7   Normally a -gnatl or -gnatv listing includes the time stamp
-   --       of the source file. This debug flag suppresses this output,
-   --       and also suppresses the message with the version number.
-   --       This is useful in certain regression tests.
+   --  d7   Normally a -gnatl or -gnatv listing includes the time stamp of the
+   --       source file and the time of the compilation. This debug flag can
+   --       be used to suppress this output, and also suppresses the message
+   --       with the version of the compiler. This is useful for regression
+   --       tests which need to have consistent output.
 
    --  d8   This forces the packed stuff to generate code assuming the
    --       opposite endianness from the actual correct value. Useful in
Index: gnat1drv.adb
===================================================================
--- gnat1drv.adb	(revision 213245)
+++ gnat1drv.adb	(working copy)
@@ -82,6 +82,7 @@ 
 with Validsw;  use Validsw;
 
 with System.Assertions;
+with System.OS_Lib;
 
 --------------
 -- Gnat1drv --
@@ -838,6 +839,10 @@ 
       Sem_Eval.Initialize;
       Sem_Type.Init_Interp_Tables;
 
+      --  Capture compilation date and time
+
+      Opt.Compilation_Time := System.OS_Lib.Current_Time_String;
+
       --  Acquire target parameters from system.ads (source of package System)
 
       Targparm_Acquire : declare
Index: errout.adb
===================================================================
--- errout.adb	(revision 213201)
+++ errout.adb	(working copy)
@@ -1761,9 +1761,11 @@ 
             Write_Name (Full_File_Name (Sfile));
 
             if not Debug_Flag_7 then
-               Write_Str (" (source file time stamp: ");
+               Write_Eol;
+               Write_Str ("Source file time stamp: ");
                Write_Time_Stamp (Sfile);
-               Write_Char (')');
+               Write_Eol;
+               Write_Str ("Compiled at: " & Compilation_Time);
             end if;
 
             Write_Eol;
Index: opt.ads
===================================================================
--- opt.ads	(revision 213245)
+++ opt.ads	(working copy)
@@ -366,14 +366,17 @@ 
    --  True if source lines removed by the preprocessor should be commented
    --  in the output file.
 
+   Compilation_Time : String (1 .. 19);
+   --  GNAT
+   --  Compilation date and time in form YYYY-MM-DD HH:MM:SS
+
    Compile_Only : Boolean := False;
    --  GNATMAKE, GNATCLEAN, GPRMAKE, GPBUILD, GPRCLEAN
    --  GNATMAKE, GPRMAKE, GPRMAKE:
-   --    set to True to skip bind and link steps (except when Bind_Only is
-   --    True).
+   --    set True to skip bind and link steps (except when Bind_Only is True)
    --  GNATCLEAN, GPRCLEAN:
-   --    set to True to delete only the files produced by the compiler but not
-   --    the library files or the executable files.
+   --    set True to delete only the files produced by the compiler but not the
+   --    library files or the executable files.
 
    Compiler_Unit : Boolean := False;
    --  GNAT1
@@ -772,11 +775,12 @@ 
    --  use of pragma Implicit_Packing.
 
    Ineffective_Inline_Warnings : Boolean := False;
-   --  GNAT Set True to activate warnings if front-end inlining (-gnatN) is
-   --  not able to actually inline a particular call (or all calls). Can be
-   --  controlled by use of -gnatwp/-gnatwP. Also set True to activate warnings
-   --  if frontend inlining is not able to inline a subprogram expected to be
-   --  inlined in GNATprove mode.
+   --  GNAT
+   --  Set True to activate warnings if front-end inlining (-gnatN) is not able
+   --  to actually inline a particular call (or all calls). Can be controlled
+   --  by use of -gnatwp/-gnatwP. Also set True to activate warnings if
+   --  frontend inlining is not able to inline a subprogram expected to
+   --  be inlined in GNATprove mode.
 
    Init_Or_Norm_Scalars : Boolean := False;
    --  GNAT, GANTBIND
Index: exp_intr.adb
===================================================================
--- exp_intr.adb	(revision 213201)
+++ exp_intr.adb	(working copy)
@@ -109,10 +109,12 @@ 
    procedure Expand_Source_Info (N : Node_Id; Nam : Name_Id);
    --  Rewrite the node by the appropriate string or positive constant.
    --  Nam can be one of the following:
-   --    Name_File             - expand string that is the name of source file
-   --    Name_Line             - expand integer line number
-   --    Name_Source_Location  - expand string of form file:line
-   --    Name_Enclosing_Entity - expand string  with name of enclosing entity
+   --    Name_File                  - expand string name of source file
+   --    Name_Line                  - expand integer line number
+   --    Name_Source_Location       - expand string of form file:line
+   --    Name_Enclosing_Entity      - expand string name of enclosing entity
+   --    Name_Compilation_Date      - expand string with compilation date
+   --    Name_Compilation_Time      - expand string with compilation time
 
    ---------------------------------
    -- Expand_Binary_Operator_Call --
@@ -557,7 +559,9 @@ 
       elsif Nam_In (Nam, Name_File,
                          Name_Line,
                          Name_Source_Location,
-                         Name_Enclosing_Entity)
+                         Name_Enclosing_Entity,
+                         Name_Compilation_Date,
+                         Name_Compilation_Time)
       then
          Expand_Source_Info (N, Nam);
 
@@ -806,6 +810,35 @@ 
 
                Write_Entity_Name (Ent);
 
+            when Name_Compilation_Date =>
+               declare
+                  subtype S13 is String (1 .. 3);
+                  Months : constant array (1 .. 12) of S13 :=
+                    ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+
+                  M1 : constant Character := Opt.Compilation_Time (6);
+                  M2 : constant Character := Opt.Compilation_Time (7);
+
+                  MM : constant Natural range 1 .. 12 :=
+                    (Character'Pos (M1) - Character'Pos ('0')) * 10 +
+                    (Character'Pos (M2) - Character'Pos ('0'));
+
+               begin
+                  --  Reformat ISO date into MMM DD YYYY (__DATE__) format
+
+                  Name_Buffer (1 .. 3)  := Months (MM);
+                  Name_Buffer (4)       := ' ';
+                  Name_Buffer (5 .. 6)  := Opt.Compilation_Time (9 .. 10);
+                  Name_Buffer (7)       := ' ';
+                  Name_Buffer (8 .. 11) := Opt.Compilation_Time (1 .. 4);
+                  Name_Len := 11;
+               end;
+
+            when Name_Compilation_Time =>
+               Name_Buffer (1 .. 8) := Opt.Compilation_Time (12 .. 19);
+               Name_Len := 8;
+
             when others =>
                raise Program_Error;
          end case;
Index: snames.ads-tmpl
===================================================================
--- snames.ads-tmpl	(revision 213201)
+++ snames.ads-tmpl	(working copy)
@@ -1187,6 +1187,8 @@ 
    --  convention name. So is To_Address, which is a GNAT attribute.
 
    First_Intrinsic_Name                  : constant Name_Id := N + $;
+   Name_Compilation_Date                 : constant Name_Id := N + $;
+   Name_Compilation_Time                 : constant Name_Id := N + $;
    Name_Divide                           : constant Name_Id := N + $;
    Name_Enclosing_Entity                 : constant Name_Id := N + $;
    Name_Exception_Information            : constant Name_Id := N + $;
Index: s-os_lib.adb
===================================================================
--- s-os_lib.adb	(revision 213201)
+++ s-os_lib.adb	(working copy)
@@ -888,6 +888,26 @@ 
       end loop File_Loop;
    end Create_Temp_File_Internal;
 
+   -------------------------
+   -- Current_Time_String --
+   -------------------------
+
+   function Current_Time_String return String is
+      subtype S23 is String (1 .. 23);
+      --  Holds current time in ISO 8601 format YYYY-MM-DD HH:MM:SS.SS + NUL
+
+      procedure Current_Time_String (Time : System.Address);
+      pragma Import (C, Current_Time_String, "__gnat_current_time_string");
+      --  Puts current time into Time in above ISO 8601 format
+
+      Result23 : aliased S23;
+      --  Current time in ISO 8601 format
+
+   begin
+      Current_Time_String (Result23'Address);
+      return Result23 (1 .. 19);
+   end Current_Time_String;
+
    -----------------
    -- Delete_File --
    -----------------
Index: s-os_lib.ads
===================================================================
--- s-os_lib.ads	(revision 213201)
+++ s-os_lib.ads	(working copy)
@@ -101,14 +101,14 @@ 
    ---------------------
 
    type OS_Time is private;
-   --  The OS's notion of time is represented by the private type OS_Time.
-   --  This is the type returned by the File_Time_Stamp functions to obtain
-   --  the time stamp of a specified file. Functions and a procedure (modeled
-   --  after the similar subprograms in package Calendar) are provided for
-   --  extracting information from a value of this type. Although these are
-   --  called GM, the intention is not that they provide GMT times in all
-   --  cases but rather the actual (time-zone independent) time stamp of the
-   --  file (of course in Unix systems, this *is* in GMT form).
+   --  The OS's notion of time is represented by the private type OS_Time. This
+   --  is the type returned by the File_Time_Stamp functions to obtain the time
+   --  stamp of a specified file. Functions and a procedure (modeled after the
+   --  similar subprograms in package Calendar) are provided for extracting
+   --  information from a value of this type. Although these are called GM, the
+   --  intention in the case of time stamps is not that they provide GMT times
+   --  in all cases but rather the actual (time-zone independent) time stamp of
+   --  the file (of course in Unix systems, this *is* in GMT form).
 
    Invalid_Time : constant OS_Time;
    --  A special unique value used to flag an invalid time stamp value
@@ -130,7 +130,7 @@ 
    function GM_Hour    (Date : OS_Time) return Hour_Type;
    function GM_Minute  (Date : OS_Time) return Minute_Type;
    function GM_Second  (Date : OS_Time) return Second_Type;
-   --  Functions to extract information from OS_Time value
+   --  Functions to extract information from OS_Time value in GMT form
 
    function "<"  (X, Y : OS_Time) return Boolean;
    function ">"  (X, Y : OS_Time) return Boolean;
@@ -163,6 +163,10 @@ 
    --  component parts and returns an OS_Time. Returns Invalid_Time if the
    --  creation fails.
 
+   function Current_Time_String return String;
+   --  Returns current local time in the form YYYY-MM-DD HH:MM:SS. The result
+   --  has bounds 1 .. 19.
+
    ----------------
    -- File Stuff --
    ----------------