summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--elf/Makefile4
-rw-r--r--mach/Machrules1
-rw-r--r--sunrpc/getrpcent.c36
-rw-r--r--sysdeps/generic/strrchr.c12
-rw-r--r--sysdeps/i386/strrchr.S6
-rw-r--r--time/Makefile3
-rw-r--r--time/strptime.c344
-rw-r--r--time/time.h9
9 files changed, 397 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog
index b48c6a50ec..03e3acc092 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+Tue May 14 19:42:04 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* sysdeps/generic/strrchr.c: Deansideclized.
+
+	* elf/Makefile (ldd): Depend on Makefile.
+	Find ld.so in $(slibdir) instead of $(libdir).
+
+	* sysdeps/i386/strrchr.S: Use `testl $3, %esi' instead of `testb $3,
+	%esi'; gas misassembles the latter into `testb $3, %dh'.
+
+	* mach/Machrules (%.udeps rule): Do $(make-target-directory) first.
+
+Tue May 14 16:38:44 1996  David Mosberger-Tang <davidm@AZStarNet.com>
+
+	* sunrpc/getrpcent.c (interpret): Declare args.  Rewrite parsing using
+	strpbrk.
+
+Tue May 14 20:18:38 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* time/Makefile (routines): Add strptime.
+	* time/time.h: Add prototype for strptime.
+	* time/strptime.c: New file.  Implementation according to XPG4.
+
 Tue May 14 14:07:10 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
 	* libc-symbols.h (lint): Macro removed.  The sunrpc code does some
diff --git a/elf/Makefile b/elf/Makefile
index 6569a7e573..6124fa95de 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -95,7 +95,7 @@ $(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so
 $(slibdir)/$(rtld-installed-name): $(objpfx)ld.so; $(do-install-program)
 $(slibdir)/ld-linux.so.1: $(objpfx)ld-linux.so.1; $(do-install-program)
 
-$(objpfx)ldd: ldd.sh.in
-	sed 's%@RTLD@%$(libdir)/$(rtld-installed-name)%g' < $< > $@.new
+$(objpfx)ldd: ldd.sh.in Makefile
+	sed 's%@RTLD@%$(slibdir)/$(rtld-installed-name)%g' < $< > $@.new
 	chmod 555 $@.new
 	mv -f $@.new $@
diff --git a/mach/Machrules b/mach/Machrules
index f7f6d2df63..6f1c1948c5 100644
--- a/mach/Machrules
+++ b/mach/Machrules
@@ -116,6 +116,7 @@ $(patsubst %,$(objpfx)%.ustamp,$(user-interfaces)): $(objpfx)%.ustamp:
 	touch $@
 -include $(patsubst %,$(objpfx)%.udeps,$(user-interfaces))
 $(patsubst %,$(objpfx)%.udeps,$(user-interfaces)): $(objpfx)%.udeps:
+	$(make-target-directory)
 	echo '#include <$*.defs>' | \
 	$(CC) $(CPPFLAGS) -M -x c - | \
 	sed -e 's,- *:,$@ $(@:.udeps=.ustamp) \
diff --git a/sunrpc/getrpcent.c b/sunrpc/getrpcent.c
index 8ef65618b0..0fc7affdf9 100644
--- a/sunrpc/getrpcent.c
+++ b/sunrpc/getrpcent.c
@@ -163,13 +163,15 @@ getrpcent()
 		return(NULL);
 	if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
 		return (NULL);
-    if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
+	if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
 		return (NULL);
 	return interpret(d->line, strlen(d->line));
 }
 
 static struct rpcent *
 interpret(val, len)
+	char * val;
+	size_t len;
 {
 	register struct rpcdata *d = _rpcdata();
 	char *p;
@@ -182,21 +184,13 @@ interpret(val, len)
 	d->line[len] = '\n';
 	if (*p == '#')
 		return (getrpcent());
-	cp = index(p, '#');
+	cp = strpbrk(p, "#\n");
 	if (cp == NULL)
-    {
-		cp = index(p, '\n');
-		if (cp == NULL)
-			return (getrpcent());
-	}
+		return (getrpcent());
 	*cp = '\0';
-	cp = index(p, ' ');
+	cp = strpbrk(p, " \t");
 	if (cp == NULL)
-    {
-		cp = index(p, '\t');
-		if (cp == NULL)
-			return (getrpcent());
-	}
+		return (getrpcent());
 	*cp++ = '\0';
 	/* THIS STUFF IS INTERNET SPECIFIC */
 	d->rpc.r_name = d->line;
@@ -204,15 +198,9 @@ interpret(val, len)
 		cp++;
 	d->rpc.r_number = atoi(cp);
 	q = d->rpc.r_aliases = d->rpc_aliases;
-	cp = index(p, ' ');
+	cp = strpbrk(p, " \t");
 	if (cp != NULL)
 		*cp++ = '\0';
-	else
-    {
-		cp = index(p, '\t');
-		if (cp != NULL)
-			*cp++ = '\0';
-	}
 	while (cp && *cp) {
 		if (*cp == ' ' || *cp == '\t') {
 			cp++;
@@ -220,15 +208,9 @@ interpret(val, len)
 		}
 		if (q < &(d->rpc_aliases[MAXALIASES - 1]))
 			*q++ = cp;
-		cp = index(p, ' ');
+		cp = strpbrk(p, " \t");
 		if (cp != NULL)
 			*cp++ = '\0';
-		else
-	    {
-			cp = index(p, '\t');
-			if (cp != NULL)
-				*cp++ = '\0';
-		}
 	}
 	*q = NULL;
 	return (&d->rpc);
diff --git a/sysdeps/generic/strrchr.c b/sysdeps/generic/strrchr.c
index 29402f086c..663b6aa753 100644
--- a/sysdeps/generic/strrchr.c
+++ b/sysdeps/generic/strrchr.c
@@ -16,25 +16,23 @@ License along with the GNU C Library; see the file COPYING.LIB.  If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <ansidecl.h>
 #include <string.h>
 
-
 /* Find the last ocurrence of C in S.  */
 char *
-DEFUN(strrchr, (s, c), CONST char *s AND int c)
+strrchr (const char *s, int c)
 {
-  register CONST char *found, *p;
+  register const char *found, *p;
 
   c = (unsigned char) c;
 
   /* Since strchr is fast, we use it rather than the obvious loop.  */
-  
+
   if (c == '\0')
-    return strchr(s, '\0');
+    return strchr (s, '\0');
 
   found = NULL;
-  while ((p = strchr(s, c)) != NULL)
+  while ((p = strchr (s, c)) != NULL)
     {
       found = p;
       s = p + 1;
diff --git a/sysdeps/i386/strrchr.S b/sysdeps/i386/strrchr.S
index 468a940d74..26d6a22d6b 100644
--- a/sysdeps/i386/strrchr.S
+++ b/sysdeps/i386/strrchr.S
@@ -58,7 +58,7 @@ ENTRY (strrchr)
 	      implementation (this is because all processor inherant
 	      boundaries are multiples of 4.  */
 
-	testb $3, %esi		/* correctly aligned ? */
+	testl $3, %esi		/* correctly aligned ? */
 	jz L19			/* yes => begin loop */
 	movb (%esi), %dl	/* load byte in question (we need it twice) */
 	cmpb %dl, %cl		/* compare byte */
@@ -68,7 +68,7 @@ L11:	orb %dl, %dl		/* is NUL? */
 	jz L2			/* yes => return NULL */
 	incl %esi		/* increment pointer */
 
-	testb $3, %esi		/* correctly aligned ? */
+	testl $3, %esi		/* correctly aligned ? */
 	jz L19			/* yes => begin loop */
 	movb (%esi), %dl	/* load byte in question (we need it twice) */
 	cmpb %dl, %cl		/* compare byte */
@@ -78,7 +78,7 @@ L12:	orb %dl, %dl		/* is NUL? */
 	jz L2			/* yes => return NULL */
 	incl %esi		/* increment pointer */
 
-	testb $3, %esi		/* correctly aligned ? */
+	testl $3, %esi		/* correctly aligned ? */
 	jz L19			/* yes => begin loop */
 	movb (%esi), %dl	/* load byte in question (we need it twice) */
 	cmpb %dl, %cl		/* compare byte */
diff --git a/time/Makefile b/time/Makefile
index bb8bd20d48..ac422bfc42 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -29,7 +29,8 @@ routines	:= offtime asctime clock ctime difftime gmtime	\
 		   localtime mktime strftime time tzset tzfile	\
 		   gettimeofday settimeofday adjtime		\
 		   getitimer setitimer				\
-		   stime dysize timegm ftime
+		   stime dysize timegm ftime			\
+		   strptime
 
 others	:= ap zdump zic
 tests	:= test_time clocktest
diff --git a/time/strptime.c b/time/strptime.c
new file mode 100644
index 0000000000..cb3d126b9c
--- /dev/null
+++ b/time/strptime.c
@@ -0,0 +1,344 @@
+/* strptime - Convert a string representation of time to a time value.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <ctype.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <string.h>
+#include <time.h>
+
+#include "../locale/localeinfo.h"
+
+
+#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
+#define match_string(cs1, s2)						      \
+  ({ size_t len = strlen (cs1);						      \
+     int result = strncasecmp (cs1, s2, len) == 0;			      \
+     if (result) s2 += len;						      \
+     result; })
+/* We intentionally do not use isdigit() for testing because this will
+   lead to problems with the wide character version.  */
+#define get_number(from, to)						      \
+  do {									      \
+    val = 0;								      \
+    if (*rp < '0' || *rp > '9')						      \
+      return NULL;							      \
+    do {								      \
+      val *= 10;							      \
+      val += *rp++ - '0';						      \
+    } while (val * 10 <= to && *rp >= '0' && *rp <= '9');		      \
+    if (val < from || val > to)						      \
+      return NULL;							      \
+  } while (0)
+#define get_alt_number(from, to)					      \
+  do {									      \
+    const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);		      \
+    val = 0;								      \
+    while (*alts != '\0')						      \
+      {									      \
+	size_t len = strlen (alts);					      \
+	if (strncasecmp (alts, rp, len) == 0)				      \
+	  break;							      \
+	alts = strchr (alts, '\0') + 1;					      \
+	++val;								      \
+      }									      \
+    if (*alts == '\0')							      \
+      return NULL;							      \
+  } while (0)
+#define recursive(new_fmt)						      \
+  do {									      \
+    if (*new_fmt == '\0')						      \
+      return NULL;							      \
+    rp = strptime (rp, new_fmt, tm);					      \
+    if (rp == NULL)							      \
+      return NULL;							      \
+  } while (0)
+  
+
+char *
+strptime (const char *buf, const char *format, struct tm *tm)
+{
+  const char *rp;
+  const char *fmt;
+  int cnt;
+  size_t val;
+  int have_I, is_pm;
+
+  rp = buf;
+  fmt = format;
+  have_I = is_pm = 0;
+
+  while (*fmt != '\0')
+    {
+      /* A white space in the format string matches 0 more or white
+	 space in the input string.  */
+      if (isspace (*fmt))
+	{
+	  while (isspace (*rp))
+	    ++rp;
+	  ++fmt;
+	  continue;
+	}
+
+      /* Any character but `%' must be matched by the same character
+	 in the iput string.  */
+      if (*fmt != '%')
+	{
+	  match_char (*fmt++, *rp++);
+	  continue;
+	}
+
+      ++fmt;
+      switch (*fmt++)
+	{
+	case '%':
+	  /* Match the `%' character itself.  */
+	  match_char ('%', *rp++);
+	  break;
+	case 'a':
+	case 'A':
+	  /* Match day of week.  */
+	  for (cnt = 0; cnt < 7; ++cnt)
+	    {
+	      if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
+		break;
+	      if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
+		break;
+	    }
+	  if (cnt == 7)
+	    /* Does not match a weekday name.  */
+	    return NULL;
+	  tm->tm_wday = cnt;
+	  break;
+	case 'b':
+	case 'B':
+	case 'h':
+	  /* Match month name.  */
+	  for (cnt = 0; cnt < 12; ++cnt)
+	    {
+	      if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
+		break;
+	      if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
+		break;
+	    }
+	  if (cnt == 12)
+	    /* Does not match a month name.  */
+	    return NULL;
+	  tm->tm_mon = cnt;
+	  break;
+	case 'c':
+	  /* Match locale's date and time format.  */
+	  recursive (_NL_CURRENT (LC_TIME, D_T_FMT));
+	  break;
+	case 'C':
+	  /* Match century number.  */
+	  get_number (0, 99);
+	  /* We don't need the number.  */
+	  break;
+	case 'd':
+	case 'e':
+	  /* Match day of month.  */
+	  get_number (1, 31);
+	  tm->tm_mday = val;
+	  break;
+	case 'D':
+	  /* Match standard day format.  */
+	  recursive ("%m/%d/%y");
+	  break;
+	case 'H':
+	  /* Match hour in 24-hour clock.  */
+	  get_number (0, 23);
+	  tm->tm_hour = val;
+	  have_I = 0;
+	  break;
+	case 'I':
+	  /* Match hour in 12-hour clock.  */
+	  get_number (1, 12);
+	  tm->tm_hour = val - 1;
+	  have_I = 1;
+	  break;
+	case 'j':
+	  /* Match day number of year.  */
+	  get_number (1, 366);
+	  tm->tm_yday = val - 1;
+	  break;
+	case 'm':
+	  /* Match number of month.  */
+	  get_number (1, 12);
+	  tm->tm_mon = val - 1;
+	  break;
+	case 'M':
+	  /* Match minute.  */
+	  get_number (0, 59);
+	  tm->tm_min = val;
+	  break;
+	case 'n':
+	case 't':
+	  /* Match any white space.  */
+	  while (isspace (*rp))
+	    ++rp;
+	  break;
+	case 'p':
+	  /* Match locale's equivalent of AM/PM.  */
+	  if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
+	    break;
+	  if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
+	    {
+	      is_pm = 1;
+	      break;
+	    }
+	  return NULL;
+	case 'r':
+	  recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM));
+	  break;
+	case 'R':
+	  recursive ("%H:%M");
+	  break;
+	case 'S':
+	  get_number (0, 61);
+	  tm->tm_sec = val;
+	  break;
+	case 'T':
+	  recursive ("%H:%M:%S");
+	  break;
+	case 'U':
+	case 'V':
+	case 'W':
+	  get_number (0, 53);
+	  /* XXX This cannot determine any field in TM.  */
+	  break;
+	case 'w':
+	  /* Match number of weekday.  */
+	  get_number (0, 6);
+	  tm->tm_wday = val;
+	  break;
+	case 'x':
+	  recursive (_NL_CURRENT (LC_TIME, D_FMT));
+	  break;
+	case 'X':
+	  recursive (_NL_CURRENT (LC_TIME, T_FMT));
+	  break;
+	case 'y':
+	  /* Match year within century.  */
+	  get_number (0, 99);
+	  tm->tm_year = val;
+	  break;
+	case 'Y':
+	  /* Match year including century number.  */
+	  get_number (0, INT_MAX);
+	  tm->tm_year = val - (val >= 2000 ? 2000 : 1900);
+	  break;
+	case 'Z':
+	  /* XXX How to handle this?  */
+	  break;
+	case 'E':
+	  switch (*fmt++)
+	    {
+	    case 'c':
+	      /* Match locale's alternate date and time format.  */
+	      recursive (_NL_CURRENT (LC_TIME, ERA_D_T_FMT));
+	      break;
+	    case 'C':
+	    case 'y':
+	    case 'Y':
+	      /* Match name of base year in locale's alternate
+		 representation.  */
+	      /* XXX This is currently not implemented.  It should
+		 use the value _NL_CURRENT (LC_TIME, ERA) but POSIX
+		 leaves this implementation defined and we haven't
+		 figured out how to do it yet.  */
+	      break;
+	    case 'x':
+	      recursive (_NL_CURRENT (LC_TIME, ERA_D_FMT));
+	      break;
+	    case 'X':
+	      recursive (_NL_CURRENT (LC_TIME, ERA_T_FMT));
+	      break;
+	    default:
+	      return NULL;
+	    }
+	  break;
+	case 'O':
+	  switch (*fmt++)
+	    {
+	    case 'd':
+	    case 'e':
+	      /* Match day of month using alternate numeric symbols.  */
+	      get_alt_number (1, 31);
+	      tm->tm_mday = val;
+	      break;
+	    case 'H':
+	      /* Match hour in 24-hour clock using alternate numeric
+		 symbols.  */
+	      get_alt_number (0, 23);
+	      tm->tm_hour = val;
+	      have_I = 0;
+	      break;
+	    case 'I':
+	      /* Match hour in 12-hour clock using alternate numeric
+		 symbols.  */
+	      get_alt_number (1, 12);
+	      tm->tm_hour = val - 1;
+	      have_I = 1;
+	      break;
+	    case 'm':
+	      /* Match month using alternate numeric symbols.  */
+	      get_alt_number (1, 12);
+	      tm->tm_mon = val - 1;
+	      break;
+	    case 'M':
+	      /* Match minutes using alternate numeric symbols.  */
+	      get_alt_number (0, 59);
+	      tm->tm_min = val;
+	      break;
+	    case 'S':
+	      /* Match seconds using alternate numeric symbols.  */
+	      get_alt_number (0, 61);
+	      tm->tm_sec = val;
+	      break;
+	    case 'U':
+	    case 'V':
+	    case 'W':
+	      get_alt_number (0, 53);
+	      /* XXX This cannot determine any field in TM.  */
+	      break;
+	    case 'w':
+	      /* Match number of weekday using alternate numeric symbols.  */
+	      get_alt_number (0, 6);
+	      tm->tm_wday = val;
+	      break;
+	    case 'y':
+	      /* Match year within century using alternate numeric symbols.  */
+	      get_alt_number (0, 99);
+	      break;
+	    default:
+	      return NULL;
+	    }
+	  break;
+	default:
+	  return NULL;
+	}
+    }
+
+  if (have_I && is_pm)
+    tm->tm_hour += 12;
+  
+  return (char *) rp;
+}
diff --git a/time/time.h b/time/time.h
index fda7f20387..12c3ce43e8 100644
--- a/time/time.h
+++ b/time/time.h
@@ -124,7 +124,14 @@ extern time_t __mktime_internal __P ((struct tm *__tp,
    Write no more than MAXSIZE characters and return the number
    of characters written, or 0 if it would exceed MAXSIZE.  */
 extern size_t strftime __P ((char *__s, size_t __maxsize,
-			 __const char *__format, __const struct tm *__tp));
+			     __const char *__format, __const struct tm *__tp));
+
+#ifdef __USE_MISC
+/* Parse S according to FORMAT and store binary time information in TP.
+   The return value is a pointer to the first unparsed character in S.  */
+extern char *strptime __P ((__const char *__s, __const char *__fmt,
+			    struct tm *__tp));
+#endif
 
 
 /* Return the `struct tm' representation of *TIMER