[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Latest version of svn_parse_date.

From: C. Scott Ananian <cananian_at_lesser-magoo.lcs.mit.edu>
Date: 2001-08-25 02:36:16 CEST

Appended is a patch representing my latest work on the svn_parse_date
replacement. The attached .tgz should also be untarred from the root
subversion directory to create the files
  subversion/libsvn_subr/svn_date.c
  subversion/tests/libsvn_subr/date-test.c
which can't be included in the patch due to permissions, etc, etc.

New features:
 1) code is completely APR-ized. apr_strptime is defined and
    svn_parse_date only uses APR functions. Portability++.
 2) test suite created for the parser. this both serves to illustrate
    some examples of input formats, as well as the validate that
    parsing occurs correctly.
 3) I put a lot of thought into calendar weirdnesses, and the current
    code should handle leap years, leap seconds, shifts to daylight
    savings time, and even stranger things correctly (as long as
    your system's implementation of localtime (as used under the
    covers by APR) handles them correctly).
New limitations:
 1) More work needed on apr_strptime: I need to add autoconf checks
    for the native strptime function, and fall back to a replacement
    (not yet written).
 2) I've got a new internationalization scheme that should better
    address noun declension, etc, issues. I haven't implemented
    it yet.

I'd appreciate it if the APR gurus could look over the patches to APR in
particular and let me know if they see any problems with the direction I'm
going.
  --s

arrangements Minister smuggle mail drop DES Castro MI6 Echelon biowarfare
colonel plutonium Qaddafi Saddam Hussein quiche India General LA blowfish
              ( http://lesser-magoo.lcs.mit.edu/~cananian )

Index: autogen.sh
===================================================================
RCS file: /usr/local/tigris/data/helm/cvs/repository/subversion/autogen.sh,v
retrieving revision 1.47
diff -u -p -r1.47 autogen.sh
--- autogen.sh 2001/08/16 19:45:44 1.47
+++ autogen.sh 2001/08/25 00:20:52
@@ -102,23 +102,6 @@ cp $ltfile ac-helpers/libtool.m4
 # any old aclocal.m4 left over from prior build so it doesn't cause errors.
 rm -f aclocal.m4
 
-# Produce getdate.c from getdate.y.
-# Again, this means that "developers" who run autogen.sh need either
-# yacc or bison -- but not people who compile sourceballs, since `make
-# dist` will include getdate.c.
-echo "Creating getdate.c..."
-bison -o subversion/libsvn_subr/getdate.c subversion/libsvn_subr/getdate.y
-if [ $? -ne 0 ]; then
- yacc -o subversion/libsvn_subr/getdate.c subversion/libsvn_subr/getdate.y
- if [ $? -ne 0 ]; then
- echo
- echo " Error: can't find either bison or yacc."
- echo " One of these is needed to generate the date parser."
- echo
- exit 1
- fi
-fi
-
 # Create the file detailing all of the build outputs for SVN.
 #
 # Note: this dependency on Python is fine: only SVN developers use autogen.sh
Index: build.conf
===================================================================
RCS file: /usr/local/tigris/data/helm/cvs/repository/subversion/build.conf,v
retrieving revision 1.31
diff -u -p -r1.31 build.conf
--- build.conf 2001/08/17 16:31:21 1.31
+++ build.conf 2001/08/25 00:20:52
@@ -269,6 +269,15 @@ install = test
 group = programs
 libs = libsvn_test libsvn_delta libsvn_subr $(SVN_APR_LIBS) libexpat
 
+# test svn_parse_date function.
+[date-test]
+type = exe
+path = subversion/tests/libsvn_subr
+sources = date-test.c
+install = test
+group = programs
+libs = libsvn_test libsvn_delta libsvn_subr $(SVN_APR_LIBS) libexpat
+
 
 ### Tests that are simply broken (fix?) ----------
 
Index: subversion/clients/cmdline/main.c
===================================================================
RCS file: /usr/local/tigris/data/helm/cvs/repository/subversion/subversion/clients/cmdline/main.c,v
retrieving revision 1.16
diff -u -p -r1.16 main.c
--- subversion/clients/cmdline/main.c 2001/08/24 22:47:26 1.16
+++ subversion/clients/cmdline/main.c 2001/08/25 00:20:52
@@ -244,14 +244,29 @@ main (int argc, const char * const *argv
         opt_state.revision = (svn_revnum_t) atoi (opt_arg);
         break;
       case 'D':
- /* svn_parse_date() originates in getdate.y; while I'd love to
- change it to const char *, that turns out to be a little
- more complex than just adding the qualifier. So for now,
- I'm casting to get rid of the compilation warning, and have
- filed issue #408 so we don't forget about this. -kff */
- apr_ansi_time_to_apr_time (&opt_state.date,
- svn_parse_date ((char *) opt_arg, NULL));
- break;
+ {
+ apr_time_t now, then;
+ /* XXX: If we evaluate -D multiple times in the course of
+ * an operation, we probably want to use the same 'now'
+ * value every time, instead of always using the current time. */
+ now = apr_time_now();
+ apr_err = svn_parse_date(opt_arg, now, &then);
+ if (APR_STATUS_IS_SUCCESS (apr_err))
+ {
+ opt_state.date = then;
+ }
+ else
+ {
+ err = svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR,
+ 0, NULL, pool,
+ "Invalid date specification `%s'",
+ opt_arg);
+ svn_handle_error (err, stderr, FALSE);
+ /* XXX: this should be fatal? Otherwise we may
+ * commit/checkout wrong versions? */
+ }
+ break;
+ }
       case 'v':
         opt_state.version = TRUE;
       case 'h':
@@ -309,6 +324,10 @@ main (int argc, const char * const *argv
                                      "The locale `%s' can not be set",
                                      opt_arg);
             svn_handle_error (err, stderr, FALSE);
+ /* XXX: this should be fatal? Otherwise we may
+ * commit/checkout wrong versions? (because we specified
+ * date strings etc according to a locale which wasn't actually
+ * set? */
           }
         break;
       default:
Index: subversion/include/svn_time.h
===================================================================
RCS file: /usr/local/tigris/data/helm/cvs/repository/subversion/subversion/include/svn_time.h,v
retrieving revision 1.2
diff -u -p -r1.2 svn_time.h
--- subversion/include/svn_time.h 2001/07/04 12:12:20 1.2
+++ subversion/include/svn_time.h 2001/08/25 00:20:52
@@ -38,16 +38,15 @@ svn_stringbuf_t *svn_time_to_string (apr
 apr_time_t svn_time_from_string (svn_stringbuf_t *timestr);
 
 
-/* Needed by getdate.y parser */
-struct getdate_time {
- time_t time;
- short timezone;
-};
-
-/* The one interface in our getdate.y parser; convert human-readable
- date TEXT into a standard C time_t. The 2nd argument is unused;
- we always pass NULL. */
-time_t svn_parse_date (char *text, struct getdate_time *now);
+/* The one public interface of the date parser: convert human-readable
+ date TEXT into a standard C time_t. Note that 'now' is passed as
+ a parameter so that you can use this routine to find out how SVN
+ *would have* parsed some string at some *arbitrary* time: relative
+ times should always parse the same even if svn_parse_date is called
+ multiple times during a computation of finite length. For this reason,
+ the 'now' parameter is *mandatory*. Returns 0 on success. */
+apr_status_t svn_parse_date (const char *text, const apr_time_t now,
+ apr_time_t * result);
 
 #endif /* SVN_TIME_H */
 
Index: subversion/tests/libsvn_subr/.cvsignore
===================================================================
RCS file: /usr/local/tigris/data/helm/cvs/repository/subversion/subversion/tests/libsvn_subr/.cvsignore,v
retrieving revision 1.10
diff -u -p -r1.10 .cvsignore
--- subversion/tests/libsvn_subr/.cvsignore 2001/06/08 21:31:23 1.10
+++ subversion/tests/libsvn_subr/.cvsignore 2001/08/25 00:20:52
@@ -8,4 +8,5 @@ stringtest
 target-test
 stream-test
 path-test
+date-test
 z
Index: www/project_tasks.html
===================================================================
RCS file: /usr/local/tigris/data/helm/cvs/repository/subversion/www/project_tasks.html,v
retrieving revision 1.8
diff -u -p -r1.8 project_tasks.html
--- www/project_tasks.html 2001/07/25 15:53:08 1.8
+++ www/project_tasks.html 2001/08/25 00:20:52
@@ -119,46 +119,6 @@ Here are the tasks:
    </li>
    <p>
 
- <!-- ---------------------------------------------------------- -->
-
- <li> <b>Fix up date parsing library issues</b> <p>
- </li>
- This task is probably small, but will require some investigation
- and list discussion first probably. The basic issue is this: Ben
- took the getdate.y date grammar file from CVS (that file has always
- been in the public domain) and imported it into Subversion. So now
- Subversion has CVS's date parsing capabilities, which are good, but
- not perfect. Aside from the functionality issues, there's also the
- problem that getdate.c needs to be automatically generated from
- getdate.y, and it would be better to have a .c file that we edit
- directly, than a .y file which causes Subversion developers to be
- dependent on having the correct version of Yacc/Bison/Whatever
- installed.
- <p>
- This message from Branko summarizes the issues pretty well; read
- it, then move back and forth in the thread to get some context and
- a sense of what people see as the solution domain right now:
- <p>
- <a
- href="http://subversion.tigris.org/servlets/ReadMsg?msgId=31147&listName=dev"
- >http://subversion.tigris.org/servlets/ReadMsg?msgId=31147&listName=dev</a>
- <p>
-
- <!-- ---------------------------------------------------------- -->
-
- <li> <b>Constify svn_parse_date()'s first parameter</b> <p>
- </li>
- This is
- <a
- href="http://subversion.tigris.org/issues/show_bug.cgi?id=408">issue
- #408</a>, the description is:
- <p>
- The first argument of svn_parse_date() should be const. However,
- because the function originates in getdate.y and that parameter is
- related to the global yyInput variable, there may be more to this
- change than just adding the qualifier...
- <p>
-
 <!-- template for further items: -->
 <!--
 
Index: apr/include/apr_time.h
===================================================================
RCS file: /home/cvspublic/apr/include/apr_time.h,v
retrieving revision 1.41
diff -u -p -r1.41 apr_time.h
--- apr/include/apr_time.h 2001/08/24 17:55:45 1.41
+++ apr/include/apr_time.h 2001/08/25 00:14:43
@@ -228,6 +228,27 @@ APR_DECLARE(apr_status_t) apr_strftime(c
                                        apr_size_t max, const char *format,
                                        apr_exploded_time_t *tm);
 
+/**
+ * converts a string representation of time to an exploded time
+ * similar to X/OPEN standard strptime function. retptr gets
+ * NULL if apr_strptime fails to match all of the format string,
+ * or a pointer to the first character not processed in the format
+ * string otherwise (points to '\0' if the format string matches the
+ * complete input string). This function does not initialize exploded
+ * time but only stores the values specified by the format string,
+ * although implementations on some platforms will recompute fields
+ * such as tm_wday and tm_yday if any of the year, month, or day
+ * elements are changed.
+ * @param s string to parse
+ * @param retptr returns the end of parsed section of s
+ * @param format The format for the time string
+ * @param tm The parsed time
+ * @deffunc apr_status_t apr_strptime(const char *s, char **retptr, const char *format, apr_exploded_time_t *tm)
+ */
+APR_DECLARE(apr_status_t) apr_strptime(const char *s, char **retptr,
+ const char *format,
+ apr_exploded_time_t *tm);
+
 #ifdef __cplusplus
 }
 #endif
Index: apr/time/unix/timestr.c
===================================================================
RCS file: /home/cvspublic/apr/time/unix/timestr.c,v
retrieving revision 1.23
diff -u -p -r1.23 timestr.c
--- apr/time/unix/timestr.c 2001/04/12 22:44:42 1.23
+++ apr/time/unix/timestr.c 2001/08/25 00:14:43
@@ -189,3 +189,56 @@ apr_status_t apr_strftime(char *s, apr_s
     (*retsize) = strftime(s, max, format, &tm);
     return APR_SUCCESS;
 }
+
+#define APR_HAS_STRPTIME /* XXX: TEMPORARY, FOR DEBUGGING */
+#ifdef APR_HAS_STRPTIME
+/* this works iff:
+ * a) system has (working) strptime function
+ * b) apr_os_exp_time is same as struct tm
+ * c) apr_os_exp_time_put ignores pool argument.
+ * Note that GNU glibc incorrectly handled %OI argument before
+ * 10-aug-2001, and so fails test (a). */
+/* XXX: how do i check the above? */
+apr_status_t apr_strptime(const char *s, char **retptr,
+ const char *format, apr_exploded_time_t *tm)
+{
+ struct tm os_tm, *os_tmp = &os_tm;
+ apr_status_t status;
+ status = apr_os_exp_time_get(&os_tmp, tm);
+ if (status != APR_SUCCESS) goto bail;
+ (*retptr) = strptime(s, format, os_tmp);
+ if (NULL == (*retptr)) {
+ status = APR_EBADDATE;
+ goto bail;
+ }
+ /* versions of glibc before 10-aug-2001 contain bug parsing %OI */
+ /* see cvs log for revision 1.34 of libc/time/strptime.c */
+ /* so test for this bug and work-around it if necessary */
+ {
+ struct tm test = os_tm;
+ test.tm_hour=0; /* protect against *really* broken strptime */
+ strptime ("8", "%OI", &test);
+ if (test.tm_hour == 7) /* BUGGY GLIBC! */
+ {
+ const char *cp;
+ /* first determine whether the format string contains %OI,
+ * necessitating a fixup. */
+ int needs_fixup=0;
+ for (cp = format; *cp && !needs_fixup; cp++)
+ if (*cp=='%' && *++cp=='O' && *++cp=='I')
+ needs_fixup=1;
+ if (needs_fixup)
+ {
+ /* fixup the bug, sigh. */
+ os_tm.tm_hour = os_tm.tm_hour + 1;
+ if (os_tm.tm_hour == 12 || os_tm.tm_hour == 24)
+ os_tm.tm_hour -= 12;
+ }
+ }
+ }
+ /* -- end bug workaround -- */
+ status = apr_os_exp_time_put(tm, &os_tmp, NULL/*craaazy*/);
+ bail:
+ return status;
+}
+#endif

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

  • APPLICATION/octet-stream attachment: svn.tgz
Received on Sat Oct 21 14:36:37 2006

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.