diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2002-06-17 09:45:15 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2002-06-17 09:45:15 +0000 |
commit | d6b2a407783dbbd6c9680601da005de0bb0ff37d (patch) | |
tree | d72244507fab5c5c59d12aa10fa411943631c56c /libc/misc/time/strftime.c | |
parent | a7ce5bbdcd1217af1aab4c15e4ce337c8ef33973 (diff) |
Commit the new time stuff, even though I haven't made it threadsafe yet.
At least people can play with it. Also, fix a buglet in setenv.c.
Diffstat (limited to 'libc/misc/time/strftime.c')
-rw-r--r-- | libc/misc/time/strftime.c | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/libc/misc/time/strftime.c b/libc/misc/time/strftime.c deleted file mode 100644 index bde0d93d8..000000000 --- a/libc/misc/time/strftime.c +++ /dev/null @@ -1,395 +0,0 @@ -/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> /* Some systems define `time_t' here. */ -#include <sys/time.h> -#include <time.h> -#include <ctype.h> -#include <limits.h> - -static unsigned int week (const struct tm *const, int, int); - -#define add(n, f) \ - do \ - { \ - i += (n); \ - if (i >= maxsize) \ - return 0; \ - else \ - if (p) \ - { \ - f; \ - p += (n); \ - } \ - } while (0) -#define cpy(n, s) add((n), memcpy((void *) p, (void *) (s), (n))) - -#ifdef _LIBC -#define fmt(n, args) add((n), if (sprintf args != (n)) return 0) -#else -#define fmt(n, args) add((n), sprintf args; if (strlen (p) != (n)) return 0) -#endif - - - -/* Return the week in the year specified by TP, - with weeks starting on STARTING_DAY. */ -static unsigned int week(const struct tm *const tp , int starting_day , int max_preceding ) -{ - int wday, dl, base; - - wday = tp->tm_wday - starting_day; - if (wday < 0) - wday += 7; - - /* Set DL to the day in the year of the first day of the week - containing the day specified in TP. */ - dl = tp->tm_yday - wday; - - /* For the computation following ISO 8601:1988 we set the number of - the week containing January 1st to 1 if this week has more than - MAX_PRECEDING days in the new year. For ISO 8601 this number is - 3, for the other representation it is 7 (i.e., not to be - fulfilled). */ - base = ((dl + 7) % 7) > max_preceding ? 1 : 0; - - /* If DL is negative we compute the result as 0 unless we have to - compute it according ISO 8601. In this case we have to return 53 - or 1 if the week containing January 1st has less than 4 days in - the new year or not. If DL is not negative we calculate the - number of complete weeks for our week (DL / 7) plus 1 (because - only for DL < 0 we are in week 0/53 and plus the number of the - first week computed in the last step. */ - return dl < 0 ? (dl < -max_preceding ? 53 : base) - : base + 1 + dl / 7; -} - -#ifndef __UCLIBC_HAS_LOCALE__ -extern char const __weekday_name[][10]; -extern char const __month_name[][10]; -#endif - -/* Write information from TP into S according to the format - string FORMAT, writing no more that MAXSIZE characters - (including the terminating '\0') and returning number of - characters written. If S is NULL, nothing will be written - anywhere, so to determine how many characters would be - written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */ -size_t strftime( char *s , size_t maxsize , const char *format , register const struct tm *tp) -{ - int hour12 = tp->tm_hour; -#ifdef __UCLIBC_HAS_LOCALE__ - const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday); - const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday); - const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon); - const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon); - const char *const ampm = _NL_CURRENT (LC_TIME, - hour12 > 11 ? PM_STR : AM_STR); - size_t aw_len = strlen(a_wkday); - size_t am_len = strlen(a_month); - size_t ap_len = strlen (ampm); -#else - const char *const f_wkday = __weekday_name[tp->tm_wday]; - const char *const f_month = __month_name[tp->tm_mon]; - const char *const a_wkday = f_wkday; - const char *const a_month = f_month; - const char *const ampm = "AMPM" + 2 * (hour12 > 11); - size_t aw_len = 3; - size_t am_len = 3; - size_t ap_len = 2; -#endif - size_t wkday_len = strlen(f_wkday); - size_t month_len = strlen(f_month); - const unsigned int y_week0 = week (tp, 0, 7); - const unsigned int y_week1 = week (tp, 1, 7); - const unsigned int y_week2 = week (tp, 1, 3); - const char *zone; - size_t zonelen; - register size_t i = 0; - register char *p = s; - register const char *f; - char number_fmt[5]; - - /* Initialize the buffer we will use for the sprintf format for numbers. */ - number_fmt[0] = '%'; - - /* The POSIX test suite assumes that setting - the environment variable TZ to a new value before calling strftime() - will influence the result (the %Z format) even if the information in - TP is computed with a totally different time zone. - This is bogus: though POSIX allows bad behavior like this, - POSIX does not require it. Do the right thing instead. */ - zone = (const char *) tp->tm_zone; - /* POSIX.1 8.1.1 requires that whenever strftime() is called, the - time zone names contained in the external variable `tzname' shall - be set as if the tzset() function had been called. */ - tzset (); - zonelen = strlen (zone); - - if (hour12 > 12) - hour12 -= 12; - else - if (hour12 == 0) hour12 = 12; - - for (f = format; *f != '\0'; ++f) - { - enum { pad_zero, pad_space, pad_none } pad; /* Padding for number. */ - unsigned int maxdigits; /* Max digits for numeric format. */ - unsigned int number_value; /* Numeric value to be printed. */ - const char *subfmt; - -#if HAVE_MBLEN - if (!isascii(*f)) - { - /* Non-ASCII, may be a multibyte. */ - int len = mblen(f, strlen(f)); - if (len > 0) - { - cpy(len, f); - continue; - } - } -#endif - - if (*f != '%') - { - add(1, *p = *f); - continue; - } - - /* Check for flags that can modify a number format. */ - ++f; - switch (*f) - { - case '_': - pad = pad_space; - ++f; - break; - case '-': - pad = pad_none; - ++f; - break; - default: - pad = pad_zero; - break; - } - - /* Now do the specified format. */ - switch (*f) - { - case '\0': - case '%': - add(1, *p = *f); - break; - - case 'a': - cpy(aw_len, a_wkday); - break; - - case 'A': - cpy(wkday_len, f_wkday); - break; - - case 'b': - case 'h': /* GNU extension. */ - cpy(am_len, a_month); - break; - - case 'B': - cpy(month_len, f_month); - break; - - case 'c': -#ifdef __UCLIBC_HAS_LOCALE__ - subfmt = _NL_CURRENT (LC_TIME, D_T_FMT); -#else - subfmt = "%a %b %d %H:%M:%S %Z %Y"; -#endif - subformat: - { - size_t len = strftime (p, maxsize - i, subfmt, tp); - if (len == 0 && *subfmt) - return 0; - add(len, ); - } - break; - -#define DO_NUMBER(digits, value) \ - maxdigits = digits; number_value = value; goto do_number -#define DO_NUMBER_NOPAD(digits, value) \ - maxdigits = digits; number_value = value; goto do_number_nopad - - case 'C': - DO_NUMBER (2, (1900 + tp->tm_year) / 100); - - case 'x': -#ifdef __UCLIBC_HAS_LOCALE__ - subfmt = _NL_CURRENT (LC_TIME, D_FMT); - goto subformat; -#endif - /* Fall through. */ - case 'D': /* GNU extension. */ - subfmt = "%m/%d/%y"; - goto subformat; - - case 'd': - DO_NUMBER (2, tp->tm_mday); - - case 'e': /* GNU extension: %d, but blank-padded. */ -#if 0 - DO_NUMBER_NOPAD (2, tp->tm_mday); -#else - DO_NUMBER (2, tp->tm_mday); -#endif - - /* All numeric formats set MAXDIGITS and NUMBER_VALUE and then - jump to one of these two labels. */ - - do_number_nopad: - /* Force `-' flag. */ - pad = pad_none; - - do_number: - { - /* Format the number according to the PAD flag. */ - - register char *nf = &number_fmt[1]; - int printed; - - switch (pad) - { - case pad_zero: - *nf++ = '0'; - case pad_space: - *nf++ = '0' + maxdigits; - case pad_none: - *nf++ = 'u'; - *nf = '\0'; - } - -#ifdef _LIBC - if (i + maxdigits >= maxsize) - return 0; - printed = sprintf (p, number_fmt, number_value); - i += printed; - p += printed; -#else - add (maxdigits, sprintf (p, number_fmt, number_value); - printed = strlen (p)); -#endif - - break; - } - - - case 'H': - DO_NUMBER (2, tp->tm_hour); - - case 'I': - DO_NUMBER (2, hour12); - - case 'k': /* GNU extension. */ - DO_NUMBER_NOPAD (2, tp->tm_hour); - - case 'l': /* GNU extension. */ - DO_NUMBER_NOPAD (2, hour12); - - case 'j': - DO_NUMBER (3, 1 + tp->tm_yday); - - case 'M': - DO_NUMBER (2, tp->tm_min); - - case 'm': - DO_NUMBER (2, tp->tm_mon + 1); - - case 'n': /* GNU extension. */ - add (1, *p = '\n'); - break; - - case 'p': - cpy(ap_len, ampm); - break; - - case 'R': /* GNU extension. */ - subfmt = "%H:%M"; - goto subformat; - - case 'r': /* GNU extension. */ - subfmt = "%I:%M:%S %p"; - goto subformat; - - case 'S': - DO_NUMBER (2, tp->tm_sec); - - case 'X': -#ifdef __UCLIBC_HAS_LOCALE__ - subfmt = _NL_CURRENT (LC_TIME, T_FMT); - goto subformat; -#endif - /* Fall through. */ - case 'T': /* GNU extenstion. */ - subfmt = "%H:%M:%S"; - goto subformat; - - case 't': /* GNU extenstion. */ - add (1, *p = '\t'); - break; - - case 'U': - DO_NUMBER (2, y_week0); - - case 'V': - DO_NUMBER (2, y_week2); - - case 'W': - DO_NUMBER (2, y_week1); - - case 'w': - DO_NUMBER (1, tp->tm_wday); - - case 'Y': - DO_NUMBER (4, 1900 + tp->tm_year); - - case 'y': - DO_NUMBER (2, tp->tm_year % 100); - - case 'Z': - /* The tzset() call might have changed the value. */ - if (!(zone && *zone) && tp->tm_isdst >= 0) - zone = tzname[tp->tm_isdst]; - if (! zone) - zone = ""; /* POSIX.2 requires the empty string here. */ - cpy(zonelen, zone); - break; - - default: - /* Bad format. */ - break; - } - } - - if (p) - *p = '\0'; - return i; -} |