delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/03/13/14:17:33

Message-Id: <199903131915.TAA75566@out2.ibm.net>
From: "Mark E." <snowball3 AT usa DOT net>
To: djgpp-workers AT delorie DOT com
Date: Sat, 13 Mar 1999 14:15:47 -0500
MIME-Version: 1.0
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/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019