ack/lang/cem/libcc.ansi/time/strftime.c
2018-06-21 22:33:47 +02:00

188 lines
3.8 KiB
C

/*
* strftime - convert a structure to a string, controlled by an argument
*/
/* $Id$ */
#include <time.h>
#include "loc_time.h"
/* The width can be -1 in both s_prnt() as in u_prnt(). This
* indicates that as many characters as needed should be printed.
*/
static char*
s_prnt(char* s, size_t maxsize, const char* str, int width)
{
while (width > 0 || (width < 0 && *str))
{
if (!maxsize)
break;
*s++ = *str++;
maxsize--;
width--;
}
return s;
}
static char*
u_prnt(char* s, size_t maxsize, unsigned val, int width)
{
int c;
c = val % 10;
val = val / 10;
if (--width > 0 || (width < 0 && val != 0))
s = u_prnt(s, (maxsize ? maxsize - 1 : 0), val, width);
if (maxsize)
*s++ = c + '0';
return s;
}
size_t
strftime(char* s, size_t maxsize,
const char* format, const struct tm* timeptr)
{
size_t n;
char *firsts, *olds;
if (!format)
return 0;
_tzset(); /* for %Z conversion */
firsts = s;
while (maxsize && *format)
{
while (maxsize && *format && *format != '%')
{
*s++ = *format++;
maxsize--;
}
if (!maxsize || !*format)
break;
format++;
olds = s;
switch (*format++)
{
case 'a':
s = s_prnt(s, maxsize,
_days[timeptr->tm_wday], ABB_LEN);
maxsize -= s - olds;
break;
case 'A':
s = s_prnt(s, maxsize, _days[timeptr->tm_wday], -1);
maxsize -= s - olds;
break;
case 'b':
s = s_prnt(s, maxsize,
_months[timeptr->tm_mon], ABB_LEN);
maxsize -= s - olds;
break;
case 'B':
s = s_prnt(s, maxsize, _months[timeptr->tm_mon], -1);
maxsize -= s - olds;
break;
case 'c':
n = strftime(s, maxsize,
"%a %b %d %H:%M:%S %Y", timeptr);
if (n)
maxsize -= n;
else
maxsize = 0;
s += n;
break;
case 'd':
s = u_prnt(s, maxsize, timeptr->tm_mday, 2);
maxsize -= s - olds;
break;
case 'H':
s = u_prnt(s, maxsize, timeptr->tm_hour, 2);
maxsize -= s - olds;
break;
case 'I':
s = u_prnt(s, maxsize,
(timeptr->tm_hour + 11) % 12 + 1, 2);
maxsize -= s - olds;
break;
case 'j':
s = u_prnt(s, maxsize, timeptr->tm_yday + 1, 3);
maxsize -= s - olds;
break;
case 'm':
s = u_prnt(s, maxsize, timeptr->tm_mon + 1, 2);
maxsize -= s - olds;
break;
case 'M':
s = u_prnt(s, maxsize, timeptr->tm_min, 2);
maxsize -= s - olds;
break;
case 'p':
s = s_prnt(s, maxsize,
(timeptr->tm_hour < 12) ? "AM" : "PM", 2);
maxsize -= s - olds;
break;
case 'S':
s = u_prnt(s, maxsize, timeptr->tm_sec, 2);
maxsize -= s - olds;
break;
case 'U':
s = u_prnt(s, maxsize, /* ??? */
(timeptr->tm_yday + 7 - timeptr->tm_wday) / 7, 2);
maxsize -= s - olds;
break;
case 'w':
s = u_prnt(s, maxsize, timeptr->tm_wday, 1);
maxsize -= s - olds;
break;
case 'W':
s = u_prnt(s, maxsize, /* ??? */
(timeptr->tm_yday + 7 - (timeptr->tm_wday + 6) % 7) / 7, 2);
maxsize -= s - olds;
break;
case 'x':
n = strftime(s, maxsize, "%a %b %d %Y", timeptr);
if (n)
maxsize -= n;
else
maxsize = 0;
s += n;
break;
case 'X':
n = strftime(s, maxsize, "%H:%M:%S", timeptr);
if (n)
maxsize -= n;
else
maxsize = 0;
s += n;
break;
case 'y':
s = u_prnt(s, maxsize, timeptr->tm_year % 100, 2);
maxsize -= s - olds;
break;
case 'Y':
s = u_prnt(s, maxsize, timeptr->tm_year + YEAR0, -1);
maxsize -= s - olds;
break;
case 'Z':
s = s_prnt(s, maxsize,
_tzname[(timeptr->tm_isdst > 0)], -1);
maxsize -= s - olds;
break;
case '%':
*s++ = '%';
maxsize--;
break;
default:
/* A conversion error. Leave the loop. */
while (*format)
format++;
break;
}
}
if (maxsize)
{
*s = '\0';
return s - firsts;
}
return 0; /* The buffer is full */
}