X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fada%2Fa-calend.adb;h=f5dd5013399e43641a370418126216d936808ede;hb=912a710685cb83a63c4b927f56d1a8c002dcbc01;hp=078e05c7d32f027d628486afcac072ea23f56451;hpb=e78e8c8eeb9163e35f31da808a111c5552dcd171;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/ada/a-calend.adb b/gcc/ada/a-calend.adb index 078e05c7d32..f5dd5013399 100644 --- a/gcc/ada/a-calend.adb +++ b/gcc/ada/a-calend.adb @@ -6,8 +6,7 @@ -- -- -- B o d y -- -- -- --- -- --- Copyright (C) 1992-2001 Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2005 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- -- @@ -90,14 +89,21 @@ package body Ada.Calendar is -- TM.all cannot be represented. -- The following constants are used in adjusting Ada dates so that they - -- fit into the range that can be handled by Unix (1970 - 2038). The trick - -- is that the number of days in any four year period in the Ada range of - -- years (1901 - 2099) has a constant number of days. This is because we - -- have the special case of 2000 which, contrary to the normal exception - -- for centuries, is a leap year after all. + -- fit into a 56 year range that can be handled by Unix (1970 included - + -- 2026 excluded). Dates that are not in this 56 year range are shifted + -- by multiples of 56 years to fit in this range. + + -- The trick is that the number of days in any four year period in the Ada + -- range of years (1901 - 2099) has a constant number of days. This is + -- because we have the special case of 2000 which, contrary to the normal + -- exception for centuries, is a leap year after all. 56 has been chosen, + -- because it is not only a multiple of 4, but also a multiple of 7. Thus + -- two dates 56 years apart fall on the same day of the week, and the + -- Daylight Saving Time change dates are usually the same for these two + -- years. Unix_Year_Min : constant := 1970; - Unix_Year_Max : constant := 2038; + Unix_Year_Max : constant := 2026; Ada_Year_Min : constant := 1901; Ada_Year_Max : constant := 2099; @@ -107,9 +113,10 @@ package body Ada.Calendar is Days_In_Month : constant array (Month_Number) of Day_Number := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); - Days_In_4_Years : constant := 365 * 3 + 366; - Seconds_In_4_Years : constant := 86_400 * Days_In_4_Years; - Seconds_In_4_YearsD : constant Duration := Duration (Seconds_In_4_Years); + Days_In_4_Years : constant := 365 * 3 + 366; + Seconds_In_4_Years : constant := 86_400 * Days_In_4_Years; + Seconds_In_56_Years : constant := Seconds_In_4_Years * 14; + Seconds_In_56_YearsD : constant := Duration (Seconds_In_56_Years); --------- -- "+" -- @@ -119,7 +126,6 @@ package body Ada.Calendar is pragma Unsuppress (Overflow_Check); begin return (Left + Time (Right)); - exception when Constraint_Error => raise Time_Error; @@ -129,7 +135,6 @@ package body Ada.Calendar is pragma Unsuppress (Overflow_Check); begin return (Time (Left) + Right); - exception when Constraint_Error => raise Time_Error; @@ -143,7 +148,6 @@ package body Ada.Calendar is pragma Unsuppress (Overflow_Check); begin return Left - Time (Right); - exception when Constraint_Error => raise Time_Error; @@ -153,7 +157,6 @@ package body Ada.Calendar is pragma Unsuppress (Overflow_Check); begin return Duration (Left) - Duration (Right); - exception when Constraint_Error => raise Time_Error; @@ -213,7 +216,6 @@ package body Ada.Calendar is DM : Month_Number; DD : Day_Number; DS : Day_Duration; - begin Split (Date, DY, DM, DD, DS); return DD; @@ -228,7 +230,6 @@ package body Ada.Calendar is DM : Month_Number; DD : Day_Number; DS : Day_Duration; - begin Split (Date, DY, DM, DD, DS); return DM; @@ -243,7 +244,6 @@ package body Ada.Calendar is DM : Month_Number; DD : Day_Number; DS : Day_Duration; - begin Split (Date, DY, DM, DD, DS); return DS; @@ -271,15 +271,6 @@ package body Ada.Calendar is LowD : constant Duration := Duration (Low); HighD : constant Duration := Duration (High); - -- The following declare the maximum duration value that can be - -- successfully converted to a 32-bit integer suitable for passing - -- to the localtime_r function. Note that we cannot assume that the - -- localtime_r function expands to accept 64-bit input on a 64-bit - -- machine, but we can count on a 32-bit range on all machines. - - Max_Time : constant := 2 ** 31 - 1; - Max_TimeD : constant Duration := Duration (Max_Time); - -- Finally the actual variables used in the computation D : Duration; @@ -294,11 +285,11 @@ package body Ada.Calendar is D := Duration (Date); - -- First of all, filter out completely ludicrous values. Remember - -- that we use the full stored range of duration values, which may - -- be significantly larger than the allowed range of Ada times. Note - -- that these checks are wider than required to make absolutely sure - -- that there are no end effects from time zone differences. + -- First of all, filter out completely ludicrous values. Remember that + -- we use the full stored range of duration values, which may be + -- significantly larger than the allowed range of Ada times. Note that + -- these checks are wider than required to make absolutely sure that + -- there are no end effects from time zone differences. if D < LowD or else D > HighD then raise Time_Error; @@ -309,32 +300,32 @@ package body Ada.Calendar is -- required range of years (the guaranteed range available is only -- EPOCH through EPOCH + N seconds). N is in practice 2 ** 31 - 1. - -- If we have a value outside this range, then we first adjust it - -- to be in the required range by adding multiples of four years. - -- For the range we are interested in, the number of days in any - -- consecutive four year period is constant. Then we do the split - -- on the adjusted value, and readjust the years value accordingly. + -- If we have a value outside this range, then we first adjust it to be + -- in the required range by adding multiples of 56 years. For the range + -- we are interested in, the number of days in any consecutive 56 year + -- period is constant. Then we do the split on the adjusted value, and + -- readjust the years value accordingly. Year_Val := 0; while D < 0.0 loop - D := D + Seconds_In_4_YearsD; - Year_Val := Year_Val - 4; + D := D + Seconds_In_56_YearsD; + Year_Val := Year_Val - 56; end loop; - while D > Max_TimeD loop - D := D - Seconds_In_4_YearsD; - Year_Val := Year_Val + 4; + while D >= Seconds_In_56_YearsD loop + D := D - Seconds_In_56_YearsD; + Year_Val := Year_Val + 56; end loop; -- Now we need to take the value D, which is now non-negative, and - -- break it down into seconds (to pass to the localtime_r function) - -- and fractions of seconds (for the adjustment below). + -- break it down into seconds (to pass to the localtime_r function) and + -- fractions of seconds (for the adjustment below). -- Surprisingly there is no easy way to do this in Ada, and certainly - -- no easy way to do it and generate efficient code. Therefore we - -- do it at a low level, knowing that it is really represented as - -- an integer with units of Small + -- no easy way to do it and generate efficient code. Therefore we do it + -- at a low level, knowing that it is really represented as an integer + -- with units of Small declare type D_Int is range 0 .. 2 ** (Duration'Size - 1) - 1; @@ -359,18 +350,18 @@ package body Ada.Calendar is Day := Tm_Val.tm_mday; -- The Seconds value is a little complex. The localtime function - -- returns the integral number of seconds, which is what we want, - -- but we want to retain the fractional part from the original - -- Time value, since this is typically stored more accurately. + -- returns the integral number of seconds, which is what we want, but + -- we want to retain the fractional part from the original Time value, + -- since this is typically stored more accurately. Seconds := Duration (Tm_Val.tm_hour * 3600 + Tm_Val.tm_min * 60 + Tm_Val.tm_sec) + Frac_Sec; - -- Note: the above expression is pretty horrible, one of these days - -- we should stop using time_of and do everything ourselves to avoid - -- these unnecessary divides and multiplies???. + -- Note: the above expression is pretty horrible, one of these days we + -- should stop using time_of and do everything ourselves to avoid these + -- unnecessary divides and multiplies???. -- The Year may still be out of range, since our entry test was -- deliberately crude. Trying to make this entry test accurate is @@ -407,8 +398,8 @@ package body Ada.Calendar is begin -- The following checks are redundant with respect to the constraint -- error checks that should normally be made on parameters, but we - -- decide to raise Constraint_Error in any case if bad values come - -- in (as a result of checks being off in the caller, or for other + -- decide to raise Constraint_Error in any case if bad values come in + -- (as a result of checks being off in the caller, or for other -- erroneous or bounded error cases). if not Year 'Valid @@ -420,7 +411,7 @@ package body Ada.Calendar is end if; -- Check for Day value too large (one might expect mktime to do this - -- check, as well as the basi checks we did with 'Valid, but it seems + -- check, as well as the basic checks we did with 'Valid, but it seems -- that at least on some systems, this built-in check is too weak). if Day > Days_In_Month (Month) @@ -436,24 +427,25 @@ package body Ada.Calendar is TM_Val.tm_mon := Month - 1; -- For the year, we have to adjust it to a year that Unix can handle. - -- We do this in four year steps, since the number of days in four - -- years is constant, so the timezone effect on the conversion from - -- local time to GMT is unaffected. - - while Year_Val <= Unix_Year_Min loop - Year_Val := Year_Val + 4; - Duration_Adjust := Duration_Adjust - Seconds_In_4_YearsD; + -- We do this in 56 year steps, since the number of days in 56 years is + -- constant, so the timezone effect on the conversion from local time + -- to GMT is unaffected; also the DST change dates are usually not + -- modified. + + while Year_Val < Unix_Year_Min loop + Year_Val := Year_Val + 56; + Duration_Adjust := Duration_Adjust - Seconds_In_56_YearsD; end loop; while Year_Val >= Unix_Year_Max loop - Year_Val := Year_Val - 4; - Duration_Adjust := Duration_Adjust + Seconds_In_4_YearsD; + Year_Val := Year_Val - 56; + Duration_Adjust := Duration_Adjust + Seconds_In_56_YearsD; end loop; TM_Val.tm_year := Year_Val - 1900; - -- Since we do not have information on daylight savings, - -- rely on the default information. + -- Since we do not have information on daylight savings, rely on the + -- default information. TM_Val.tm_isdst := -1; Result_Secs := mktime (TM_Val'Unchecked_Access); @@ -461,14 +453,13 @@ package body Ada.Calendar is -- That gives us the basic value in seconds. Two adjustments are -- needed. First we must undo the year adjustment carried out above. -- Second we put back the fraction seconds value since in general the - -- Day_Duration value we received has additional precision which we - -- do not want to lose in the constructed result. + -- Day_Duration value we received has additional precision which we do + -- not want to lose in the constructed result. return Time (Duration (Result_Secs) + Duration_Adjust + (Seconds - Duration (Int_Secs))); - end Time_Of; ---------- @@ -480,7 +471,6 @@ package body Ada.Calendar is DM : Month_Number; DD : Day_Number; DS : Day_Duration; - begin Split (Date, DY, DM, DD, DS); return DY;