Mail Archives: djgpp-workers/1999/03/13/14:17:33
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/
- Raw text -