[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...