From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10358 invoked by alias); 9 Jul 2015 10:04:26 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 35745 Received: (qmail 28531 invoked from network); 9 Jul 2015 10:04:24 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; bh=S79Sm4+RDpmeVl9W8lvvT9CL6caeNYJOhyuPZ/m1ka8=; b=MDEd4r9r3XJ7Jo3hBFuXWYl4L9jsYaBtzw2wM2VrIi4AG6LvJIduoz60slpVi/3aZ4 MmNt4KW0qDhilAox5OC0HoZBUlRg0CL1To3vNhJGQusYc0y1dYcZyC9v9PvKeKNKgiUA Fr8Bdh9MyrC/ceU2lSJ/zE9JcaZcNs4RsX3PpuDtsgnI12fYS5wfBBhlOxR4DFyjfeKL aayejxMZE3vgFDY6mBfuCRTi2BFfykFs75GLc/WOLteYkb6MtqpFbraLwf4r4B0SaxwK 12Xd9NP+r789H7d/RPlGEewtt0zYS8Qro+xAefyAAFM+HpQgwzgFZDJZ46uq4GS1Uzzp yEyg== X-Received: by 10.180.149.206 with SMTP id uc14mr41271593wib.12.1436435894158; Thu, 09 Jul 2015 02:58:14 -0700 (PDT) From: Mikael Magnusson To: zsh-workers@zsh.org Subject: PATCH: ztrftime: Pass everything unhandled to the system strftime() Date: Thu, 9 Jul 2015 11:58:07 +0200 Message-Id: <1436435887-28736-1-git-send-email-mikachu@gmail.com> X-Mailer: git-send-email 2.4.0 In-Reply-To: <20150709094122.17abacc8@pwslap01u.europe.root.pri> References: <20150709094122.17abacc8@pwslap01u.europe.root.pri> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This seems to work, I've added tests, and a comment. See also threads 35725 and 35734. --- Src/utils.c | 79 +++++++++++++++++++++++++++++++++++---------------- Test/V09datetime.ztst | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 Test/V09datetime.ztst Eagerly awaiting reports of systems that handle %04y but not %#A. diff --git a/Src/utils.c b/Src/utils.c index 13fc96a..8ff575f 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2883,7 +2883,7 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) int hr12; #ifdef HAVE_STRFTIME int decr; - char tmp[4]; + char *fmtstart; #else static char *astr[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; @@ -2899,7 +2899,11 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) int strip; int digs = 3; +#ifdef HAVE_STRFTIME + fmtstart = +#endif fmt++; + if (*fmt == '-') { strip = 1; fmt++; @@ -2924,6 +2928,21 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) */ if (ztrftimebuf(&bufsize, 2)) return -1; +#ifdef HAVE_STRFTIME + /* Our internal handling doesn't handle padding and other gnu extensions, + * so here we detect them and pass over to strftime(). We don't want + * to do this unconditionally though, as we have some extensions that + * strftime() doesn't have (%., %f, %L and %K) */ +morefmt: + if (!((fmt - fmtstart == 1) || (fmt - fmtstart == 2 && strip) || *fmt == '.')) { + while (*fmt && strchr("OE^#_-0123456789", *fmt)) + fmt++; + if (*fmt) { + fmt++; + goto strftimehandling; + } + } +#endif switch (*fmt++) { case '.': if (ztrftimebuf(&bufsize, digs)) @@ -2939,10 +2958,10 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) sprintf(buf, "%0*ld", digs, usec); buf += digs; break; - case 'd': - if (tm->tm_mday > 9 || !strip) - *buf++ = '0' + tm->tm_mday / 10; - *buf++ = '0' + tm->tm_mday % 10; + case '\0': + /* Guard against premature end of string */ + *buf++ = '%'; + fmt--; break; case 'f': strip = 1; @@ -2983,6 +3002,12 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) *buf++ = '0' + (hr12 % 10); break; +#ifndef HAVE_STRFTIME + case 'd': + if (tm->tm_mday > 9 || !strip) + *buf++ = '0' + tm->tm_mday / 10; + *buf++ = '0' + tm->tm_mday % 10; + break; case 'm': if (tm->tm_mon > 8 || !strip) *buf++ = '0' + (tm->tm_mon + 1) / 10; @@ -3003,18 +3028,8 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) *buf++ = '0' + (tm->tm_year / 10) % 10; *buf++ = '0' + tm->tm_year % 10; break; - case '\0': - /* Guard against premature end of string */ - *buf++ = '%'; - fmt--; - break; -#ifndef HAVE_STRFTIME case 'Y': { - /* - * Not worth handling this natively if - * strftime has it. - */ int year, digits, testyear; year = tm->tm_year + 1900; digits = 1; @@ -3048,24 +3063,38 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) if (fmt[-1] != '%') *buf++ = fmt[-1]; #else + case 'E': + case 'O': + case '^': + case '#': + case '_': + case '-': + case '0' ... '9': + goto morefmt; +strftimehandling: default: /* * Remember we've already allowed for two characters * in the accounting in bufsize (but nowhere else). */ - *buf = '\1'; - sprintf(tmp, strip ? "%%-%c" : "%%%c", fmt[-1]); - if (!strftime(buf, bufsize + 2, tmp, tm)) { - if (*buf) { - buf[0] = '\0'; - return -1; + int size = fmt - fmtstart; + char *tmp = zhalloc(size + 1); + strncpy(tmp, fmtstart, size); + tmp[size] = '\0'; + *buf = '\1'; + if (!strftime(buf, bufsize + 2, tmp, tm)) + { + if (*buf) { + buf[0] = '\0'; + return -1; + } + return 0; } - return 0; + decr = strlen(buf); + buf += decr; + bufsize -= decr - 2; } - decr = strlen(buf); - buf += decr; - bufsize -= decr - 2; #endif break; } diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst new file mode 100644 index 0000000..c69e31e --- /dev/null +++ b/Test/V09datetime.ztst @@ -0,0 +1,63 @@ +%prep + + if ! (zmodload zsh/datetime >/dev/null 2>/dev/null); then + ZTST_unimplemented="can't load the zsh/datetime module for testing" + fi + setopt multibyte + zmodload zsh/datetime + unset LC_ALL + LC_TIME=C + if [[ "$(strftime %04y 1)" = "0070" ]]; then + [[ "$(LC_TIME=ja_JP.UTF-8 strftime %OS 1)" = 一 ]] || { + print -u $ZTST_fd "Not testing alternate date format extensions (missing ja_JP.UTF-8 locale)" + skip_japanese=1 + } + else + print -u $ZTST_fd "Skipping strftime extension tests" + skip_extensions=1 + fi + +%test + + strftime %y 0 + strftime %Y 1000000000 + strftime %x 1200000000 + strftime %X 1200000001 +0:basic format specifiers +>70 +>2001 +>01/10/08 +>22:20:01 + + strftime %-m_%f_%K_%L 1181000000 + strftime %6. 0 +0:zsh extensions +>6_5_1_1 +>000000 + + [[ $skip_japanese = 1 ]] && repeat 5; do echo skipped; done || ( + LC_TIME=ja_JP.UTF-8 + strftime %Ey 1000000000 + strftime %Oy 1000000000 + strftime %Ex 1000000000 + strftime %OS 1000000000 + strftime %03Ey 650000000 + ) +0:alternate format extensions +*>skipped|13 +>skipped|一 +>skipped|平成13年09月09日 +>skipped|四十 +>skipped|002 + + [[ $skip_extensions = 1 ]] && repeat 4; do echo skipped; done || ( + strftime '%#A' 0 + strftime '%^_10B' 0 + strftime %03Ey 650000000 + strftime %-Oe 0 + ) +0:various extensions +*>skipped|THURSDAY +>skipped| JANUARY +>skipped|090 +>skipped|1 -- 2.4.0