summaryrefslogtreecommitdiff
path: root/lib/libc/stdtime
diff options
context:
space:
mode:
authorAlexey Zelkin <phantom@FreeBSD.org>2002-03-12 17:24:54 +0000
committerAlexey Zelkin <phantom@FreeBSD.org>2002-03-12 17:24:54 +0000
commitbeb648e82be6e8579ce0eb81e53842d0e9ed5542 (patch)
tree8de1b1f1995a5b4614fdd9195e9d30c036cfefe8 /lib/libc/stdtime
parent5606778c828065308e5901a9e966ccb7630fe8ed (diff)
Notes
Diffstat (limited to 'lib/libc/stdtime')
-rw-r--r--lib/libc/stdtime/Makefile.inc2
-rw-r--r--lib/libc/stdtime/strftime.321
-rw-r--r--lib/libc/stdtime/strftime.c35
-rw-r--r--lib/libc/stdtime/strptime.c79
-rw-r--r--lib/libc/stdtime/timelocal.c208
-rw-r--r--lib/libc/stdtime/timelocal.h39
6 files changed, 117 insertions, 267 deletions
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
index 8869af0619d8..96e559b8cc0f 100644
--- a/lib/libc/stdtime/Makefile.inc
+++ b/lib/libc/stdtime/Makefile.inc
@@ -1,7 +1,7 @@
# Makefile.inc,v 1.2 1994/09/13 21:26:01 wollman Exp
# $FreeBSD$
-.PATH: ${.CURDIR}/../libc/stdtime
+.PATH: ${.CURDIR}/../libc/stdtime ${.CURDIR}/../locale
SRCS+= asctime.c difftime.c localtime.c strftime.c strptime.c timelocal.c
diff --git a/lib/libc/stdtime/strftime.3 b/lib/libc/stdtime/strftime.3
index f0987dcbe2e1..e6fed171d18e 100644
--- a/lib/libc/stdtime/strftime.3
+++ b/lib/libc/stdtime/strftime.3
@@ -85,25 +85,17 @@ as follows:-
is replaced by national representation of the full weekday name.
.It Cm %a
is replaced by national representation of
-the abbreviated weekday name, where the abbreviation
-is the first three characters.
+the abbreviated weekday name.
.It Cm \&%B
is replaced by national representation of the full month name.
.It Cm %b
is replaced by national representation of
-the abbreviated month name, where the abbreviation is
-the first three characters.
+the abbreviated month name.
.It Cm \&%C
is replaced by (year / 100) as decimal number; single
digits are preceded by a zero.
.It Cm %c
is replaced by national representation of time and date.
-The format is similar to that produced by
-.Xr ctime 3
-and is
-equivalent to "%a %Ef %T %Y".
-It also implies the
-"3+1+6+1+8+1+4" format of output.
.It Cm \&%D
is equivalent to
.Dq Li %m/%d/%y .
@@ -118,14 +110,15 @@ The sequences
are supposed to provide alternate
representations.
.Pp
-Additionly %Ef implemented to represent short month name / day
-order of the date, %EF to represent long month name / day
-order
-and %OB to represent alternative months names
+Additionly %OB implemented
+to represent alternative months names
(used standalone, without day mentioned).
.It Cm %e
is replaced by the day of month as a decimal number (1-31); single
digits are preceded by a blank.
+.It Cm \&%F
+is equivalent to
+.Dq Li %Y-%m-%d .
.It Cm \&%G
is replaced by a year as a decimal number with century.
This year is the one that contains the greater part of
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
index 40e015549223..3b1060dbc6b2 100644
--- a/lib/libc/stdtime/strftime.c
+++ b/lib/libc/stdtime/strftime.c
@@ -76,6 +76,7 @@ _fmt(format, t, pt, ptlim)
const char *const ptlim;
{
int Ealternative, Oalternative;
+ struct lc_time_T *tptr = __get_current_time_locale();
for ( ; *format; ++format) {
if (*format == '%') {
@@ -88,24 +89,24 @@ label:
break;
case 'A':
pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
- "?" : Locale->weekday[t->tm_wday],
+ "?" : tptr->weekday[t->tm_wday],
pt, ptlim);
continue;
case 'a':
pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
- "?" : Locale->wday[t->tm_wday],
+ "?" : tptr->wday[t->tm_wday],
pt, ptlim);
continue;
case 'B':
pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
- "?" : (Oalternative ? Locale->alt_month :
- Locale->month)[t->tm_mon],
+ "?" : (Oalternative ? tptr->alt_month :
+ tptr->month)[t->tm_mon],
pt, ptlim);
continue;
case 'b':
case 'h':
pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
- "?" : Locale->mon[t->tm_mon],
+ "?" : tptr->mon[t->tm_mon],
pt, ptlim);
continue;
case 'C':
@@ -120,8 +121,7 @@ label:
"%02d", pt, ptlim);
continue;
case 'c':
- /* NOTE: c_fmt is intentionally ignored */
- pt = _fmt("%a %Ef %T %Y", t, pt, ptlim);
+ pt = _fmt(tptr->c_fmt, t, pt, ptlim);
continue;
case 'D':
pt = _fmt("%m/%d/%y", t, pt, ptlim);
@@ -156,15 +156,8 @@ label:
case 'e':
pt = _conv(t->tm_mday, "%2d", pt, ptlim);
continue;
- case 'f':
- if (!Ealternative)
- break;
- pt = _fmt(Locale->Ef_fmt, t, pt, ptlim);
- continue;
case 'F':
- if (!Ealternative)
- break;
- pt = _fmt(Locale->EF_fmt, t, pt, ptlim);
+ pt = _fmt("%Y-%m-%d", t, pt, ptlim);
continue;
case 'H':
pt = _conv(t->tm_hour, "%02d", pt, ptlim);
@@ -223,15 +216,15 @@ label:
continue;
case 'p':
pt = _add((t->tm_hour >= 12) ?
- Locale->pm :
- Locale->am,
+ tptr->pm :
+ tptr->am,
pt, ptlim);
continue;
case 'R':
pt = _fmt("%H:%M", t, pt, ptlim);
continue;
case 'r':
- pt = _fmt("%I:%M:%S %p", t, pt, ptlim);
+ pt = _fmt(tptr->ampm_fmt, t, pt, ptlim);
continue;
case 'S':
pt = _conv(t->tm_sec, "%02d", pt, ptlim);
@@ -376,10 +369,10 @@ label:
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'X':
- pt = _fmt(Locale->X_fmt, t, pt, ptlim);
+ pt = _fmt(tptr->X_fmt, t, pt, ptlim);
continue;
case 'x':
- pt = _fmt(Locale->x_fmt, t, pt, ptlim);
+ pt = _fmt(tptr->x_fmt, t, pt, ptlim);
continue;
case 'y':
pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
@@ -415,7 +408,7 @@ label:
};
continue;
case '+':
- pt = _fmt(Locale->date_fmt, t, pt, ptlim);
+ pt = _fmt(tptr->date_fmt, t, pt, ptlim);
continue;
case '%':
/*
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index 754932367a60..0294a3952c84 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -93,6 +93,7 @@ _strptime(const char *buf, const char *fmt, struct tm *tm)
int i,
len;
int Ealternative, Oalternative;
+ struct lc_time_T *tptr = __get_current_time_locale();
ptr = fmt;
while (*ptr != 0) {
@@ -122,7 +123,7 @@ label:
break;
case '+':
- buf = _strptime(buf, Locale->date_fmt, tm);
+ buf = _strptime(buf, tptr->date_fmt, tm);
if (buf == 0)
return 0;
break;
@@ -145,8 +146,7 @@ label:
break;
case 'c':
- /* NOTE: c_fmt is intentionally ignored */
- buf = _strptime(buf, "%a %Ef %T %Y", tm);
+ buf = _strptime(buf, tptr->c_fmt, tm);
if (buf == 0)
return 0;
break;
@@ -170,10 +170,7 @@ label:
goto label;
case 'F':
- case 'f':
- if (!Ealternative)
- break;
- buf = _strptime(buf, (c == 'f') ? Locale->Ef_fmt : Locale->EF_fmt, tm);
+ buf = _strptime(buf, "%Y-%m-%d", tm);
if (buf == 0)
return 0;
break;
@@ -185,7 +182,7 @@ label:
break;
case 'r':
- buf = _strptime(buf, "%I:%M:%S %p", tm);
+ buf = _strptime(buf, tptr->ampm_fmt, tm);
if (buf == 0)
return 0;
break;
@@ -197,13 +194,13 @@ label:
break;
case 'X':
- buf = _strptime(buf, Locale->X_fmt, tm);
+ buf = _strptime(buf, tptr->X_fmt, tm);
if (buf == 0)
return 0;
break;
case 'x':
- buf = _strptime(buf, Locale->x_fmt, tm);
+ buf = _strptime(buf, tptr->x_fmt, tm);
if (buf == 0)
return 0;
break;
@@ -293,8 +290,8 @@ label:
* XXX This is bogus if parsed before hour-related
* specifiers.
*/
- len = strlen(Locale->am);
- if (strncasecmp(buf, Locale->am, len) == 0) {
+ len = strlen(tptr->am);
+ if (strncasecmp(buf, tptr->am, len) == 0) {
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour == 12)
@@ -303,8 +300,8 @@ label:
break;
}
- len = strlen(Locale->pm);
- if (strncasecmp(buf, Locale->pm, len) == 0) {
+ len = strlen(tptr->pm);
+ if (strncasecmp(buf, tptr->pm, len) == 0) {
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour != 12)
@@ -317,22 +314,17 @@ label:
case 'A':
case 'a':
- for (i = 0; i < asizeof(Locale->weekday); i++) {
- if (c == 'A') {
- len = strlen(Locale->weekday[i]);
- if (strncasecmp(buf,
- Locale->weekday[i],
- len) == 0)
- break;
- } else {
- len = strlen(Locale->wday[i]);
- if (strncasecmp(buf,
- Locale->wday[i],
- len) == 0)
- break;
- }
+ for (i = 0; i < asizeof(tptr->weekday); i++) {
+ len = strlen(tptr->weekday[i]);
+ if (strncasecmp(buf, tptr->weekday[i],
+ len) == 0)
+ break;
+ len = strlen(tptr->wday[i]);
+ if (strncasecmp(buf, tptr->wday[i],
+ len) == 0)
+ break;
}
- if (i == asizeof(Locale->weekday))
+ if (i == asizeof(tptr->weekday))
return 0;
tm->tm_wday = i;
@@ -411,32 +403,27 @@ label:
case 'B':
case 'b':
case 'h':
- for (i = 0; i < asizeof(Locale->month); i++) {
+ for (i = 0; i < asizeof(tptr->month); i++) {
if (Oalternative) {
if (c == 'B') {
- len = strlen(Locale->alt_month[i]);
+ len = strlen(tptr->alt_month[i]);
if (strncasecmp(buf,
- Locale->alt_month[i],
+ tptr->alt_month[i],
len) == 0)
break;
}
} else {
- if (c == 'B') {
- len = strlen(Locale->month[i]);
- if (strncasecmp(buf,
- Locale->month[i],
- len) == 0)
- break;
- } else {
- len = strlen(Locale->mon[i]);
- if (strncasecmp(buf,
- Locale->mon[i],
- len) == 0)
- break;
- }
+ len = strlen(tptr->month[i]);
+ if (strncasecmp(buf, tptr->month[i],
+ len) == 0)
+ break;
+ len = strlen(tptr->mon[i]);
+ if (strncasecmp(buf, tptr->mon[i],
+ len) == 0)
+ break;
}
}
- if (i == asizeof(Locale->month))
+ if (i == asizeof(tptr->month))
return 0;
tm->tm_mon = i;
diff --git a/lib/libc/stdtime/timelocal.c b/lib/libc/stdtime/timelocal.c
index 3a810edfb523..48c4b8aca543 100644
--- a/lib/libc/stdtime/timelocal.c
+++ b/lib/libc/stdtime/timelocal.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
* Copyright (c) 1997 FreeBSD Inc.
* All rights reserved.
*
@@ -26,30 +27,18 @@
* $FreeBSD$
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/syslimits.h>
-#include <fcntl.h>
-#include <locale.h>
#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include "setlocale.h"
-#include "timelocal.h"
-static int split_lines(char *, const char *);
-static void set_from_buf(const char *, int);
+#include "ldpart.h"
+#include "timelocal.h"
-struct lc_time_T _time_localebuf;
-int _time_using_locale;
+static struct lc_time_T _time_locale;
+static int _time_using_locale;
+static char *time_locale_buf;
-#define LCTIME_SIZE_FULL (sizeof(struct lc_time_T) / sizeof(char *))
-#define LCTIME_SIZE_1 \
- (offsetof(struct lc_time_T, alt_month[0]) / sizeof(char *))
-#define LCTIME_SIZE_2 \
- (offsetof(struct lc_time_T, Ef_fmt) / sizeof(char *))
+#define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *))
-const struct lc_time_T _C_time_locale = {
+static const struct lc_time_T _C_time_locale = {
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
@@ -68,19 +57,18 @@ const struct lc_time_T _C_time_locale = {
"%H:%M:%S",
/*
- ** x_fmt
- ** Since the C language standard calls for
- ** "date, using locale's date format," anything goes.
- ** Using just numbers (as here) makes Quakers happier;
- ** it's also compatible with SVR4.
- */
+ * x_fmt
+ * Since the C language standard calls for
+ * "date, using locale's date format," anything goes.
+ * Using just numbers (as here) makes Quakers happier;
+ * it's also compatible with SVR4.
+ */
"%m/%d/%y",
/*
- ** c_fmt (ctime-compatible)
- ** Not used, just compatibility placeholder.
- */
- NULL,
+ * c_fmt
+ */
+ "%a %b %e %H:%M:%S %Y",
/* am */
"AM",
@@ -89,155 +77,43 @@ const struct lc_time_T _C_time_locale = {
"PM",
/* date_fmt */
- "%a %Ef %X %Z %Y",
+ "%a %b %e %H:%M:%S %Z %Y",
+ /* alt_month
+ * Standalone months forms for %OB
+ */
{
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
},
- /* Ef_fmt
- ** To determine short months / day order
- */
- "%b %e",
+ /* md_order
+ * Month / day order in dates
+ */
+ "md",
- /* EF_fmt
- ** To determine long months / day order
- */
- "%B %e"
+ /* ampm_fmt
+ * To determine 12-hour clock format time (empty, if N/A)
+ */
+ "%I:%M:%S %p"
};
-
-int
-__time_load_locale(const char *name)
-{
- static char * locale_buf;
- static char locale_buf_C[] = "C";
- static int num_lines;
-
- int fd;
- char * lbuf;
- char * p;
- const char * plim;
- char filename[PATH_MAX];
- struct stat st;
- size_t namesize;
- size_t bufsize;
- int save_using_locale;
-
- save_using_locale = _time_using_locale;
- _time_using_locale = 0;
-
- if (name == NULL)
- goto no_locale;
-
- if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
- return 0;
-
- /*
- ** If the locale name is the same as our cache, use the cache.
- */
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- set_from_buf(lbuf, num_lines);
- _time_using_locale = 1;
- return 0;
- }
- /*
- ** Slurp the locale file into the cache.
- */
- namesize = strlen(name) + 1;
-
- if (!_PathLocale)
- goto no_locale;
- /* Range checking not needed, 'name' size is limited */
- strcpy(filename, _PathLocale);
- strcat(filename, "/");
- strcat(filename, name);
- strcat(filename, "/LC_TIME");
- fd = _open(filename, O_RDONLY);
- if (fd < 0)
- goto no_locale;
- if (fstat(fd, &st) != 0)
- goto bad_locale;
- if (st.st_size <= 0)
- goto bad_locale;
- bufsize = namesize + st.st_size;
- locale_buf = NULL;
- lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
- malloc(bufsize) : reallocf(lbuf, bufsize);
- if (lbuf == NULL)
- goto bad_locale;
- (void) strcpy(lbuf, name);
- p = lbuf + namesize;
- plim = p + st.st_size;
- if (_read(fd, p, (size_t) st.st_size) != st.st_size)
- goto bad_lbuf;
- if (_close(fd) != 0)
- goto bad_lbuf;
- /*
- ** Parse the locale file into localebuf.
- */
- if (plim[-1] != '\n')
- goto bad_lbuf;
- num_lines = split_lines(p, plim);
- if (num_lines >= LCTIME_SIZE_FULL)
- num_lines = LCTIME_SIZE_FULL;
- else if (num_lines >= LCTIME_SIZE_2)
- num_lines = LCTIME_SIZE_2;
- else if (num_lines >= LCTIME_SIZE_1)
- num_lines = LCTIME_SIZE_1;
- else
- goto reset_locale;
- set_from_buf(lbuf, num_lines);
- /*
- ** Record the successful parse in the cache.
- */
- locale_buf = lbuf;
-
- _time_using_locale = 1;
- return 0;
-
-reset_locale:
- /*
- * XXX - This may not be the correct thing to do in this case.
- * setlocale() assumes that we left the old locale alone.
- */
- locale_buf = locale_buf_C;
- _time_localebuf = _C_time_locale;
- save_using_locale = 0;
-bad_lbuf:
- free(lbuf);
-bad_locale:
- (void)_close(fd);
-no_locale:
- _time_using_locale = save_using_locale;
- return -1;
+struct lc_time_T *
+__get_current_time_locale(void) {
+ return (_time_using_locale
+ ? &_time_locale
+ : (struct lc_time_T *)&_C_time_locale);
}
-static int
-split_lines(char *p, const char *plim)
-{
- int i;
+int
+__time_load_locale(const char *name) {
- for (i = 0; p < plim; i++) {
- p = strchr(p, '\n');
- *p++ = '\0';
- }
- return i;
-}
+ int ret;
-static void
-set_from_buf(const char *p, int num_lines)
-{
- const char **ap;
- int i;
+ ret = __part_load_locale(name, &_time_using_locale,
+ time_locale_buf, "LC_TIME",
+ LCTIME_SIZE, LCTIME_SIZE,
+ (const char **)&_time_locale);
- for (ap = (const char **) &_time_localebuf, i = 0;
- i < num_lines; ++ap, ++i)
- *ap = p += strlen(p) + 1;
- if (num_lines >= LCTIME_SIZE_2)
- return;
- for (i = 0; i < 12; i++)
- _time_localebuf.alt_month[i] = _time_localebuf.month[i];
+ return (ret);
}
diff --git a/lib/libc/stdtime/timelocal.h b/lib/libc/stdtime/timelocal.h
index b5ab91dfb6a8..5d26bf938d97 100644
--- a/lib/libc/stdtime/timelocal.h
+++ b/lib/libc/stdtime/timelocal.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997 FreeBSD Inc.
+ * Copyright (c) 1997-2002 FreeBSD Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,29 +26,30 @@
* $FreeBSD$
*/
+#ifndef _TIMELOCAL_H_
+#define _TIMELOCAL_H_
+
/*
* Private header file for the strftime and strptime localization
* stuff.
*/
struct lc_time_T {
- const char * mon[12];
- const char * month[12];
- const char * wday[7];
- const char * weekday[7];
- const char * X_fmt;
- const char * x_fmt;
- const char * c_fmt; /* not used, just compatibility placeholder */
- const char * am;
- const char * pm;
- const char * date_fmt;
- const char * alt_month[12];
- const char * Ef_fmt;
- const char * EF_fmt;
+ const char *mon[12];
+ const char *month[12];
+ const char *wday[7];
+ const char *weekday[7];
+ const char *X_fmt;
+ const char *x_fmt;
+ const char *c_fmt;
+ const char *am;
+ const char *pm;
+ const char *date_fmt;
+ const char *alt_month[12];
+ const char *md_order;
+ const char *ampm_fmt;
};
-extern struct lc_time_T _time_localebuf;
-extern int _time_using_locale;
-extern const struct lc_time_T _C_time_locale;
-
-#define Locale (_time_using_locale ? &_time_localebuf : &_C_time_locale)
+struct lc_time_T *__get_current_time_locale(void);
+int __time_load_locale(const char *);
+#endif /* !_TIMELOCAL_H_ */