diff options
| author | Alexey Zelkin <phantom@FreeBSD.org> | 2002-03-12 17:24:54 +0000 |
|---|---|---|
| committer | Alexey Zelkin <phantom@FreeBSD.org> | 2002-03-12 17:24:54 +0000 |
| commit | beb648e82be6e8579ce0eb81e53842d0e9ed5542 (patch) | |
| tree | 8de1b1f1995a5b4614fdd9195e9d30c036cfefe8 /lib/libc/stdtime | |
| parent | 5606778c828065308e5901a9e966ccb7630fe8ed (diff) | |
Notes
Diffstat (limited to 'lib/libc/stdtime')
| -rw-r--r-- | lib/libc/stdtime/Makefile.inc | 2 | ||||
| -rw-r--r-- | lib/libc/stdtime/strftime.3 | 21 | ||||
| -rw-r--r-- | lib/libc/stdtime/strftime.c | 35 | ||||
| -rw-r--r-- | lib/libc/stdtime/strptime.c | 79 | ||||
| -rw-r--r-- | lib/libc/stdtime/timelocal.c | 208 | ||||
| -rw-r--r-- | lib/libc/stdtime/timelocal.h | 39 |
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_ */ |
