[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r3809 - in /fsf/trunk/libc: ./ include/ libio/ localedata/ localedata/locales/ nscd/ posix/ sysdeps/posix/ time/ timezone/



Author: eglibc
Date: Mon Oct 15 00:04:07 2007
New Revision: 3809

Log:
Import glibc-mainline for 2007-10-15

Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/include/stdio.h
    fsf/trunk/libc/include/time.h
    fsf/trunk/libc/libio/ftello.c
    fsf/trunk/libc/localedata/ChangeLog
    fsf/trunk/libc/localedata/locales/pl_PL
    fsf/trunk/libc/localedata/show-ucs-data.c
    fsf/trunk/libc/nscd/nscd_getgr_r.c
    fsf/trunk/libc/posix/glob.c
    fsf/trunk/libc/posix/tst-rfc3484-2.c
    fsf/trunk/libc/posix/tst-rfc3484.c
    fsf/trunk/libc/sysdeps/posix/getaddrinfo.c
    fsf/trunk/libc/time/tzfile.c
    fsf/trunk/libc/time/tzset.c
    fsf/trunk/libc/timezone/tst-timezone.c

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Mon Oct 15 00:04:07 2007
@@ -1,4 +1,38 @@
 2007-10-14  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* posix/glob.c: Reimplement link_exists_p to use fstatat64.
+
+	* posix/glob.c: Add some branch prediction throughout.
+
+	* nscd/nscd_getgr_r.c (nscd_getgr_r): Store result of successful
+	read from nscd.
+
+	* sysdeps/posix/getaddrinfo.c (struct sort_result): Add
+	service_order.
+	(rfc3484_sort): Make sure that even if qsort doesn't support
+	stable sorting out sorting here is stable by comparing service_order.
+	(getaddrinfo): Initialize service_order.
+	* posix/tst-rfc3484.c (do_test): Adjust for addition of
+	service_order field to sorting structure.
+	* posix/tst-rfc3484-2.c (do_test): Likewise.
+
+	* include/time.h: Declare __tzset_parse_tz and __tzset_compute.
+	* time/tzset.c (tzset_internal): Break TZ string parsing out into
+	__tzset_parse_tz and updating of daylight, timezone, tzname into
+	update_vars.
+	(__tz_compute): Renamed from tz_compute.  Take additional parameters.
+	(__tz_convert): Updating of tm_isdst, tm_zone, and tm_gmtoff now
+	happens in __tz_compute.
+	* time/tzfile.c (__tzfile_read): Also read TZ string.
+	(find_transition): Fold into __tzfile_compute.
+	(__tzfile_compute): For times beyond the last transition try to
+	use the TZ string.
+	* timezone/tst-timezone.c: Information in daylight and tzname does
+	change for Asia/Tokyo timezone with more concrete information.
+	Remove the test.
+
+	* include/stdio.h: Add libc_hidden_proto for ftello.
+	* libio/ftello.c: Add libc_hidden_def.
 
 	[BZ #1140]
 	* time/tzfile.c (__tzfile_compute): Compute tzname[] values based

Modified: fsf/trunk/libc/include/stdio.h
==============================================================================
--- fsf/trunk/libc/include/stdio.h (original)
+++ fsf/trunk/libc/include/stdio.h Mon Oct 15 00:04:07 2007
@@ -138,6 +138,7 @@
 libc_hidden_proto (fileno)
 libc_hidden_proto (fwrite)
 libc_hidden_proto (fseek)
+libc_hidden_proto (ftello)
 libc_hidden_proto (fflush_unlocked)
 libc_hidden_proto (fread_unlocked)
 libc_hidden_proto (fwrite_unlocked)

Modified: fsf/trunk/libc/include/time.h
==============================================================================
--- fsf/trunk/libc/include/time.h (original)
+++ fsf/trunk/libc/include/time.h Mon Oct 15 00:04:07 2007
@@ -46,6 +46,9 @@
 			      struct tm *tp);
 extern void __tzfile_default (const char *std, const char *dst,
 			      long int stdoff, long int dstoff);
+extern void __tzset_parse_tz (const char *tz);
+extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
+     __THROW internal_function;
 
 /* Subroutine of `mktime'.  Return the `time_t' representation of TP and
    normalize TP, given that a `struct tm *' maps to a `time_t' as performed

Modified: fsf/trunk/libc/libio/ftello.c
==============================================================================
--- fsf/trunk/libc/libio/ftello.c (original)
+++ fsf/trunk/libc/libio/ftello.c Mon Oct 15 00:04:07 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004
+/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004, 2007
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -63,3 +63,4 @@
     }
   return pos;
 }
+libc_hidden_def (ftello)

Modified: fsf/trunk/libc/localedata/ChangeLog
==============================================================================
--- fsf/trunk/libc/localedata/ChangeLog (original)
+++ fsf/trunk/libc/localedata/ChangeLog Mon Oct 15 00:04:07 2007
@@ -1,3 +1,9 @@
+2007-10-14  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	[BZ #4098]
+	* locales/pl_PL: Change abmon, abday, and d_fmt according to
+	results of vote.
+
 2007-10-10  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	* locales/iso14651_t1_common: If DIACRIT_FORWARD is defined, define

Modified: fsf/trunk/libc/localedata/locales/pl_PL
==============================================================================
--- fsf/trunk/libc/localedata/locales/pl_PL (original)
+++ fsf/trunk/libc/localedata/locales/pl_PL Mon Oct 15 00:04:07 2007
@@ -2150,13 +2150,17 @@
 END LC_NUMERIC
 
 LC_TIME
-abday   "<U004E>";/
-        "<U0050><U006E>";/
-        "<U0057><U0074>";/
-        "<U015A><U0072>";/
-        "<U0043><U007A>";/
-        "<U0050><U0074>";/
-        "<U0053><U006F>"
+% The abday, abmon, and d_fmt information has been changed (back) to match
+% the preference expressed in the poll organized to get some concensus.
+% The results were not entirely clear on all easpects but the choices
+% here seem to have the most support.  For more details:
+%
+%   https://bugzilla.redhat.com/show_bug.cgi?id=242296
+%
+abday   "<U006E><U0069><U0065>";"<U0070><U006F><U006E>";/
+        "<U0077><U0074><U006F>";"<U015B><U0072><U006F>";/
+        "<U0063><U007A><U0077>";"<U0070><U0069><U0105>";/
+        "<U0073><U006F><U0062>"
 day     "<U006E><U0069><U0065><U0064><U007A><U0069><U0065><U006C><U0061>";/
         "<U0070><U006F><U006E><U0069><U0065><U0064><U007A><U0069><U0061><U0142><U0065><U006B>";/
         "<U0077><U0074><U006F><U0072><U0065><U006B>";/
@@ -2164,18 +2168,12 @@
         "<U0063><U007A><U0077><U0061><U0072><U0074><U0065><U006B>";/
         "<U0070><U0069><U0105><U0074><U0065><U006B>";/
         "<U0073><U006F><U0062><U006F><U0074><U0061>"
-abmon   "<U0049>";/
-        "<U0049><U0049>";/
-        "<U0049><U0049><U0049>";/
-        "<U0049><U0056>";/
-        "<U0056>";/
-        "<U0056><U0049>";/
-        "<U0056><U0049><U0049>";/
-        "<U0056><U0049><U0049><U0049>";/
-        "<U0049><U0058>";/
-        "<U0058>";/
-        "<U0058><U0049>";/
-        "<U0058><U0049><U0049>"
+abmon   "<U0073><U0074><U0079>";"<U006C><U0075><U0074>";/
+        "<U006D><U0061><U0072>";"<U006B><U0077><U0069>";/
+        "<U006D><U0061><U006A>";"<U0063><U007A><U0065>";/
+        "<U006C><U0069><U0070>";"<U0073><U0069><U0065>";/
+        "<U0077><U0072><U007A>";"<U0070><U0061><U017A>";/
+        "<U006C><U0069><U0073>";"<U0067><U0072><U0075>"
 mon     "<U0073><U0074><U0079><U0063><U007A><U0065><U0144>";/
         "<U006C><U0075><U0074><U0079>";/
         "<U006D><U0061><U0072><U007A><U0065><U0063>";/
@@ -2191,7 +2189,7 @@
 d_t_fmt "<U0025><U0061><U002C><U0020>/
 <U0025><U002D><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U002C><U0020>/
 <U0025><U0054>"
-d_fmt   "<U0025><U002D><U0064><U0020><U0025><U0062><U0020><U0025><U0059>"
+d_fmt   "<U0025><U0064><U002E><U0025><U006D><U002E><U0025><U0059>"
 t_fmt   "<U0025><U0054>"
 am_pm   "";""
 t_fmt_ampm ""

Modified: fsf/trunk/libc/localedata/show-ucs-data.c
==============================================================================
--- fsf/trunk/libc/localedata/show-ucs-data.c (original)
+++ fsf/trunk/libc/localedata/show-ucs-data.c Mon Oct 15 00:04:07 2007
@@ -9,6 +9,13 @@
   int n;
   char *line = NULL;
   size_t len = 0;
+
+  if (argc == 1)
+    {
+      static char *new_argv[] = { NULL, (char *) "/dev/stdin", NULL };
+      argv = new_argv;
+      argc = 2;
+    }
 
   for (n = 1; n < argc; ++n)
     {

Modified: fsf/trunk/libc/nscd/nscd_getgr_r.c
==============================================================================
--- fsf/trunk/libc/nscd/nscd_getgr_r.c (original)
+++ fsf/trunk/libc/nscd/nscd_getgr_r.c Mon Oct 15 00:04:07 2007
@@ -264,40 +264,38 @@
       retval = 0;
 
       /* If there are no group members TOTAL_LEN is zero.  */
-      if (total_len > 0)
-	{
-	  if (gr_name == NULL)
-	    {
-	      size_t n = __readall (sock, resultbuf->gr_mem[0], total_len);
-	      if (__builtin_expect (n != total_len, 0))
-		{
-		  /* The `errno' to some value != ERANGE.  */
-		  __set_errno (ENOENT);
-		  retval = ENOENT;
-		}
-	      else
-		*result = resultbuf;
+      if (gr_name == NULL)
+	{
+	  if (total_len > 0
+	      && __builtin_expect (__readall (sock, resultbuf->gr_mem[0],
+					      total_len) != total_len, 0))
+	    {
+	      /* The `errno' to some value != ERANGE.  */
+	      __set_errno (ENOENT);
+	      retval = ENOENT;
 	    }
 	  else
-	    {
-	      /* Copy the group member names.  */
-	      memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len);
-
-	      /* Try to detect corrupt databases.  */
-	      if (resultbuf->gr_name[gr_name_len - 1] != '\0'
-		  || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
-		  || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
-			if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
-			  break;
-		      cnt < gr_resp.gr_mem_cnt; }))
-		{
-		  /* We cannot use the database.  */
-		  retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
-		  goto out_close;
-		}
-
-	      *result = resultbuf;
-	    }
+	    *result = resultbuf;
+	}
+      else
+	{
+	  /* Copy the group member names.  */
+	  memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len);
+
+	  /* Try to detect corrupt databases.  */
+	  if (resultbuf->gr_name[gr_name_len - 1] != '\0'
+	      || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
+		    if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
+		      break;
+		  cnt < gr_resp.gr_mem_cnt; }))
+	    {
+	      /* We cannot use the database.  */
+	      retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
+	      goto out_close;
+	    }
+
+	  *result = resultbuf;
 	}
     }
   else

Modified: fsf/trunk/libc/posix/glob.c
==============================================================================
--- fsf/trunk/libc/posix/glob.c (original)
+++ fsf/trunk/libc/posix/glob.c Mon Oct 15 00:04:07 2007
@@ -774,7 +774,7 @@
 
       /* Return the directory if we don't check for error or if it exists.  */
       if ((flags & GLOB_NOCHECK)
-	  || (((flags & GLOB_ALTDIRFUNC)
+	  || (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
 	       ? ((*pglob->gl_stat) (dirname, &st) == 0
 		  && S_ISDIR (st.st_mode))
 	       : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
@@ -846,7 +846,7 @@
 	    *(char *) &dirname[--dirlen] = '\0';
 	}
 
-      if ((flags & GLOB_ALTDIRFUNC) != 0)
+      if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) != 0, 0))
 	{
 	  /* Use the alternative access functions also in the recursive
 	     call.  */
@@ -1030,7 +1030,7 @@
       struct_stat64 st64;
 
       for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
-	if (((flags & GLOB_ALTDIRFUNC)
+	if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
 	     ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
 		&& S_ISDIR (st.st_mode))
 	     : (__stat64 (pglob->gl_pathv[i], &st64) == 0
@@ -1222,21 +1222,42 @@
    allocated with alloca to be recycled.  */
 #if !defined _LIBC || !defined GLOB_ONLY_P
 static int
-link_exists_p (const char *dir, size_t dirlen, const char *fname,
-	       glob_t *pglob, int flags)
+__attribute_noinline__
+link_exists2_p (const char *dir, size_t dirlen, const char *fname,
+	       glob_t *pglob
+# ifndef _LIBC
+		, int flags
+# endif
+		)
 {
   size_t fnamelen = strlen (fname);
   char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
   struct stat st;
+# ifndef _LIBC
   struct_stat64 st64;
+# endif
 
   mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
 	   fname, fnamelen + 1);
 
-  return (((flags & GLOB_ALTDIRFUNC)
+# ifdef _LIBC
+  return (*pglob->gl_stat) (fullname, &st) == 0;
+# else
+  return ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
 	   ? (*pglob->gl_stat) (fullname, &st)
 	   : __stat64 (fullname, &st64)) == 0);
+# endif
 }
+# ifdef _LIBC
+#  define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
+  (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)			      \
+   ? link_exists2_p (dirname, dirnamelen, fname, pglob)			      \
+   : ({ struct stat64 st64;						      \
+       __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0; }))
+# else
+#  define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
+  link_exists2_p (dirname, dirnamelen, fname, pglob, flags)
+# endif
 #endif
 
 
@@ -1290,7 +1311,7 @@
       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
 			"/", 1),
 	       pattern, patlen + 1);
-      if (((flags & GLOB_ALTDIRFUNC)
+      if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
 	   ? (*pglob->gl_stat) (fullname, &st)
 	   : __stat64 (fullname, &st64)) == 0)
 	/* We found this file to be existing.  Now tell the rest
@@ -1299,7 +1320,7 @@
     }
   else
     {
-      stream = ((flags & GLOB_ALTDIRFUNC)
+      stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
 		? (*pglob->gl_opendir) (directory)
 		: opendir (directory));
       if (stream == NULL)
@@ -1311,6 +1332,10 @@
 	}
       else
 	{
+#ifdef _LIBC
+	  int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+		     ? -1 : dirfd ((DIR *) stream));
+#endif
 	  int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
 			   | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
 #if defined _AMIGA || defined VMS
@@ -1333,7 +1358,7 @@
 		}
 	      d64buf;
 
-	      if (flags & GLOB_ALTDIRFUNC)
+	      if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
 		{
 		  struct dirent *d32 = (*pglob->gl_readdir) (stream);
 		  if (d32 != NULL)
@@ -1347,7 +1372,7 @@
 	      else
 		d = __readdir64 (stream);
 #else
-	      struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
+	      struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
 				  ? ((struct dirent *)
 				     (*pglob->gl_readdir) (stream))
 				  : __readdir (stream));
@@ -1369,7 +1394,7 @@
 		  /* If the file we found is a symlink we have to
 		     make sure the target file exists.  */
 		  if (!DIRENT_MIGHT_BE_SYMLINK (d)
-		      || link_exists_p (directory, dirlen, name, pglob,
+		      || link_exists_p (dfd, directory, dirlen, name, pglob,
 					flags))
 		    {
 		      if (cur == names->count)
@@ -1485,7 +1510,7 @@
   if (stream != NULL)
     {
       save = errno;
-      if (flags & GLOB_ALTDIRFUNC)
+      if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
 	(*pglob->gl_closedir) (stream);
       else
 	closedir (stream);

Modified: fsf/trunk/libc/posix/tst-rfc3484-2.c
==============================================================================
--- fsf/trunk/libc/posix/tst-rfc3484-2.c (original)
+++ fsf/trunk/libc/posix/tst-rfc3484-2.c Mon Oct 15 00:04:07 2007
@@ -98,12 +98,14 @@
   results[0].got_source_addr = true;
   results[0].source_addr_len = sizeof (so1);
   results[0].source_addr_flags = 0;
+  results[0].service_order = 0;
   memcpy (&results[0].source_addr, &so1, sizeof (so1));
 
   results[1].dest_addr = &ai2;
   results[1].got_source_addr = true;
   results[1].source_addr_len = sizeof (so2);
   results[1].source_addr_flags = 0;
+  results[1].service_order = 1;
   memcpy (&results[1].source_addr, &so2, sizeof (so2));
 
 
@@ -122,12 +124,14 @@
   results[1].got_source_addr = true;
   results[1].source_addr_len = sizeof (so1);
   results[1].source_addr_flags = 0;
+  results[1].service_order = 1;
   memcpy (&results[1].source_addr, &so1, sizeof (so1));
 
   results[0].dest_addr = &ai2;
   results[0].got_source_addr = true;
   results[0].source_addr_len = sizeof (so2);
   results[0].source_addr_flags = 0;
+  results[0].service_order = 0;
   memcpy (&results[0].source_addr, &so2, sizeof (so2));
 
 

Modified: fsf/trunk/libc/posix/tst-rfc3484.c
==============================================================================
--- fsf/trunk/libc/posix/tst-rfc3484.c (original)
+++ fsf/trunk/libc/posix/tst-rfc3484.c Mon Oct 15 00:04:07 2007
@@ -93,6 +93,7 @@
       memcpy(&results[i].source_addr, &so, sizeof (so));
       results[i].source_addr_len = sizeof (so);
       results[i].source_addr_flags = 0;
+      results[i].service_order = i;
     }
 
   qsort (results, naddrs, sizeof (results[0]), rfc3484_sort);

Modified: fsf/trunk/libc/sysdeps/posix/getaddrinfo.c
==============================================================================
--- fsf/trunk/libc/sysdeps/posix/getaddrinfo.c (original)
+++ fsf/trunk/libc/sysdeps/posix/getaddrinfo.c Mon Oct 15 00:04:07 2007
@@ -1002,6 +1002,7 @@
 {
   struct addrinfo *dest_addr;
   struct sockaddr_storage source_addr;
+  size_t service_order;
   uint8_t source_addr_len;
   bool got_source_addr;
   uint8_t source_addr_flags;
@@ -1403,8 +1404,11 @@
     }
 
 
-  /* Rule 10: Otherwise, leave the order unchanged.  */
-  return 0;
+  /* Rule 10: Otherwise, leave the order unchanged.  To ensure this
+     compare with the value indicating the order in which the entries
+     have been received from the services.  NB: no two entries can have
+     the same order so the test will never return zero.  */
+  return a1->service_order < a2->service_order ? -1 : 1;
 }
 
 
@@ -1951,6 +1955,7 @@
 	{
 	  results[i].dest_addr = q;
 	  results[i].got_source_addr = false;
+	  results[i].service_order = i;
 
 	  /* If we just looked up the address for a different
 	     protocol, reuse the result.  */

Modified: fsf/trunk/libc/time/tzfile.c
==============================================================================
--- fsf/trunk/libc/time/tzfile.c (original)
+++ fsf/trunk/libc/time/tzfile.c Mon Oct 15 00:04:07 2007
@@ -62,6 +62,7 @@
 static long int rule_dstoff;
 static size_t num_leaps;
 static struct leap *leaps;
+static char *tzspec;
 
 #include <endian.h>
 #include <byteswap.h>
@@ -113,6 +114,7 @@
   size_t leaps_idx;
   int was_using_tzfile = __use_tzfile;
   int trans_width = 4;
+  size_t tzspec_len;
 
   if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
     abort ();
@@ -241,10 +243,18 @@
 		& ~(__alignof__ (struct leap) - 1));
   leaps_idx = total_size;
   total_size += num_leaps * sizeof (struct leap);
+  tzspec_len = (trans_width == 8
+		? st.st_size - (ftello (f)
+				+ num_transitions * (8 + 1)
+				+ num_types * 6
+				+ chars
+				+ num_leaps * 8
+				+ num_isstd
+				+ num_isgmt) - 1 : 0);
 
   /* Allocate enough memory including the extra block requested by the
      caller.  */
-  transitions = (time_t *) malloc (total_size + extra);
+  transitions = (time_t *) malloc (total_size + tzspec_len + extra);
   if (transitions == NULL)
     goto lose;
 
@@ -253,6 +263,10 @@
   types = (struct ttinfo *) ((char *) transitions + types_idx);
   zone_names = (char *) types + num_types * sizeof (struct ttinfo);
   leaps = (struct leap *) ((char *) transitions + leaps_idx);
+  if (trans_width == 8)
+    tzspec = (char *) leaps + num_leaps * sizeof (struct leap);
+  else
+    tzspec = NULL;
   if (extra > 0)
     *extrap = (char *) &leaps[num_leaps];
 
@@ -356,11 +370,16 @@
   while (i < num_types)
     types[i++].isgmt = 0;
 
-  /* XXX When a version 2 file is available it can contain a POSIX TZ-style
-     formatted string which specifies how times past the last one specified
-     are supposed to be handled.  We might want to handle this at some
-     point.  But it might be overhead since most/all? files have an
-     open-ended last entry.  */
+  /* Read the POSIX TZ-style information if possible.  */
+  if (tzspec != NULL)
+    {
+      /* Skip over the newline first.  */
+      if (getc_unlocked (f) != '\n'
+	  || fread_unlocked (tzspec, 1, tzspec_len - 1, f) != tzspec_len - 1)
+	tzspec = NULL;
+      else
+	tzspec[tzspec_len - 1] = '\0';
+    }
 
   fclose (f);
 
@@ -530,128 +549,6 @@
   compute_tzname_max (stdlen + dstlen);
 }
 
-static struct ttinfo *
-internal_function
-find_transition (time_t timer)
-{
-  size_t i;
-
-  __tzname[0] = NULL;
-  __tzname[1] = NULL;
-
-  if (num_transitions == 0 || timer < transitions[0])
-    {
-      /* TIMER is before any transition (or there are no transitions).
-	 Choose the first non-DST type
-	 (or the first if they're all DST types).  */
-      i = 0;
-      while (i < num_types && types[i].isdst)
-	{
-	  if (__tzname[1] == NULL)
-	    __tzname[1] = __tzstring (&zone_names[types[i].idx]);
-
-	  ++i;
-	}
-
-      if (i == num_types)
-	i = 0;
-      __tzname[0] = __tzstring (&zone_names[types[i].idx]);
-      if (__tzname[1] == NULL)
-	{
-	  size_t j = i;
-	  while (j < num_types)
-	    if (types[j].isdst)
-	      {
-		__tzname[1] = __tzstring (&zone_names[types[j].idx]);
-		break;
-	      }
-	    else
-	      ++j;
-	}
-    }
-  else if (timer >= transitions[num_transitions - 1])
-    {
-      i = num_transitions - 1;
-      goto found;
-    }
-  else
-    {
-      /* Find the first transition after TIMER, and
-	 then pick the type of the transition before it.  */
-      size_t lo = 0;
-      size_t hi = num_transitions - 1;
-      /* Assume that DST is changing twice a year and guess initial
-	 search spot from it.
-	 Half of a gregorian year has on average 365.2425 * 86400 / 2
-	 = 15778476 seconds.  */
-      i = (transitions[num_transitions - 1] - timer) / 15778476;
-      if (i < num_transitions)
-	{
-	  i = num_transitions - 1 - i;
-	  if (timer < transitions[i])
-	    {
-	      if (i < 10 || timer >= transitions[i - 10])
-		{
-		  /* Linear search.  */
-		  while (timer < transitions[i - 1])
-		    --i;
-		  goto found;
-		}
-	      hi = i - 10;
-	    }
-	  else
-	    {
-	      if (i + 10 >= num_transitions || timer < transitions[i + 10])
-		{
-		  /* Linear search.  */
-		  while (timer >= transitions[i])
-		    ++i;
-		  goto found;
-		}
-	      lo = i + 10;
-	    }
-	}
-
-      /* Binary search.  */
-      /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
-      while (lo + 1 < hi)
-	{
-	  i = (lo + hi) / 2;
-	  if (timer < transitions[i])
-	    hi = i;
-	  else
-	    lo = i;
-	}
-      i = hi;
-
-    found:
-      /* assert (timer >= transitions[i - 1] && timer < transitions[i]); */
-      __tzname[types[type_idxs[i - 1]].isdst]
-	= __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
-      size_t j = i;
-      while (j < num_transitions)
-	{
-	  int type = type_idxs[j];
-	  int dst = types[type].isdst;
-	  int idx = types[type].idx;
-
-	  if (__tzname[dst] == NULL)
-	    {
-	      __tzname[dst] = __tzstring (&zone_names[idx]);
-
-	      if (__tzname[1 - dst] != NULL)
-		break;
-	    }
-
-	  ++j;
-	}
-
-      i = type_idxs[i - 1];
-    }
-
-  return &types[i];
-}
-
 void
 __tzfile_compute (time_t timer, int use_localtime,
 		  long int *leap_correct, int *leap_hit,
@@ -661,7 +558,139 @@
 
   if (use_localtime)
     {
-      struct ttinfo *info = find_transition (timer);
+      __tzname[0] = NULL;
+      __tzname[1] = NULL;
+
+      if (num_transitions == 0 || timer < transitions[0])
+	{
+	  /* TIMER is before any transition (or there are no transitions).
+	     Choose the first non-DST type
+	     (or the first if they're all DST types).  */
+	  i = 0;
+	  while (i < num_types && types[i].isdst)
+	    {
+	      if (__tzname[1] == NULL)
+		__tzname[1] = __tzstring (&zone_names[types[i].idx]);
+
+	      ++i;
+	    }
+
+	  if (i == num_types)
+	    i = 0;
+	  __tzname[0] = __tzstring (&zone_names[types[i].idx]);
+	  if (__tzname[1] == NULL)
+	    {
+	      size_t j = i;
+	      while (j < num_types)
+		if (types[j].isdst)
+		  {
+		    __tzname[1] = __tzstring (&zone_names[types[j].idx]);
+		    break;
+		  }
+		else
+		  ++j;
+	    }
+	}
+      else if (timer >= transitions[num_transitions - 1])
+	{
+	  if (tzspec == NULL)
+	    {
+	    use_last:
+	      i = num_transitions - 1;
+	      goto found;
+	    }
+
+	  /* Parse the POSIX TZ-style string.  */
+	  __tzset_parse_tz (tzspec);
+
+	  /* Convert to broken down structure.  If this fails do not
+	     use the string.  */
+	  if (! __offtime (&timer, 0, tp))
+	    goto use_last;
+
+	  /* Use the rules from the TZ string to compute the change.  */
+	  __tz_compute (timer, tp, 1);
+
+	  *leap_correct = 0L;
+	  *leap_hit = 0;
+	  return;
+	}
+      else
+	{
+	  /* Find the first transition after TIMER, and
+	     then pick the type of the transition before it.  */
+	  size_t lo = 0;
+	  size_t hi = num_transitions - 1;
+	  /* Assume that DST is changing twice a year and guess initial
+	     search spot from it.
+	     Half of a gregorian year has on average 365.2425 * 86400 / 2
+	     = 15778476 seconds.  */
+	  i = (transitions[num_transitions - 1] - timer) / 15778476;
+	  if (i < num_transitions)
+	    {
+	      i = num_transitions - 1 - i;
+	      if (timer < transitions[i])
+		{
+		  if (i < 10 || timer >= transitions[i - 10])
+		    {
+		      /* Linear search.  */
+		      while (timer < transitions[i - 1])
+			--i;
+		      goto found;
+		    }
+		  hi = i - 10;
+		}
+	      else
+		{
+		  if (i + 10 >= num_transitions || timer < transitions[i + 10])
+		    {
+		      /* Linear search.  */
+		      while (timer >= transitions[i])
+			++i;
+		      goto found;
+		    }
+		  lo = i + 10;
+		}
+	    }
+
+	  /* Binary search.  */
+	  /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
+	  while (lo + 1 < hi)
+	    {
+	      i = (lo + hi) / 2;
+	      if (timer < transitions[i])
+		hi = i;
+	      else
+		lo = i;
+	    }
+	  i = hi;
+
+	found:
+	  /* assert (timer >= transitions[i - 1] && timer < transitions[i]); */
+	  __tzname[types[type_idxs[i - 1]].isdst]
+	    = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
+	  size_t j = i;
+	  while (j < num_transitions)
+	    {
+	      int type = type_idxs[j];
+	      int dst = types[type].isdst;
+	      int idx = types[type].idx;
+
+	      if (__tzname[dst] == NULL)
+		{
+		  __tzname[dst] = __tzstring (&zone_names[idx]);
+
+		  if (__tzname[1 - dst] != NULL)
+		    break;
+		}
+
+	      ++j;
+	    }
+
+	  i = type_idxs[i - 1];
+	}
+
+      struct ttinfo *info = &types[i];
       __daylight = rule_stdoff != rule_dstoff;
       __timezone = -rule_stdoff;
 

Modified: fsf/trunk/libc/time/tzset.c
==============================================================================
--- fsf/trunk/libc/time/tzset.c (original)
+++ fsf/trunk/libc/time/tzset.c Mon Oct 15 00:04:07 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2002,2003,2004,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -70,7 +70,6 @@
 
 
 static void compute_change (tz_rule *rule, int year) __THROW internal_function;
-static void tz_compute (const struct tm *tm) __THROW internal_function;
 static void tzset_internal (int always, int explicit)
      __THROW internal_function;
 
@@ -92,7 +91,7 @@
 {
   char *p;
   struct tzstring_l *t, *u, *new;
-  size_t len = strlen(s);
+  size_t len = strlen (s);
 
   /* Walk the list and look for a match.  If this string is the same
      as the end of an already-allocated string, it can share space. */
@@ -140,79 +139,33 @@
 
 static char *old_tz;
 
-/* Interpret the TZ envariable.  */
 static void
 internal_function
-tzset_internal (always, explicit)
-     int always;
-     int explicit;
-{
-  static int is_initialized;
-  register const char *tz;
+update_vars (void)
+{
+  __daylight = tz_rules[0].offset != tz_rules[1].offset;
+  __timezone = -tz_rules[0].offset;
+  __tzname[0] = (char *) tz_rules[0].name;
+  __tzname[1] = (char *) tz_rules[1].name;
+
+  /* Keep __tzname_cur_max up to date.  */
+  size_t len0 = strlen (__tzname[0]);
+  size_t len1 = strlen (__tzname[1]);
+  if (len0 > __tzname_cur_max)
+    __tzname_cur_max = len0;
+  if (len1 > __tzname_cur_max)
+    __tzname_cur_max = len1;
+}
+
+/* Parse the POSIX TZ-style string.  */
+void
+__tzset_parse_tz (tz)
+     const char *tz;
+{
   register size_t l;
   char *tzbuf;
   unsigned short int hh, mm, ss;
   unsigned short int whichrule;
-
-  if (is_initialized && !always)
-    return;
-  is_initialized = 1;
-
-  /* Examine the TZ environment variable.  */
-  tz = getenv ("TZ");
-  if (tz == NULL && !explicit)
-    /* Use the site-wide default.  This is a file name which means we
-       would not see changes to the file if we compare only the file
-       name for change.  We want to notice file changes if tzset() has
-       been called explicitly.  Leave TZ as NULL in this case.  */
-    tz = TZDEFAULT;
-  if (tz && *tz == '\0')
-    /* User specified the empty string; use UTC explicitly.  */
-    tz = "Universal";
-
-  /* A leading colon means "implementation defined syntax".
-     We ignore the colon and always use the same algorithm:
-     try a data file, and if none exists parse the 1003.1 syntax.  */
-  if (tz && *tz == ':')
-    ++tz;
-
-  /* Check whether the value changes since the last run.  */
-  if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
-    /* No change, simply return.  */
-    return;
-
-  if (tz == NULL)
-    /* No user specification; use the site-wide default.  */
-    tz = TZDEFAULT;
-
-  tz_rules[0].name = NULL;
-  tz_rules[1].name = NULL;
-
-  /* Save the value of `tz'.  */
-  if (old_tz != NULL)
-    free (old_tz);
-  old_tz = tz ? __strdup (tz) : NULL;
-
-  /* Try to read a data file.  */
-  __tzfile_read (tz, 0, NULL);
-  if (__use_tzfile)
-    return;
-
-  /* No data file found.  Default to UTC if nothing specified.  */
-
-  if (tz == NULL || *tz == '\0'
-      || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
-    {
-      tz_rules[0].name = tz_rules[1].name = "UTC";
-      tz_rules[0].type = tz_rules[1].type = J0;
-      tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0;
-      tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0;
-      tz_rules[0].secs = tz_rules[1].secs = 0;
-      tz_rules[0].offset = tz_rules[1].offset = 0L;
-      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
-      tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
-      goto out;
-    }
 
   /* Clear out old state and reset to unnamed UTC.  */
   memset (tz_rules, 0, sizeof tz_rules);
@@ -413,20 +366,81 @@
     }
 
  out:
-  __daylight = tz_rules[0].offset != tz_rules[1].offset;
-  __timezone = -tz_rules[0].offset;
-  __tzname[0] = (char *) tz_rules[0].name;
-  __tzname[1] = (char *) tz_rules[1].name;
-
-  {
-    /* Keep __tzname_cur_max up to date.  */
-    size_t len0 = strlen (__tzname[0]);
-    size_t len1 = strlen (__tzname[1]);
-    if (len0 > __tzname_cur_max)
-      __tzname_cur_max = len0;
-    if (len1 > __tzname_cur_max)
-      __tzname_cur_max = len1;
-  }
+  update_vars ();
+}
+
+/* Interpret the TZ envariable.  */
+static void
+internal_function
+tzset_internal (always, explicit)
+     int always;
+     int explicit;
+{
+  static int is_initialized;
+  register const char *tz;
+
+  if (is_initialized && !always)
+    return;
+  is_initialized = 1;
+
+  /* Examine the TZ environment variable.  */
+  tz = getenv ("TZ");
+  if (tz == NULL && !explicit)
+    /* Use the site-wide default.  This is a file name which means we
+       would not see changes to the file if we compare only the file
+       name for change.  We want to notice file changes if tzset() has
+       been called explicitly.  Leave TZ as NULL in this case.  */
+    tz = TZDEFAULT;
+  if (tz && *tz == '\0')
+    /* User specified the empty string; use UTC explicitly.  */
+    tz = "Universal";
+
+  /* A leading colon means "implementation defined syntax".
+     We ignore the colon and always use the same algorithm:
+     try a data file, and if none exists parse the 1003.1 syntax.  */
+  if (tz && *tz == ':')
+    ++tz;
+
+  /* Check whether the value changes since the last run.  */
+  if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
+    /* No change, simply return.  */
+    return;
+
+  if (tz == NULL)
+    /* No user specification; use the site-wide default.  */
+    tz = TZDEFAULT;
+
+  tz_rules[0].name = NULL;
+  tz_rules[1].name = NULL;
+
+  /* Save the value of `tz'.  */
+  if (old_tz != NULL)
+    free (old_tz);
+  old_tz = tz ? __strdup (tz) : NULL;
+
+  /* Try to read a data file.  */
+  __tzfile_read (tz, 0, NULL);
+  if (__use_tzfile)
+    return;
+
+  /* No data file found.  Default to UTC if nothing specified.  */
+
+  if (tz == NULL || *tz == '\0'
+      || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
+    {
+      tz_rules[0].name = tz_rules[1].name = "UTC";
+      tz_rules[0].type = tz_rules[1].type = J0;
+      tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0;
+      tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0;
+      tz_rules[0].secs = tz_rules[1].secs = 0;
+      tz_rules[0].offset = tz_rules[1].offset = 0L;
+      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+      tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
+      update_vars ();
+      return;
+    }
+
+  __tzset_parse_tz (tz);
 }
 
 /* Figure out the exact time (as a time_t) in YEAR
@@ -523,13 +537,34 @@
 
 /* Figure out the correct timezone for TM and set `__tzname',
    `__timezone', and `__daylight' accordingly.  */
-static void
+void
 internal_function
-tz_compute (tm)
-     const struct tm *tm;
+__tz_compute (timer, tm, use_localtime)
+     time_t timer;
+     struct tm *tm;
+     int use_localtime;
 {
   compute_change (&tz_rules[0], 1900 + tm->tm_year);
   compute_change (&tz_rules[1], 1900 + tm->tm_year);
+
+  if (use_localtime)
+    {
+      int isdst;
+
+      /* We have to distinguish between northern and southern
+	 hemisphere.  For the latter the daylight saving time
+	 ends in the next year.  */
+      if (__builtin_expect (tz_rules[0].change
+			    > tz_rules[1].change, 0))
+	isdst = (timer < tz_rules[1].change
+		 || timer >= tz_rules[0].change);
+      else
+	isdst = (timer >= tz_rules[0].change
+		 && timer < tz_rules[1].change);
+      tm->tm_isdst = isdst;
+      tm->tm_zone = __tzname[isdst];
+      tm->tm_gmtoff = tz_rules[isdst].offset;
+    }
 }
 
 /* Reinterpret the TZ environment variable and set `tzname'.  */
@@ -583,35 +618,14 @@
       if (! __offtime (timer, 0, tp))
 	tp = NULL;
       else
-	tz_compute (tp);
+	__tz_compute (*timer, tp, use_localtime);
       leap_correction = 0L;
       leap_extra_secs = 0;
     }
 
   if (tp)
     {
-      if (use_localtime)
-	{
-	  if (!__use_tzfile)
-	    {
-	      int isdst;
-
-	      /* We have to distinguish between northern and southern
-		 hemisphere.  For the latter the daylight saving time
-		 ends in the next year.  */
-	      if (__builtin_expect (tz_rules[0].change
-				    > tz_rules[1].change, 0))
-		isdst = (*timer < tz_rules[1].change
-			 || *timer >= tz_rules[0].change);
-	      else
-		isdst = (*timer >= tz_rules[0].change
-			 && *timer < tz_rules[1].change);
-	      tp->tm_isdst = isdst;
-	      tp->tm_zone = __tzname[isdst];
-	      tp->tm_gmtoff = tz_rules[isdst].offset;
-	    }
-	}
-      else
+      if (! use_localtime)
 	{
 	  tp->tm_isdst = 0;
 	  tp->tm_zone = "GMT";

Modified: fsf/trunk/libc/timezone/tst-timezone.c
==============================================================================
--- fsf/trunk/libc/timezone/tst-timezone.c (original)
+++ fsf/trunk/libc/timezone/tst-timezone.c Mon Oct 15 00:04:07 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@xxxxxxx>, 1998.
 
@@ -44,7 +44,6 @@
   { "America/Chicago", 1, 21600, {"CST", "CDT" }},
   { "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }},
   { "America/Los_Angeles", 1, 28800, {"PST", "PDT" }},
-  { "Asia/Tokyo", 1, -32400, {"JST", "JDT" }},
   { "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }},
   { NULL, 0, 0 }
 };