Module Name:    src
Committed By:   ginsbach
Date:           Thu May 14 02:37:37 UTC 2009

Modified Files:
        src/distrib/sets/lists/base: mi
        src/distrib/sets/lists/comp: mi
        src/etc/mtree: NetBSD.dist
        src/include: time.h
        src/lib/libc/time: Makefile.inc
        src/share/examples: Makefile
Added Files:
        src/lib/libc/time: getdate.3 getdate.c
        src/share/examples/getdate: Makefile datemsk.template posixmsk.example3
            posixmsk.example4

Log Message:
Add the getdate(3) function and getdate_err value, conforming to IEEE
Std 1003.1 (``POSIX.1'') and the Open Group Base Specifications X/Open
System Interfaces extension (``XSI'').


To generate a diff of this commit:
cvs rdiff -u -r1.808 -r1.809 src/distrib/sets/lists/base/mi
cvs rdiff -u -r1.1259 -r1.1260 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.399 -r1.400 src/etc/mtree/NetBSD.dist
cvs rdiff -u -r1.38 -r1.39 src/include/time.h
cvs rdiff -u -r1.11 -r1.12 src/lib/libc/time/Makefile.inc
cvs rdiff -u -r0 -r1.1 src/lib/libc/time/getdate.3 \
    src/lib/libc/time/getdate.c
cvs rdiff -u -r1.17 -r1.18 src/share/examples/Makefile
cvs rdiff -u -r0 -r1.1 src/share/examples/getdate/Makefile \
    src/share/examples/getdate/datemsk.template \
    src/share/examples/getdate/posixmsk.example3 \
    src/share/examples/getdate/posixmsk.example4

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/base/mi
diff -u src/distrib/sets/lists/base/mi:1.808 src/distrib/sets/lists/base/mi:1.809
--- src/distrib/sets/lists/base/mi:1.808	Fri May  8 23:28:46 2009
+++ src/distrib/sets/lists/base/mi	Thu May 14 02:37:35 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.808 2009/05/08 23:28:46 christos Exp $
+# $NetBSD: mi,v 1.809 2009/05/14 02:37:35 ginsbach Exp $
 #
 # Note:	Don't delete entries from here - mark them as "obsolete" instead,
 #	unless otherwise stated below.
@@ -1787,6 +1787,7 @@
 ./usr/share/examples/emul/ultrix/etc		base-sys-examples
 ./usr/share/examples/fstab			base-fstab-examples
 ./usr/share/examples/ftpd			base-netutil-examples
+./usr/share/examples/getdate			base-sys-examples
 ./usr/share/examples/hostapd			base-netutil-examples
 ./usr/share/examples/ipf			base-netutil-examples
 ./usr/share/examples/isdn			base-isdn-examples

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.1259 src/distrib/sets/lists/comp/mi:1.1260
--- src/distrib/sets/lists/comp/mi:1.1259	Wed May 13 02:50:31 2009
+++ src/distrib/sets/lists/comp/mi	Thu May 14 02:37:36 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.1259 2009/05/13 02:50:31 pgoyette Exp $
+#	$NetBSD: mi,v 1.1260 2009/05/14 02:37:36 ginsbach Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5535,7 +5535,8 @@
 ./usr/share/man/cat3/getcurx.0			comp-c-catman		.cat
 ./usr/share/man/cat3/getcury.0			comp-c-catman		.cat
 ./usr/share/man/cat3/getcwd.0			comp-c-catman		.cat
-./usr/share/man/cat3/getdate.0			comp-obsolete		obsolete
+./usr/share/man/cat3/getdate.0			comp-c-catman		.cat
+./usr/share/man/cat3/getdate_err.0		comp-c-catman		.cat
 ./usr/share/man/cat3/getdevmajor.0		comp-c-catman		.cat
 ./usr/share/man/cat3/getdirentries.0		comp-c-catman		.cat
 ./usr/share/man/cat3/getdiskbyname.0		comp-c-catman		.cat
@@ -16340,7 +16341,8 @@
 ./usr/share/man/man3/getcurx.3			comp-c-man		.man
 ./usr/share/man/man3/getcury.3			comp-c-man		.man
 ./usr/share/man/man3/getcwd.3			comp-c-man		.man
-./usr/share/man/man3/getdate.3			comp-obsolete		obsolete
+./usr/share/man/man3/getdate.3			comp-c-man		.man
+./usr/share/man/man3/getdate_err.3		comp-c-man		.man
 ./usr/share/man/man3/getdevmajor.3		comp-c-man		.man
 ./usr/share/man/man3/getdirentries.3		comp-c-man		.man
 ./usr/share/man/man3/getdiskbyname.3		comp-c-man		.man

Index: src/etc/mtree/NetBSD.dist
diff -u src/etc/mtree/NetBSD.dist:1.399 src/etc/mtree/NetBSD.dist:1.400
--- src/etc/mtree/NetBSD.dist:1.399	Sat May  2 16:02:19 2009
+++ src/etc/mtree/NetBSD.dist	Thu May 14 02:37:35 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: NetBSD.dist,v 1.399 2009/05/02 16:02:19 pooka Exp $
+#	$NetBSD: NetBSD.dist,v 1.400 2009/05/14 02:37:35 ginsbach Exp $
 #	@(#)4.4BSD.dist	8.1 (Berkeley) 6/13/93
 
 # Do not customize this file as it may be overwritten on upgrades.
@@ -677,6 +677,7 @@
 ./usr/share/examples/disktab
 ./usr/share/examples/fstab
 ./usr/share/examples/ftpd
+./usr/share/examples/getdate
 ./usr/share/examples/hostapd
 ./usr/share/examples/ipf
 ./usr/share/examples/isdn

Index: src/include/time.h
diff -u src/include/time.h:1.38 src/include/time.h:1.39
--- src/include/time.h:1.38	Sun Jan 11 03:04:12 2009
+++ src/include/time.h	Thu May 14 02:37:36 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: time.h,v 1.38 2009/01/11 03:04:12 christos Exp $	*/
+/*	$NetBSD: time.h,v 1.39 2009/05/14 02:37:36 ginsbach Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -131,6 +131,12 @@
     struct tm * __restrict);
 #endif
 
+#if (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
+    defined(_NETBSD_SOURCE)
+struct tm *getdate(const char *);
+extern int getdate_err;
+#endif
+
 #if (_POSIX_C_SOURCE - 0) >= 199309L || (_XOPEN_SOURCE - 0) >= 500 || \
     defined(_NETBSD_SOURCE)
 #include <sys/time.h>		/* XXX for struct timespec */

Index: src/lib/libc/time/Makefile.inc
diff -u src/lib/libc/time/Makefile.inc:1.11 src/lib/libc/time/Makefile.inc:1.12
--- src/lib/libc/time/Makefile.inc:1.11	Sat Jul 16 19:36:25 2005
+++ src/lib/libc/time/Makefile.inc	Thu May 14 02:37:36 2009
@@ -1,10 +1,11 @@
-#	$NetBSD: Makefile.inc,v 1.11 2005/07/16 19:36:25 christos Exp $
+#	$NetBSD: Makefile.inc,v 1.12 2009/05/14 02:37:36 ginsbach Exp $
 
 .PATH: ${.CURDIR}/time
 
 SRCS+=	_daylight.c							\
-	asctime.c difftime.c localtime.c strftime.c strptime.c
-MAN+=	ctime.3 offtime.3 time2posix.3 tzfile.5 tzset.3 strftime.3 strptime.3
+	asctime.c difftime.c localtime.c getdate.c strftime.c strptime.c
+MAN+=	ctime.3 getdate.3 offtime.3 strftime.3 strptime.3		\
+	time2posix.3 tzfile.5 tzset.3
 CPPFLAGS+=-DALL_STATE -DUSG_COMPAT
 
 MLINKS+=ctime.3 ctime_r.3	\

Index: src/share/examples/Makefile
diff -u src/share/examples/Makefile:1.17 src/share/examples/Makefile:1.18
--- src/share/examples/Makefile:1.17	Mon Jan 19 07:08:28 2009
+++ src/share/examples/Makefile	Thu May 14 02:37:36 2009
@@ -1,6 +1,6 @@
-#	$NetBSD: Makefile,v 1.17 2009/01/19 07:08:28 jmmv Exp $
+#	$NetBSD: Makefile,v 1.18 2009/05/14 02:37:36 ginsbach Exp $
 
-SUBDIR= amd apm disktab emul fstab ftpd hostapd isdn pppd racoon	\
+SUBDIR= amd apm disktab emul fstab ftpd getdate hostapd isdn pppd racoon \
 	supfiles syslogd wsmoused
 
 .include <bsd.subdir.mk>

Added files:

Index: src/lib/libc/time/getdate.3
diff -u /dev/null src/lib/libc/time/getdate.3:1.1
--- /dev/null	Thu May 14 02:37:37 2009
+++ src/lib/libc/time/getdate.3	Thu May 14 02:37:36 2009
@@ -0,0 +1,234 @@
+.\"	$NetBSD: getdate.3,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+.\"
+.\" Copyright (c) 2009, The NetBSD Foundation.
+.\" All Rights Reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Brian Ginsbach.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd May 8, 2009
+.Dt GETDATE 3
+.Os
+.Sh NAME
+.Nm getdate ,
+.Nm getdate_err
+.Nd convert user format date and time
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft "struct tm *"
+.Fo "getdate"
+.Fa "const char *str"
+.Fc
+.Vt extern int getdate_err ;
+.Sh DESCRIPTION
+The
+.Fn getdate
+function converts a date or time character string pointed to by
+.Fa str
+into a static
+.Va tm
+structure.
+.Pp
+The input string is parsed and interpreted using templates.
+A text file containing templates is specified by the
+environment variable
+.Ev DATEMSK .
+This should contain the full path to the template file.
+Lines in the template file represent acceptable date and/or time
+conversion specifications.
+These specifications are similar to those given for
+.Xr strptime 3 .
+The first line in the template file that matches the input string
+is used to interpret and convert to internal time format.
+.Ss Internal Format Conversion
+The following rules apply to converting the input into the internal format.
+.Bl -bullet -offset indent
+.It
+If only the weekday is given, the conversion assumes today when the
+weekday matches today or the first future matching weekday.
+.It
+If only the month and no year is given, the conversion assumes the
+current month when the month matches or the first future matching month.
+The first day of the month is assumed if no day is given.
+.It
+If only the year is given, the values of the
+.Fa tm_mon ,
+.Fa tm_mday ,
+.Fa tm_wday ,
+.Fa tm_yday ,
+and
+.Fa tm_isdst
+members of the returned
+.Va "struct tm"
+are unspecified.
+.It
+If the century is given, but the year within the century is not given,
+the conversion assumes the current year.
+.It
+If no hour, minute, and second are given, the conversion assumes
+the current hour, minute, and second.
+.It
+If no date is given, the conversion assumes today when the given hour
+is greater than the current hour and tomorrow when the given hour is less.
+.It
+If
+.Cm \&%Z
+is being scanned, then the broken-down time is based on the the
+current time of the matched timezone and not the current runtime
+environment timezone.
+.El
+.Sh RETURN VALUES
+If successful, the
+.Fn getdate
+function returns a pointer to a static
+.Va tm
+structure containing the broken-down time.
+Otherwise, a null pointer is returned and
+.Va getdate_err
+is set to indicate the error.
+.Pp
+The variable
+.Va getdate_err
+can have the following values:
+.Bl -tag -width NNN
+.It 1
+.Ev DATEMSK
+environment variable is null or undefined.
+.It 2
+Cannot open the template file for reading.
+.It 3
+Get file status failed for template file.
+.It 4
+Template file is not a regular file.
+.It 5
+Encountered an error while reading the template file.
+.It 6
+Cannot allocate memory.
+.It 7
+Input string does not match any line in the template file.
+.It 8
+Input string is invalid
+.Pq for example February 31
+or could not be represented in a
+.Va time_t .
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width DATEMSK
+.It Ev DATEMSK
+The full path to the text file containing the templates
+for acceptable date and/or time conversions.
+.El
+.Sh FILES
+.Bl -tag -width DATEMSK
+.It  Pa /usr/share/examples/getdate/datemsk.template
+An example template file that could be specified via the
+.Ev DATEMSK
+environment variable.
+.El
+.Sh EXAMPLES
+The following example shows the possible contents of a template file:
+.Pp
+.Bd -literal -offset indent -compact
+%m
+%A %B %d, %Y, %H:%M:%S
+%A
+%B
+%m/%d/%y %I %p
+%d,%m,%Y %H:%M
+at %A the %dst of %B in %Y
+run job at %I %p, %B %dnd
+%A den %d. %B %Y %H.%M Uhr
+.Ed
+.Pp
+The following are examples of valid input for the above template:
+.Pp
+.Bd -literal -offset indent -compact
+10/1/87 4 PM
+Friday
+Firday September 18, 1987, 10:30:30
+24,9,1986 10:30
+at monday the 1st of december in 1986
+run job at 3 PM, december 2nd
+.Ed
+.Pp
+The following examples show how local data and time specification can be
+defined in the template.
+.Pp
+.Bl -column -offset indent ".Sy Input String" ".Sy Line in Template"
+.It Sy "Input String" Ta Sy "Line in Template"
+.It Li 11/27/86 Ta Li \&%m/\&%d/\&%y
+.It Li 27.11.86 Ta Li \&%d.\&%m/\&%y
+.It Li 86-11-27 Ta Li \&%y-\&%m-\&%d
+.It Li "Friday 12:00:00" Ta "\&%A \&%H:\&%M:\&%S"
+.El
+.Pp
+The following examples illustrate the Internal Format Conversion rules
+given that the current date is
+.Li "Mon Sep 22 12:19:47 EDT 1986"
+and the
+.Ev LC_TIME
+environment variable is set to the default C locale.
+.Pp
+.Bl -column -offset indent ".Sy Input String" ".Sy Line in Template" ".Sy Date"
+.It Sy Input String Ta Sy Line in Template Ta Sy Date
+.It Li Mon Ta Li \&%a Ta Li "Mon Sep 22 12:19:47 EDT 1986"
+.It Li Sun Ta Li \&%a Ta Li "Sun Sep 28 12:19:47 EDT 1986"
+.It Li Fri Ta Li \&%a Ta Li "Sun Sep 26 12:19:47 EDT 1986"
+.It Li September Ta Li \&%B Ta Li "Mon Sep  1 12:19:47 EDT 1986"
+.It Li January Ta Li \&%B Ta Li "Thu Jan  1 12:19:47 EST 1987"
+.It Li December Ta Li \&%B Ta Li "Mon Dec  1 12:19:47 EST 1987"
+.It Li "Sep Mon" Ta Li "\&%b %a" Ta Li "Mon Sep  1 12:19:47 EDT 1986"
+.It Li "Jan Fri" Ta Li "\&%b %a" Ta Li "Fri Jan  2 12:19:47 EDT 1987"
+.It Li "Dec Mon" Ta Li "\&%b %a" Ta Li "Mon Dec  1 12:19:47 EDT 1986"
+.It Li "Jan Wed 1989" Ta Li "\&%b \&%a \&%Y" Ta Li "Wed Jan  4 12:19:47 EST 1989"
+.It Li "Fri 9" Ta Li "\&%a \&%H" Ta Li "Fri Sep 26 09:00:00 EDT 1986"
+.It Li "Feb 10:30" Ta Li "\&%b \&%H:\&%S" Ta Li "Sun Feb  1 10:00:30 EST 1987"
+.It Li 10:30 Ta Li "\&%H:\&%M" Ta Li "Tue Sep 23 10:30:00 EDT 1986"
+.It Li 13:30 Ta Li "\&%H:\&%M" Ta Li "Tue Sep 22 13:30:00 EDT 1986"
+.El
+.Sh SEE ALSO
+.Xr ctime 3 ,
+.Xr localtime 3 ,
+.Xr mktime 3 ,
+.Xr strftime 3 ,
+.Xr strptime 3 ,
+.Xr time 3
+.Sh STANDARDS
+The
+.Fn getdate
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+function appeared in
+.At V.4 .
+.Sh BUGS
+The
+.Nm
+interface is inherently unsafe for multi-threaded programs or libraries,
+since it returns a pointer to a static variable and uses a global state
+variable.
Index: src/lib/libc/time/getdate.c
diff -u /dev/null src/lib/libc/time/getdate.c:1.1
--- /dev/null	Thu May 14 02:37:37 2009
+++ src/lib/libc/time/getdate.c	Thu May 14 02:37:36 2009
@@ -0,0 +1,270 @@
+/*	$NetBSD: getdate.c,v 1.1 2009/05/14 02:37:36 ginsbach Exp $	*/
+/*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Brian Ginsbach.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <util.h>
+
+#define TMSENTINEL	(-1)
+
+/*
+ * getdate_err is set to one of the following values on error.
+ *
+ * 1	The DATEMSK environment variable is null or undefined.
+ * 2	The template file cannot be opened for reading.
+ * 3	Failed to get file status information.
+ * 4	Template file is not a regular file.
+ * 5	Encountered an error while reading the template file.
+ * 6	Cannot allocate memory.
+ * 7	Input string does not match any line in the template.
+ * 8	Input string is invalid (for example, February 31) or could not
+ *	be represented in a time_t.
+ */
+
+int getdate_err;
+
+struct tm *
+getdate(const char *str)
+{
+	char *datemsk, *line, *rp;
+	FILE *fp;
+	struct stat sb;
+	static struct tm rtm, tmnow;
+	struct tm *tmp, *rtmp = &rtm;
+	size_t lineno = 0;
+	time_t now;
+
+	if (((datemsk = getenv("DATEMSK")) == NULL) || *datemsk == '\0') {
+		getdate_err = 1;
+		return (NULL);
+	}
+
+	if (stat(datemsk, &sb) < 0) {
+		getdate_err = 3;
+		return (NULL);
+	}
+
+	if ((sb.st_mode & S_IFMT) != S_IFREG) {
+		getdate_err = 4;
+		return (NULL);
+	}
+
+	if ((fp = fopen(datemsk, "r")) == NULL) {
+		getdate_err = 2;
+		return (NULL);
+	}
+
+	/* loop through datemsk file */
+	errno = 0;
+	rp = NULL;
+	while ((line = fparseln(fp, NULL, &lineno, NULL, 0)) != NULL) {
+		/* initialize tmp with sentinels */
+		rtm.tm_sec = rtm.tm_min = rtm.tm_hour = TMSENTINEL;
+		rtm.tm_mday = rtm.tm_mon = rtm.tm_year = TMSENTINEL;
+		rtm.tm_wday = rtm.tm_yday = rtm.tm_isdst = TMSENTINEL;
+		rtm.tm_gmtoff = 0;
+		rtm.tm_zone = NULL;
+		rp = strptime(str, line, rtmp);
+		free(line);
+		if (rp != NULL) 
+			break;
+		errno = 0;
+	}
+	if (errno != 0 || ferror(fp)) {
+		if (errno == ENOMEM)
+			getdate_err = 6;
+		else
+			getdate_err = 5;
+		fclose(fp);
+		return (NULL);
+	}
+	if (feof(fp) || (rp != NULL && *rp != '\0')) {
+		getdate_err = 7;
+		return (NULL);
+	}
+	fclose(fp);
+
+	time(&now);
+	tmp = localtime(&now);
+	tmnow = *tmp;
+
+	/*
+	 * This implementation does not accept setting the broken-down time
+	 * to anything other than the localtime().  It is not possible to
+	 * change the scanned timezone with %Z.
+	 *
+	 * Note IRIX and Solaris accept only the current zone for %Z.
+	 * XXX Is there any implementation that matches the standard?
+	 * XXX (Or am I reading the standard wrong?)
+	 *
+	 * Note: Neither XPG 6 (POSIX 2004) nor XPG 7 (POSIX 2008)
+	 * requires strptime(3) support for %Z.
+	 */
+
+	/*
+	 * Given only a weekday find the first matching weekday starting
+	 * with the current weekday and moving into the future.
+	 */
+	if (rtm.tm_wday != TMSENTINEL && rtm.tm_year == TMSENTINEL &&
+	    rtm.tm_mon == TMSENTINEL && rtm.tm_mday == TMSENTINEL) {
+		rtm.tm_year = tmnow.tm_year;
+		rtm.tm_mon = tmnow.tm_mon;
+		rtm.tm_mday = tmnow.tm_mday +
+			(rtm.tm_wday - tmnow.tm_wday + 7) % 7;
+	}
+
+	/*
+	 * Given only a month (and no year) find the first matching month
+	 * starting with the current month and moving into the future.
+	 */
+	if (rtm.tm_mon != TMSENTINEL) {
+		if (rtm.tm_year == TMSENTINEL) {
+			rtm.tm_year = tmnow.tm_year +
+				((rtm.tm_mon < tmnow.tm_mon)? 1 : 0);
+		}
+		if (rtm.tm_mday == TMSENTINEL) {
+			/* assume the first of the month */
+			rtm.tm_mday = 1;
+			/*
+			 * XXX This isn't documented! Just observed behavior.
+			 *
+			 * Given the weekday find the first matching weekday
+			 * starting with the weekday of the first day of the
+			 * the month and moving into the future.
+			 */
+			if (rtm.tm_wday != TMSENTINEL) {
+				struct tm tm;
+
+				memset(&tm, 0, sizeof(struct tm));
+				tm.tm_year = rtm.tm_year;
+				tm.tm_mon = rtm.tm_mon;
+				tm.tm_mday = 1;
+				mktime(&tm);
+				rtm.tm_mday +=
+					(rtm.tm_wday - tm.tm_wday + 7) % 7;
+			}
+		}
+	}
+
+	/*
+	 * Given no time of day assume the current time of day.
+	 */
+	if (rtm.tm_hour == TMSENTINEL &&
+	    rtm.tm_min == TMSENTINEL && rtm.tm_sec == TMSENTINEL) {
+		rtm.tm_hour = tmnow.tm_hour;
+		rtm.tm_min = tmnow.tm_min;
+		rtm.tm_sec = tmnow.tm_sec;
+	}
+	/*
+	 * Given an hour and no date, find the first matching hour starting
+	 * with the current hour and moving into the future
+	 */
+	if (rtm.tm_hour != TMSENTINEL &&
+	    rtm.tm_year == TMSENTINEL && rtm.tm_mon == TMSENTINEL &&
+	    rtm.tm_mday == TMSENTINEL) {
+		rtm.tm_year = tmnow.tm_year;
+		rtm.tm_mon = tmnow.tm_mon;
+		rtm.tm_mday = tmnow.tm_mday;
+		if (rtm.tm_hour < tmnow.tm_hour)
+			rtm.tm_hour += 24;
+	}
+
+	/*
+	 * Set to 'sane' values; mktime(3) does funny things otherwise.
+	 * No hours, no minutes, no seconds, no service.
+	 */
+	if (rtm.tm_hour == TMSENTINEL)
+		rtm.tm_hour = 0;
+	if (rtm.tm_min == TMSENTINEL)
+		rtm.tm_min = 0;
+	if (rtm.tm_sec == TMSENTINEL)
+		rtm.tm_sec = 0;
+
+	/*
+	 * Given only a year the values of month, day of month, day of year,
+	 * week day and is daylight (summer) time are unspecified.
+	 * (Specified on the Solaris man page not POSIX.)
+	 */
+	if (rtm.tm_year != TMSENTINEL &&
+	    rtm.tm_mon == TMSENTINEL && rtm.tm_mday == TMSENTINEL) {
+		rtm.tm_mon = 0;
+		rtm.tm_mday = 1;
+		/*
+		 * XXX More undocumented functionality but observed.
+		 *
+		 * Given the weekday find the first matching weekday
+		 * starting with the weekday of the first day of the the
+		 * month and moving into the future.
+		 */
+		if (rtm.tm_wday != TMSENTINEL) {
+			struct tm tm;
+
+			memset(&tm, 0, sizeof(struct tm));
+			tm.tm_year = rtm.tm_year;
+			tm.tm_mon = rtm.tm_mon;
+			tm.tm_mday = 1;
+			mktime(&tm);
+			rtm.tm_mday += (rtm.tm_wday - tm.tm_wday + 7) % 7;
+		}
+	}
+
+	/*
+	 * Given only the century but no year within, the current year
+	 * is assumed.  (Specified on the Solaris man page not POSIX.)
+	 *
+	 * Warning ugly end case
+	 *
+	 * This is more work since strptime(3) doesn't "do the right thing".
+	 */
+	if (rtm.tm_year != TMSENTINEL && (rtm.tm_year - 1900) >= 0) {
+		rtm.tm_year -= 1900;
+		rtm.tm_year += (tmnow.tm_year % 100);
+	}
+
+	/*
+	 * mktime() will normalize all values and also check that the
+	 * value will fit into a time_t.
+	 *
+	 * This is only for POSIX correctness.	A date >= 1900 is
+	 * really ok, but using a time_t limits things.
+	 */
+	if (mktime(rtmp) < 0) {
+		getdate_err = 8;
+		return (NULL);
+	}
+
+	return (rtmp);
+}

Index: src/share/examples/getdate/Makefile
diff -u /dev/null src/share/examples/getdate/Makefile:1.1
--- /dev/null	Thu May 14 02:37:37 2009
+++ src/share/examples/getdate/Makefile	Thu May 14 02:37:36 2009
@@ -0,0 +1,12 @@
+#	$NetBSD: Makefile,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+
+NOOBJ=	# defined
+
+.include <bsd.own.mk>
+
+.if ${MKSHARE} != "no"
+FILES=	datemsk.template posixmsk.example3 posixmsk.example4
+FILESDIR=/usr/share/examples/getdate
+.endif
+
+.include <bsd.prog.mk>
Index: src/share/examples/getdate/datemsk.template
diff -u /dev/null src/share/examples/getdate/datemsk.template:1.1
--- /dev/null	Thu May 14 02:37:37 2009
+++ src/share/examples/getdate/datemsk.template	Thu May 14 02:37:36 2009
@@ -0,0 +1,38 @@
+# $NetBSD: datemsk.template,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+# getdate(3) DATEMSK template file
+%m/%d/%y %I:%M:%S %p
+%m/%d/%Y %I:%M:%S %p
+%m/%d/%y %H:%M:%S
+%m/%d/%Y %H:%M:%S
+%m/%d/%y %I:%M %p
+%m/%d/%Y %I:%M %p
+%m/%d/%y %H:%M
+%m/%d/%Y %H:%M
+%m/%d/%y %I %p
+%m/%d/%Y %I %p
+%m/%d/%y %H
+%m/%d/%Y %H
+%m/%d/%y
+%m/%d/%Y
+%m/%d
+%b %d, %Y %I:%M:%S %p
+%b %d, %Y %H:%M:%S
+%B %d, %Y %I:%M:%S %p
+%B %d, %Y %H:%M:%S
+%b %d, %Y %I:%M %p
+%b %d, %Y %H:%M
+%B %d, %Y %I:%M %p
+%B %d, %Y %H:%M
+%b %d, %Y %I %p
+%b %d, %Y %H
+%B %d, %Y %I %p
+%B %d, %Y %H
+%b %d, %Y
+%B %d, %Y
+%b %d
+%B %d
+%m%d%H%M%y
+%m%d%H%M%Y
+%m%d%H%M
+%m%d%H
+%m%d
Index: src/share/examples/getdate/posixmsk.example3
diff -u /dev/null src/share/examples/getdate/posixmsk.example3:1.1
--- /dev/null	Thu May 14 02:37:37 2009
+++ src/share/examples/getdate/posixmsk.example3	Thu May 14 02:37:36 2009
@@ -0,0 +1,9 @@
+# $NetBSD: posixmsk.example3,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+#
+# The Open Group Base Specifications Issue 7 / IEEE Std 1003.1-2008
+# Example 3
+#
+%m/%d/%y
+%d.%m.%y
+%y-%m-%d
+%A %H:%M:%S
Index: src/share/examples/getdate/posixmsk.example4
diff -u /dev/null src/share/examples/getdate/posixmsk.example4:1.1
--- /dev/null	Thu May 14 02:37:37 2009
+++ src/share/examples/getdate/posixmsk.example4	Thu May 14 02:37:36 2009
@@ -0,0 +1,12 @@
+# $NetBSD: posixmsk.example4,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+#
+# The Open Group Base Specifications Issue 7 / IEEE Std 1003.1-2008
+# Example 4
+#
+%a
+%B
+%b %a
+%b %a %Y
+%a %H
+%b %H:%S
+%H:%M

Reply via email to