[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Omaha.pm] Why I hack Perl
This is Date.xs, some C code that Class::Date uses.
Glancing at this today reminded me how spoiled I am by being a Perl
programmer.
j
(I'm in pine. I hope this doesn't line wrap.)
void
strftime_xs(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1,
isdst = -1)
char * fmt
int sec
int min
int hour
int mday
int mon
int year
int wday
int yday
int isdst
PPCODE:
{
char tmpbuf[128];
struct tm mytm;
int len;
memset(&mytm, 0, sizeof(mytm));
mytm.tm_sec = sec;
mytm.tm_min = min;
mytm.tm_hour = hour;
mytm.tm_mday = mday;
mytm.tm_mon = mon;
mytm.tm_year = year;
mytm.tm_wday = wday;
mytm.tm_yday = yday;
mytm.tm_isdst = isdst;
classdate_mini_mktime(&mytm);
CLASSDATE_TM_DEBUG(mytm);
len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm);
/*
** The following is needed to handle to the situation where
** tmpbuf overflows. Basically we want to allocate a buffer
** and try repeatedly. The reason why it is so complicated
** is that getting a return value of 0 from strftime can indicate
** one of the following:
** 1. buffer overflowed,
** 2. illegal conversion specifier, or
** 3. the format string specifies nothing to be returned(not
** an error). This could be because format is an empty string
** or it specifies %p that yields an empty string in some locale.
** If there is a better way to make it portable, go ahead by
** all means.
*/
if ((len > 0 && len < sizeof(tmpbuf)) || (len == 0 && *fmt == '\0'))
ST(0) = sv_2mortal(newSVpv(tmpbuf, len));
else {
/* Possibly buf overflowed - try again with a bigger buf*/
int fmtlen = strlen(fmt);
int bufsize = fmtlen + sizeof(tmpbuf);
char* buf;
int buflen;
New(0, buf, bufsize, char);
while (buf) {
CLASSDATE_TM_DEBUG(mytm);
...etc...