Message-Id: <199903131915.TAA75566@out2.ibm.net> From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Sat, 13 Mar 1999 14:15:47 -0500 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: strftime patch X-mailer: Pegasus Mail for Win32 (v3.01d) Reply-To: djgpp-workers AT delorie DOT com In trying to port a program I wrote with BC++ 4.52 to DJGPP, I discovered that DJGPP's strftime() doesn't support the POSIX 'O' modifier (e.g. %Od, %Oe, etc.). The patch below adds support 'O' modifiers and minimally supports the 'E' modifiers by acting as if '%Ex' were given as '%x' where 'x' is the specifier. Index: djgpp/src/libc/ansi/time/strftime.c ======================================================= ============ RCS file: /cvs/djgpp/djgpp/src/libc/ansi/time/strftime.c,v retrieving revision 1.2 diff -c -3 -b -r1.2 strftime.c *** strftime.c 1998/01/01 16:42:52 1.2 --- strftime.c 1999/03/13 19:03:27 *************** *** 21,26 **** --- 21,34 ---- "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; + static const char *Ofmt[] = { + "st", "nd", "rd", "th", + }; + static const char Ofmt_index[] = { + 3, 0, 1, 2, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 1, 2, 3, 3, 3, 3, 3, 3, + }; static size_t gsize; static char *pt; *************** *** 57,65 **** --- 65,88 ---- return _add(++p, 0); } + static + const char *_get_ordinal (int num) + { + if (num <= 0) + return ""; + + if (num >= 20) + num %= 10; + + return Ofmt[(int)Ofmt_index[num] ]; + } + static size_t _fmt(const char *format, const struct tm *t, int upcase) { + int add_ordinal = 0; + char no_pad = 0; + for (; *format; ++format) { if (*format == '%') *************** *** 73,81 **** pad = space = '0', format++; if (format[1] == '^') upcase = 1, format++; ! switch(*++format) { case '\0': --format; break; --- 96,123 ---- pad = space = '0', format++; if (format[1] == '^') upcase = 1, format++; + + ++format; ! /* Support %Ox specifiers */ ! if (*format == 'O') { + add_ordinal = 1; + ++format; + } + else + { + add_ordinal = 0; + + /* Support %Ex specifiers by acting as if %x were given. */ + if (*format == 'E') + { + ++format; + } + } + + switch(*format) + { case '\0': --format; break; *************** *** 115,120 **** --- 157,164 ---- case 'e': if (!_conv(t->tm_mday, 2, ' ')) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_mday), upcase); continue; case 'D': if (!_fmt("%m/%d/%y", t, upcase)) *************** *** 123,138 **** case 'd': if (!_conv(t->tm_mday, 2, pad)) return 0; continue; case 'H': if (!_conv(t->tm_hour, 2, pad)) return 0; continue; case 'I': ! if (!_conv(t->tm_hour % 12 ? ! t->tm_hour % 12 : 12, 2, pad)) return 0; continue; case 'j': if (!_conv(t->tm_yday + 1, 3, pad)) return 0; --- 167,190 ---- case 'd': if (!_conv(t->tm_mday, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_mday), upcase); continue; case 'H': if (!_conv(t->tm_hour, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_hour), upcase); continue; case 'I': ! { ! int num = (t->tm_hour % 12 ? t->tm_hour % 12 : 12); ! if (!_conv(num, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(num), upcase); continue; + } case 'j': if (!_conv(t->tm_yday + 1, 3, pad)) return 0; *************** *** 149,158 **** case 'M': if (!_conv(t->tm_min, 2, pad)) return 0; continue; case 'm': ! if (!_conv(t->tm_mon + 1, 2, pad)) return 0; continue; case 'n': if (!_add("\n", upcase)) --- 201,214 ---- case 'M': if (!_conv(t->tm_min, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_min), upcase); continue; case 'm': ! if (!_conv(t->tm_mon + 1, 2, (add_ordinal ? no_pad : pad))) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_mon + 1), upcase); continue; case 'n': if (!_add("\n", upcase)) *************** *** 173,178 **** --- 229,236 ---- case 'S': if (!_conv(t->tm_sec, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_sec), upcase); continue; case 'T': case 'X': *************** *** 184,206 **** return 0; continue; case 'u': ! if (!_conv(t->tm_wday==0 ? 7 : t->tm_wday, 1, pad)) return 0; continue; case 'U': ! if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, ! 2, pad)) return 0; continue; case 'W': ! if (!_conv((t->tm_yday + 7 - ! (t->tm_wday ? (t->tm_wday - 1) : 6)) ! / 7, 2, pad)) return 0; continue; case 'w': if (!_conv(t->tm_wday, 1, pad)) return 0; continue; case 'x': if (!_fmt("%m/%d/%y", t, upcase)) --- 242,278 ---- return 0; continue; case 'u': ! { ! int num = (t->tm_wday == 0 ? 7 : t->tm_wday); ! if (!_conv(num, 1, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(num), upcase); continue; + } case 'U': ! { ! int num = (t->tm_yday + 7 - t->tm_wday) / 7; ! if (!_conv(num, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(num), upcase); continue; + } case 'W': ! { ! int num = (t->tm_yday + 7 - (t->tm_wday ? (t->tm_wday - 1) : 6)) / 7; ! if (!_conv(num, 2, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(num), upcase); continue; + } case 'w': if (!_conv(t->tm_wday, 1, pad)) return 0; + if (add_ordinal) + _add(_get_ordinal(t->tm_wday), upcase); continue; case 'x': if (!_fmt("%m/%d/%y", t, upcase)) *************** *** 208,216 **** continue; case 'y': case 'g': ! if (!_conv((t->tm_year + TM_YEAR_BASE) % 100, 2, pad)) return 0; continue; case 'Y': case 'G': if (!_conv(t->tm_year + TM_YEAR_BASE, 4, pad)) --- 280,294 ---- continue; case 'y': case 'g': ! { ! int num = (t->tm_year + TM_YEAR_BASE) % 100; ! if (!_conv(num, 2, pad)) return 0; + + if (add_ordinal) + _add(_get_ordinal(num), upcase); continue; + } case 'Y': case 'G': if (!_conv(t->tm_year + TM_YEAR_BASE, 4, pad)) Index: djgpp/src/libc/ansi/time/strftime.txh ======================================================= ============ RCS file: /cvs/djgpp/djgpp/src/libc/ansi/time/strftime.txh,v retrieving revision 1.2 diff -c -3 -r1.2 strftime.txh *** strftime.txh 1998/09/27 15:21:00 1.2 --- strftime.txh 1999/03/13 19:04:27 *************** *** 118,123 **** --- 118,127 ---- The week of the year, with the first week defined by the first Sunday of the year, zero padded to two characters (@code{39}) + @item %u + + The day of the week (1-7) (@code{6}) + @item %W The week of the year, with the first week defined by the first Monday of *************** *** 146,151 **** --- 150,220 ---- @item %% A percent symbol (@code{%}) + + @end table + + Some format specifiers can be modified with the @code{O} or @code{E} + modifier to indicate that an alternate format should be added + to the output instead of the regular format. If a format specifier + does not support an alternate output format (the case for all @code{E} + modifiers), then the regular format will be output. For those + format specifiers that support the @code{O} modifier, the value + is output as an ordinal string if possible. + + Here are the @code{%O} specifiers, with the + examples as if the time was Friday, October 1, 1993, at 03:30:34 PM EDT: + + @table + + @item %Od + + The day of the month as an ordianl (@code{2nd}) + + @item %Oe + + The day of the month as an ordinal (@code{2nd}) + + @item %OH + + The hour (0-24) as an ordinal (@code{15th}) + + @item %OI + + The hour (1-12) in ordinal format (@code{3rd}) + + @item %OM + + The minutes in ordinal format (@code{30th}) + + @item %Om + + The month (1-12) in ordinal format (@code{10th}) + + @item %OS + + The seconds in ordinal format (@code{35th}) + + @item %OU + + The week of the year, with the first week defined by + the first Sunday of the year, in ordinal format (@code{39th}) + + @item %Ou + + The day of the week in ordinal format (1st-7th) (@code{6th}) + + @item %OW + + The week of the year, with the first week defined by the first Monday of + the year, in ordinal format (@code{39th}) + + @item %Ow + + The day of the week (0th-6th) in ordinal format (@code{5th}) + + @item %Oy + + The year (0th-99th) of the century (@code{93rd}) @end table --- Mark Elbrecht snowball3 AT usa DOT net http://members.xoom.com/snowball3/