64-bit Sparc Solaris has 64-bit time_t, 64-bit uintmax_t, and file
timestamps with nanosecond resolution.  For hosts like these, GNU make
3.79 ignores the nanoseconds part of file timestamps, as the 64-bit
time_t value occupies all of the uintmax_t objects that GNU make uses
to store time stamps.  This can cause problems on modern machines that
can do more than one make action per second.

A better solution is to split each uintmax_t timestamp into a 30-bit
part for nanoseconds, and a 34-bit part for seconds.  This doesn't
lose any time information until the year 2514, and by then uintmax_t
should be larger than 64 bits, so it isn't a practical problem, but
just to be safe, the patch proposed below checks that all timestamps
are between 1970 and 2514.

This patch assumes all the patches that I've previously submitted for
GNU make 3.79.  As a small bonus, the change in representation shrinks
GNU make a bit on 32-bit Solaris, perhaps because it uses shifting and
masking to manipulate timestamps (instead of multiplication and division).

2000-06-10  Paul Eggert  <[EMAIL PROTECTED]>

        Support nanosecond resolution on hosts with 64-bit time_t and
        uintmax_t (e.g. 64-bit Sparc Solaris), by splitting
        FILE_TIMESTAMP into a 30-bit part for nanoseconds, with the
        rest for seconds, if FILE_TIMESTAMP is at least 64 bits wide.

        * make.h: Always define FILE_TIMESTAMP to be uintmax_t, for
        simplicity.

        * filedef.h (FILE_TIMESTAMP_HI_RES, FILE_TIMESTAMP_LO_BITS,
        UNKNOWN_MTIME, NONEXISTENT_MTIME, OLD_MTIME,
        ORDINARY_MTIME_MIN, ORDINARY_MTIME_MAX): New macros.
        (FILE_TIMESTAMP_STAT_MODTIME): Now takes fname arg.  All uses changed.
        (FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD,
        FILE_TIMESTAMP_FROM_S_AND_NS): Remove.
        (FILE_TIMESTAMP_S, FILE_TIMESTAMP_NS): Use shifts instead of
        multiplication and division.  Offset the timestamps by
        ORDINARY_MTIME_MIN.
        (file_timestamp_cons): New decl.
        (NEW_MTIME): Now just the maximal timestamp value, as we no longer use
        -1 to refer to nonexistent files.

        * file.c (snap_deps, print_file): Use NONEXISTENT_MTIME,
        UNKNOWN_MTIME, and OLD_MTIME instead of magic constants.
        * filedef.h (file_mtime_1): Likewise.
        * main.c (main): Likewise.
        * remake.c (update_file_1, notice_finished_file, check_dep,
        f_mtime, name_mtime, library_search): Likewise.
        * vpath.c (selective_vpath_search): Likewise.

        * remake.c (f_mtime): Do not assume that (time_t) -1 equals
        NONEXISTENT_MTIME.  When futzing with time stamps, adjust by
        multiples of 2**30, not 10**9.  Do not calculate timestamp
        adjustments on DOS unless they are needed.

        * commands.c (delete_target): Do not assume that
        FILE_TIMESTAMP_S yields -1 for a nonexistent file, as that is
        no longer true with the new representation.

        * file.c (file_timestamp_cons): New function, replacing
        FILE_TIMESTAMP_FROM_S_AND_NS.  All uses changed.
        (file_timestamp_now): Use FILE_TIMESTAMP_HI_RES instead of 1 <
        FILE_TIMESTAMPS_PER_S to determine whether we're using hi-res
        timestamps.
        (print_file): Print OLD_MTIME values as "very old" instead of
        as a timestamp.

===================================================================
RCS file: commands.c,v
retrieving revision 3.79.0.1
retrieving revision 3.79.0.2
diff -pu -r3.79.0.1 -r3.79.0.2
--- commands.c  2000/05/18 00:28:13     3.79.0.1
+++ commands.c  2000/06/10 20:23:15     3.79.0.2
@@ -477,7 +477,10 @@ delete_target (file, on_behalf_of)
 #ifndef NO_ARCHIVES
   if (ar_name (file->name))
     {
-      if (ar_member_date (file->name) != FILE_TIMESTAMP_S (file->last_mtime))
+      time_t file_date = (file->last_mtime == NONEXISTENT_MTIME
+                         ? (time_t) -1
+                         : (time_t) FILE_TIMESTAMP_S (file->last_mtime));
+      if (ar_member_date (file->name) != file_date)
        {
          if (on_behalf_of)
            error (NILF, _("*** [%s] Archive member `%s' may be bogus; not deleted"),
@@ -492,7 +495,7 @@ delete_target (file, on_behalf_of)
 
   if (stat (file->name, &st) == 0
       && S_ISREG (st.st_mode)
-      && FILE_TIMESTAMP_STAT_MODTIME (st) != file->last_mtime)
+      && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime)
     {
       if (on_behalf_of)
        error (NILF, _("*** [%s] Deleting file `%s'"), on_behalf_of, file->name);
===================================================================
RCS file: file.c,v
retrieving revision 3.79.0.2
retrieving revision 3.79.0.3
diff -pu -r3.79.0.2 -r3.79.0.3
--- file.c      2000/05/22 16:45:52     3.79.0.2
+++ file.c      2000/06/10 20:23:15     3.79.0.3
@@ -475,8 +475,8 @@ snap_deps ()
        {
          /* Mark this file as phony and nonexistent.  */
          f2->phony = 1;
-         f2->last_mtime = (FILE_TIMESTAMP) -1;
-         f2->mtime_before_update = (FILE_TIMESTAMP) -1;
+         f2->last_mtime = NONEXISTENT_MTIME;
+         f2->mtime_before_update = NONEXISTENT_MTIME;
        }
 
   for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
@@ -564,35 +564,73 @@ set_command_state (file, state)
     d->file->command_state = state;
 }
 
+/* Convert an external file timestamp to internal form.  */
+
+FILE_TIMESTAMP
+file_timestamp_cons (fname, s, ns)
+     char const *fname;
+     time_t s;
+     int ns;
+{
+  int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0);
+  FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS;
+  FILE_TIMESTAMP ts = product + offset;
+
+  if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX)
+        && product <= ts && ts <= ORDINARY_MTIME_MAX))
+    {
+      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
+      ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
+      file_timestamp_sprintf (buf, ts);
+      error (NILF, _("%s: Timestamp out of range; substituting %s"),
+            fname ? fname : _("Current time"), buf);
+    }
+    
+  return ts;
+}
+
 /* Get and print file timestamps.  */
 
 FILE_TIMESTAMP
 file_timestamp_now ()
 {
+  time_t s;
+  int ns;
+
   /* Don't bother with high-resolution clocks if file timestamps have
      only one-second resolution.  The code below should work, but it's
      not worth the hassle of debugging it on hosts where it fails.  */
-  if (1 < FILE_TIMESTAMPS_PER_S)
+  if (FILE_TIMESTAMP_HI_RES)
     {
 #if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
       {
        struct timespec timespec;
        if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
-         return FILE_TIMESTAMP_FROM_S_AND_NS (timespec.tv_sec,
-                                              timespec.tv_nsec);
+         {
+           s = timespec.tv_sec;
+           ns = timespec.tv_nsec;
+           goto got_time;
+         }
       }
 #endif
 #if HAVE_GETTIMEOFDAY
       {
        struct timeval timeval;
        if (gettimeofday (&timeval, 0) == 0)
-         return FILE_TIMESTAMP_FROM_S_AND_NS (timeval.tv_sec,
-                                              timeval.tv_usec * 1000);
+         {
+           s = timeval.tv_sec;
+           ns = timeval.tv_usec * 1000;
+           goto got_time;
+         }
       }
 #endif
     }
 
-  return FILE_TIMESTAMP_FROM_S_AND_NS (time ((time_t *) 0), 0);
+  s = time ((time_t *) 0);
+  ns = 0;
+
+ got_time:
+  return file_timestamp_cons (0, s, ns);
 }
 
 void
@@ -666,10 +704,12 @@ print_file (f)
        printf (" %s", dep_name (d));
       putchar ('\n');
     }
-  if (f->last_mtime == 0)
+  if (f->last_mtime == UNKNOWN_MTIME)
     puts (_("#  Modification time never checked."));
-  else if (f->last_mtime == (FILE_TIMESTAMP) -1)
+  else if (f->last_mtime == NONEXISTENT_MTIME)
     puts (_("#  File does not exist."));
+  else if (f->last_mtime == OLD_MTIME)
+    puts (_("#  File is very old."));
   else
     {
       char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
===================================================================
RCS file: filedef.h,v
retrieving revision 3.79
retrieving revision 3.79.0.2
diff -pu -r3.79 -r3.79.0.2
--- filedef.h   2000/04/03 05:20:10     3.79
+++ filedef.h   2000/06/10 20:35:07     3.79.0.2
@@ -118,28 +118,28 @@ extern void notice_finished_file PARAMS 
 
 
 #ifdef ST_MTIM_NSEC
-# define FILE_TIMESTAMP_STAT_MODTIME(st) \
-    FILE_TIMESTAMP_FROM_S_AND_NS ((st).st_mtime, \
-                                  (st).st_mtim.ST_MTIM_NSEC)
-# define FILE_TIMESTAMPS_PER_S \
-    MIN ((FILE_TIMESTAMP) 1000000000, \
-         (INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) \
-         / INTEGER_TYPE_MAXIMUM (time_t)))
+# define FILE_TIMESTAMP_HI_RES \
+    (2147483647 < INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) >> 31)
+# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \
+    file_timestamp_cons (fname, (st).st_mtime, (st).st_mtim.ST_MTIM_NSEC)
 #else
-# define FILE_TIMESTAMP_STAT_MODTIME(st) ((st).st_mtime)
-# define FILE_TIMESTAMPS_PER_S 1
+# define FILE_TIMESTAMP_HI_RES 0
+# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \
+    file_timestamp_cons (fname, (st).st_mtime, 0)
 #endif
 
-#define FILE_TIMESTAMP_FROM_S_AND_NS(s, ns) \
-    ((s) * FILE_TIMESTAMPS_PER_S \
-     + (ns) * FILE_TIMESTAMPS_PER_S / 1000000000)
-#define FILE_TIMESTAMP_DIV(a, b) ((a)/(b) - ((a)%(b) < 0))
-#define FILE_TIMESTAMP_MOD(a, b) ((a)%(b) + ((a)%(b) < 0) * (b))
-#define FILE_TIMESTAMP_S(ts) FILE_TIMESTAMP_DIV ((ts), FILE_TIMESTAMPS_PER_S)
-#define FILE_TIMESTAMP_NS(ts) \
-    (((FILE_TIMESTAMP_MOD ((ts), FILE_TIMESTAMPS_PER_S) * 1000000000) \
-       + (FILE_TIMESTAMPS_PER_S - 1)) \
-      / FILE_TIMESTAMPS_PER_S)
+/* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution.
+   (Multiply by 2**30 instead of by 10**9 to save time at the cost of
+   slightly decreasing the number of available timestamps.)  With
+   64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04
+   UTC, but by then uintmax_t should be larger than 64 bits.  */
+#define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1)
+#define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0)
+
+#define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \
+                             >> FILE_TIMESTAMP_LO_BITS)
+#define FILE_TIMESTAMP_NS(ts) (((ts) - ORDINARY_MTIME_MIN) \
+                              & ((1 << FILE_TIMESTAMP_LO_BITS) - 1))
 
 /* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN"
    representing a file timestamp.  The upper bound is not necessarily 19,
@@ -159,35 +159,48 @@ extern void notice_finished_file PARAMS 
     * 302 / 1000) \
    + 1 + 1 + 4 + 25)
 
+extern FILE_TIMESTAMP file_timestamp_cons PARAMS ((char const *,
+                                                  time_t, int));
 extern FILE_TIMESTAMP file_timestamp_now PARAMS ((void));
 extern void file_timestamp_sprintf PARAMS ((char *p, FILE_TIMESTAMP ts));
 
 /* Return the mtime of file F (a struct file *), caching it.
-   The value is -1 if the file does not exist.  */
+   The value is NONEXISTENT_MTIME if the file does not exist.  */
 #define file_mtime(f) file_mtime_1 ((f), 1)
 /* Return the mtime of file F (a struct file *), caching it.
    Don't search using vpath for the file--if it doesn't actually exist,
    we don't find it.
-   The value is -1 if the file does not exist.  */
+   The value is NONEXISTENT_MTIME if the file does not exist.  */
 #define file_mtime_no_search(f) file_mtime_1 ((f), 0)
 extern FILE_TIMESTAMP f_mtime PARAMS ((struct file *file, int search));
 #define file_mtime_1(f, v) \
-  ((f)->last_mtime ? (f)->last_mtime : f_mtime ((f), v))
+  ((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime)
+
+/* Special timestamp values.  */
+
+/* The file's timestamp is not yet known.  */
+#define UNKNOWN_MTIME 0
+
+/* The file does not exist.  */
+#define NONEXISTENT_MTIME 1
+
+/* The file does not exist, and we assume that it is older than any
+   actual file.  */
+#define OLD_MTIME 2
+
+/* The smallest and largest ordinary timestamps.  */
+#define ORDINARY_MTIME_MIN (OLD_MTIME + 1)
+#define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \
+                            << FILE_TIMESTAMP_LO_BITS) \
+                           + ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1)
 
 /* Modtime value to use for `infinitely new'.  We used to get the current time
    from the system and use that whenever we wanted `new'.  But that causes
    trouble when the machine running make and the machine holding a file have
    different ideas about what time it is; and can also lose for `force'
    targets, which need to be considered newer than anything that depends on
-   them, even if said dependents' modtimes are in the future.
-
-   If FILE_TIMESTAMP is unsigned, its maximum value is the same as
-   ((FILE_TIMESTAMP) -1), so use one less than that, because -1 is
-   used for non-existing files.  */
-#define NEW_MTIME \
-     (INTEGER_TYPE_SIGNED (FILE_TIMESTAMP) \
-      ? INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) \
-      : (INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) - 1))
+   them, even if said dependents' modtimes are in the future.  */
+#define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP)
 
 #define check_renamed(file) \
   while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here.  */
===================================================================
RCS file: main.c,v
retrieving revision 3.79.0.1
retrieving revision 3.79.0.2
diff -pu -r3.79.0.1 -r3.79.0.2
--- main.c      2000/05/18 00:28:13     3.79.0.1
+++ main.c      2000/06/10 20:35:07     3.79.0.2
@@ -1538,7 +1538,7 @@ int main (int argc, char ** argv)
 
   build_vpath_lists ();
 
-  /* Mark files given with -o flags as very old (00:00:01.00 Jan 1, 1970)
+  /* Mark files given with -o flags as very old
      and as having been updated already, and files given with -W flags as
      brand new (time-stamp as far as possible into the future).  */
 
@@ -1546,7 +1546,7 @@ int main (int argc, char ** argv)
     for (p = old_files->list; *p != 0; ++p)
       {
        f = enter_command_line_file (*p);
-       f->last_mtime = f->mtime_before_update = (FILE_TIMESTAMP) 1;
+       f->last_mtime = f->mtime_before_update = OLD_MTIME;
        f->updated = 1;
        f->update_status = 0;
        f->command_state = cs_finished;
@@ -1679,7 +1679,7 @@ int main (int argc, char ** argv)
                         error (NILF, _("Failed to remake makefile `%s'."),
                                d->file->name);
                         mtime = file_mtime_no_search (d->file);
-                        any_remade |= (mtime != (FILE_TIMESTAMP) -1
+                        any_remade |= (mtime != NONEXISTENT_MTIME
                                        && mtime != makefile_mtimes[i]);
                       }
                   }
===================================================================
RCS file: make.h,v
retrieving revision 3.79.0.1
retrieving revision 3.79.0.2
diff -pu -r3.79.0.1 -r3.79.0.2
--- make.h      2000/05/22 16:45:52     3.79.0.1
+++ make.h      2000/06/10 20:35:07     3.79.0.2
@@ -286,14 +286,10 @@ extern char *alloca ();
 # endif /* HAVE_ALLOCA_H.  */
 #endif /* GCC.  */
 
-#ifdef ST_MTIM_NSEC
-# if HAVE_INTTYPES_H
-#  include <inttypes.h>
-# endif
-# define FILE_TIMESTAMP uintmax_t
-#else
-# define FILE_TIMESTAMP time_t
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
 #endif
+#define FILE_TIMESTAMP uintmax_t
 
 /* ISDIGIT offers the following features:
    - Its arg may be any int or unsigned int; it need not be an unsigned char.
===================================================================
RCS file: remake.c,v
retrieving revision 3.79.0.3
retrieving revision 3.79.0.5
diff -pu -r3.79.0.3 -r3.79.0.5
--- remake.c    2000/05/31 21:25:10     3.79.0.3
+++ remake.c    2000/06/10 21:36:21     3.79.0.5
@@ -390,7 +390,7 @@ update_file_1 (file, depth)
 
   this_mtime = file_mtime (file);
   check_renamed (file);
-  noexist = this_mtime == (FILE_TIMESTAMP) -1;
+  noexist = this_mtime == NONEXISTENT_MTIME;
   if (noexist)
     DBF (DB_BASIC, _("File `%s' does not exist.\n"));
 
@@ -560,7 +560,7 @@ update_file_1 (file, depth)
 #if 1  /* %%% In version 4, remove this code completely to
           implement not remaking deps if their deps are newer
           than their parents.  */
-      if (d_mtime == (FILE_TIMESTAMP) -1 && !d->file->intermediate)
+      if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate)
        /* We must remake if this dep does not
           exist and is not intermediate.  */
        must_make = 1;
@@ -577,7 +577,7 @@ update_file_1 (file, depth)
        {
           const char *fmt = 0;
 
-         if (d_mtime == (FILE_TIMESTAMP) -1)
+         if (d_mtime == NONEXISTENT_MTIME)
             {
               if (ISDB (DB_BASIC))
                 fmt = _("Prerequisite `%s' of target `%s' does not exist.\n");
@@ -726,7 +726,7 @@ notice_finished_file (file)
        }
     }
 
-  if (file->mtime_before_update == 0)
+  if (file->mtime_before_update == UNKNOWN_MTIME)
     file->mtime_before_update = file->last_mtime;
 
   if (ran && !file->phony)
@@ -750,7 +750,7 @@ notice_finished_file (file)
       else if (file->is_target && file->cmds == 0)
        i = 1;
 
-      file->last_mtime = i == 0 ? 0 : NEW_MTIME;
+      file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME;
 
       /* Propagate the change of modification time to all the double-colon
         entries for this file.  */
@@ -811,7 +811,7 @@ check_dep (file, depth, this_mtime, must
       check_renamed (file);
       mtime = file_mtime (file);
       check_renamed (file);
-      if (mtime == (FILE_TIMESTAMP) -1 || mtime > this_mtime)
+      if (mtime == NONEXISTENT_MTIME || mtime > this_mtime)
        *must_make_ptr = 1;
     }
   else
@@ -839,7 +839,7 @@ check_dep (file, depth, this_mtime, must
       check_renamed (file);
       mtime = file_mtime (file);
       check_renamed (file);
-      if (mtime != (FILE_TIMESTAMP) -1 && mtime > this_mtime)
+      if (mtime != NONEXISTENT_MTIME && mtime > this_mtime)
        *must_make_ptr = 1;
          /* Otherwise, update all non-intermediate files we depend on,
             if necessary, and see whether any of them is more
@@ -1039,6 +1039,7 @@ f_mtime (file, search)
       char *arname, *memname;
       struct file *arfile;
       int arname_used = 0;
+      time_t member_date;
 
       /* Find the archive's name.  */
       ar_parse_name (file->name, &arname, &memname);
@@ -1093,18 +1094,21 @@ f_mtime (file, search)
        free (arname);
       free (memname);
 
-      if (mtime == (FILE_TIMESTAMP) -1)
+      if (mtime == NONEXISTENT_MTIME)
        /* The archive doesn't exist, so it's members don't exist either.  */
-       return (FILE_TIMESTAMP) -1;
+       return NONEXISTENT_MTIME;
 
-      mtime = FILE_TIMESTAMP_FROM_S_AND_NS (ar_member_date (file->hname), 0);
+      member_date = ar_member_date (file->hname);
+      mtime = (member_date == (time_t) -1
+              ? NONEXISTENT_MTIME
+              : file_timestamp_cons (file->hname, member_date, 0));
     }
   else
 #endif
     {
       mtime = name_mtime (file->name);
 
-      if (mtime == (FILE_TIMESTAMP) -1 && search && !file->ignore_vpath)
+      if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
        {
          /* If name_mtime failed, search VPATH.  */
          char *name = file->name;
@@ -1113,8 +1117,8 @@ f_mtime (file, search)
              || (name[0] == '-' && name[1] == 'l'
                  && library_search (&name, &mtime)))
            {
-             if (mtime != 0)
-               /* vpath_search and library_search store zero in MTIME
+             if (mtime != UNKNOWN_MTIME)
+               /* vpath_search and library_search store UNKNOWN_MTIME
                   if they didn't need to do a stat call for their work.  */
                file->last_mtime = mtime;
 
@@ -1142,35 +1146,38 @@ f_mtime (file, search)
 
        We only need to do this once, for now. */
 
-    static FILE_TIMESTAMP now;
+    if (!clock_skew_detected
+       && mtime != NONEXISTENT_MTIME
+       && !file->updated)
+      {
+       static FILE_TIMESTAMP now;
 
-    FILE_TIMESTAMP adjusted_mtime = mtime;
+       FILE_TIMESTAMP adjusted_mtime = mtime;
+
+#if defined WINDOWS32 || defined _MSDOS__
+       FILE_TIMESTAMP adjustment;
 #ifdef WINDOWS32
-    /* FAT filesystems round time to the nearest even second!
-       Allow for any file (NTFS or FAT) to perhaps suffer from this
-       brain damage.  */
-    if ((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
-       && FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
-      adjusted_mtime -= FILE_TIMESTAMPS_PER_S;
+       /* FAT filesystems round time to the nearest even second!
+          Allow for any file (NTFS or FAT) to perhaps suffer from this
+          brain damage.  */
+       adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
+                      && FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
+                     ? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS
+                     : 0);
 #else
-#ifdef __MSDOS__
-    /* On DJGPP under Windows 98 and Windows NT, FAT filesystems can
-       set file times up to 3 seconds into the future!  The bug doesn't
-       occur in plain DOS or in Windows 95, but we play it safe.  */
-    adjusted_mtime -= 3 * FILE_TIMESTAMPS_PER_S;
+       /* On DJGPP under Windows 98 and Windows NT, FAT filesystems can
+          set file times up to 3 seconds into the future!  The bug doesn't
+          occur in plain DOS or in Windows 95, but we play it safe.  */
+       adjustment = (FILE_TIMESTAMP) 3 << FILE_TIMESTAMP_LO_BITS;
 #endif
+       if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
+         adjusted_mtime -= adjustment;
 #endif
 
-    if (!clock_skew_detected
-        && mtime != (FILE_TIMESTAMP)-1 && now < adjusted_mtime
-        && !file->updated)
-      {
-       /* This file's time appears to be in the future.
-          Update our concept of the present, and compare again.  */
-
-       now = file_timestamp_now ();
-
-       if (now < adjusted_mtime)
+       /* If the file's time appears to be in the future, udpate our
+          concept of the present and try once more.  */
+       if (now < adjusted_mtime
+           && (now = file_timestamp_now ()) < adjusted_mtime)
           {
            char mtimebuf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
            char nowbuf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
@@ -1195,7 +1202,8 @@ f_mtime (file, search)
         been built by us but was found now, it existed before make
         started.  So, turn off the intermediate bit so make doesn't
         delete it, since it didn't create it.  */
-      if (mtime != (FILE_TIMESTAMP)-1 && file->command_state == cs_not_started
+      if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started
+         && file->command_state == cs_not_started
          && !file->tried_implicit && file->intermediate)
        file->intermediate = 0;
 
@@ -1221,10 +1229,10 @@ name_mtime (name)
       {
        if (errno != ENOENT && errno != ENOTDIR)
          perror_with_name ("stat:", name);
-       return (FILE_TIMESTAMP) -1;
+       return NONEXISTENT_MTIME;
       }
 
-  return FILE_TIMESTAMP_STAT_MODTIME (st);
+  return FILE_TIMESTAMP_STAT_MODTIME (name, st);
 }
 
 
@@ -1310,7 +1318,7 @@ library_search (lib, mtime_ptr)
 
       /* Look first for `libNAME.a' in the current directory.  */
       mtime = name_mtime (libbuf);
-      if (mtime != (FILE_TIMESTAMP) -1)
+      if (mtime != NONEXISTENT_MTIME)
        {
          *lib = xstrdup (libbuf);
          if (mtime_ptr != 0)
@@ -1350,7 +1358,7 @@ library_search (lib, mtime_ptr)
        {
          sprintf (buf, "%s/%s", *dp, libbuf);
          mtime = name_mtime (buf);
-         if (mtime != (FILE_TIMESTAMP) -1)
+         if (mtime != NONEXISTENT_MTIME)
            {
              *lib = xstrdup (buf);
              if (mtime_ptr != 0)
===================================================================
RCS file: vpath.c,v
retrieving revision 3.79.0.1
retrieving revision 3.79.0.2
diff -pu -r3.79.0.1 -r3.79.0.2
--- vpath.c     2000/05/18 00:28:13     3.79.0.1
+++ vpath.c     2000/06/10 20:35:07     3.79.0.2
@@ -525,10 +525,10 @@ selective_vpath_search (path, file, mtim
              if (mtime_ptr != 0)
                /* Store the modtime into *MTIME_PTR for the caller.
                   If we have had no need to stat the file here,
-                  we record a zero modtime to indicate this.  */
+                  we record UNKNOWN_MTIME to indicate this.  */
                *mtime_ptr = (exists_in_cache
-                             ? FILE_TIMESTAMP_STAT_MODTIME (st)
-                             : (FILE_TIMESTAMP) 0);
+                             ? FILE_TIMESTAMP_STAT_MODTIME (name, st)
+                             : UNKNOWN_MTIME);
 
              free (name);
              return 1;

Reply via email to