"Fossies" - the Fresh Open Source Software Archive

Member "asctime.c" (15 Apr 2018, 4125 Bytes) of package /linux/misc/tzcode2018i.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "asctime.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2018d_vs_2018e.

    1 /* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000.  */
    2 
    3 /*
    4 ** This file is in the public domain, so clarified as of
    5 ** 1996-06-05 by Arthur David Olson.
    6 */
    7 
    8 /*
    9 ** Avoid the temptation to punt entirely to strftime;
   10 ** the output of strftime is supposed to be locale specific
   11 ** whereas the output of asctime is supposed to be constant.
   12 */
   13 
   14 /*LINTLIBRARY*/
   15 
   16 #include "private.h"
   17 #include <stdio.h>
   18 
   19 /*
   20 ** Some systems only handle "%.2d"; others only handle "%02d";
   21 ** "%02.2d" makes (most) everybody happy.
   22 ** At least some versions of gcc warn about the %02.2d;
   23 ** we conditionalize below to avoid the warning.
   24 */
   25 /*
   26 ** All years associated with 32-bit time_t values are exactly four digits long;
   27 ** some years associated with 64-bit time_t values are not.
   28 ** Vintage programs are coded for years that are always four digits long
   29 ** and may assume that the newline always lands in the same place.
   30 ** For years that are less than four digits, we pad the output with
   31 ** leading zeroes to get the newline in the traditional place.
   32 ** The -4 ensures that we get four characters of output even if
   33 ** we call a strftime variant that produces fewer characters for some years.
   34 ** The ISO C and POSIX standards prohibit padding the year,
   35 ** but many implementations pad anyway; most likely the standards are buggy.
   36 */
   37 #ifdef __GNUC__
   38 #define ASCTIME_FMT "%s %s%3d %2.2d:%2.2d:%2.2d %-4s\n"
   39 #else /* !defined __GNUC__ */
   40 #define ASCTIME_FMT "%s %s%3d %02.2d:%02.2d:%02.2d %-4s\n"
   41 #endif /* !defined __GNUC__ */
   42 /*
   43 ** For years that are more than four digits we put extra spaces before the year
   44 ** so that code trying to overwrite the newline won't end up overwriting
   45 ** a digit within a year and truncating the year (operating on the assumption
   46 ** that no output is better than wrong output).
   47 */
   48 #ifdef __GNUC__
   49 #define ASCTIME_FMT_B   "%s %s%3d %2.2d:%2.2d:%2.2d     %s\n"
   50 #else /* !defined __GNUC__ */
   51 #define ASCTIME_FMT_B   "%s %s%3d %02.2d:%02.2d:%02.2d     %s\n"
   52 #endif /* !defined __GNUC__ */
   53 
   54 #define STD_ASCTIME_BUF_SIZE    26
   55 /*
   56 ** Big enough for something such as
   57 ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648     -2147483648\n
   58 ** (two three-character abbreviations, five strings denoting integers,
   59 ** seven explicit spaces, two explicit colons, a newline,
   60 ** and a trailing NUL byte).
   61 ** The values above are for systems where an int is 32 bits and are provided
   62 ** as an example; the define below calculates the maximum for the system at
   63 ** hand.
   64 */
   65 #define MAX_ASCTIME_BUF_SIZE    (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
   66 
   67 static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
   68 
   69 char *
   70 asctime_r(register const struct tm *timeptr, char *buf)
   71 {
   72     static const char   wday_name[][4] = {
   73         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
   74     };
   75     static const char   mon_name[][4] = {
   76         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
   77         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
   78     };
   79     register const char *   wn;
   80     register const char *   mn;
   81     char            year[INT_STRLEN_MAXIMUM(int) + 2];
   82     char            result[MAX_ASCTIME_BUF_SIZE];
   83 
   84     if (timeptr == NULL) {
   85         errno = EINVAL;
   86         return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
   87     }
   88     if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
   89         wn = "???";
   90     else    wn = wday_name[timeptr->tm_wday];
   91     if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
   92         mn = "???";
   93     else    mn = mon_name[timeptr->tm_mon];
   94     /*
   95     ** Use strftime's %Y to generate the year, to avoid overflow problems
   96     ** when computing timeptr->tm_year + TM_YEAR_BASE.
   97     ** Assume that strftime is unaffected by other out-of-range members
   98     ** (e.g., timeptr->tm_mday) when processing "%Y".
   99     */
  100     strftime(year, sizeof year, "%Y", timeptr);
  101     /*
  102     ** We avoid using snprintf since it's not available on all systems.
  103     */
  104     sprintf(result,
  105         ((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
  106         wn, mn,
  107         timeptr->tm_mday, timeptr->tm_hour,
  108         timeptr->tm_min, timeptr->tm_sec,
  109         year);
  110     if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
  111         return strcpy(buf, result);
  112     else {
  113         errno = EOVERFLOW;
  114         return NULL;
  115     }
  116 }
  117 
  118 char *
  119 asctime(register const struct tm *timeptr)
  120 {
  121     return asctime_r(timeptr, buf_asctime);
  122 }