Index: trunk/src/emx/src/lib/time/strptime.c
===================================================================
--- trunk/src/emx/src/lib/time/strptime.c	(revision 2069)
+++ trunk/src/emx/src/lib/time/strptime.c	(revision 2070)
@@ -38,6 +38,6 @@
   if (!(s = parse_fmt (s, FMT, tm, &mask))) \
     return NULL;
-#define NUMBER(DST,MIN,MAX,ADD) \
-  if (!(s = parse_number (s, DST, MIN, MAX, ADD))) \
+#define NUMBER(DST,MIN,MAX,ADD,LEN) \
+  if (!(s = parse_number (s, DST, MIN, MAX, ADD, LEN))) \
     return NULL;
 #define STRING(STR) \
@@ -49,5 +49,5 @@
 
 static const char *parse_number (const char *s, int *dst,
-  int min, int max, int add)
+  int min, int max, int add, int len)
 {
   int n;
@@ -58,5 +58,5 @@
     return NULL;
   n = 0;
-  while (isdigit (*s))
+  while (isdigit (*s) && len-- > 0)
     n = n * 10 + (*s++ - '0');  /* TODO: check for overflow */
   if (n < min || (max >= 0 && n > max))
@@ -109,13 +109,14 @@
 
 #define MASK_CENTURY	0x00000001
-#define MASK_YEAR2	0x00000002
-#define MASK_YEAR4	0x00000004
-#define MASK_YEAR	(MASK_YEAR2 | MASK_YEAR4)
+#define MASK_YEAR_ANY   0x10000000	
+#define MASK_YEAR2	0x10000002
+#define MASK_YEAR4	0x10000004
 #define MASK_YEARDAY	0x00000008
 #define MASK_MONTH	0x00000010
 #define MASK_MONTHDAY	0x00000020
-#define MASK_WEEKS	0x00000040
-#define MASK_WEEKM	0x00000080
-#define MASK_WEEK	(MASK_WEEKM | MASK_WEEKS)
+#define MASK_WEEK_ANY	0x20000000
+#define MASK_WEEKS	0x20000040
+#define MASK_WEEKM	0x20000080
+#define MASK_WEEKI	0x20001000
 #define MASK_WEEKDAY	0x00000100
 #define MASK_HOUR	0x00000200
@@ -190,5 +191,5 @@
 
         case 'C': /* Century number */
-          NUMBER (&century, 0, 99, 0);
+          NUMBER (&century, 0, 99, 0, 2);
           mask |= MASK_CENTURY;
           break;
@@ -196,5 +197,5 @@
         case 'd': /* Day of the month (1-31) */
         case 'e':
-          NUMBER (&tm->tm_mday, 1, 31, 0);
+          NUMBER (&tm->tm_mday, 1, 31, 0, 2);
           mask |= MASK_MONTHDAY;
           break;
@@ -204,7 +205,11 @@
           break;
 
+        case 'F': /* ISO Date - C99 */
+          RECURSE ("%Y-%m-%d");
+          break;
+
         case 'H': /* Hour (00-23) */
         case 'k':
-          NUMBER (&tm->tm_hour, 0, 23, 0);
+          NUMBER (&tm->tm_hour, 0, 23, 0, 2);
           mask |= MASK_HOUR;
           break;
@@ -212,20 +217,20 @@
         case 'I': /* Hour (01-12) */
         case 'l':
-          NUMBER (&tm->tm_hour, 1, 12, 0);
+          NUMBER (&tm->tm_hour, 1, 12, 0, 2);
           mask |= MASK_HOUR;
           break;
 
         case 'j': /* Day of the year (1-366) */
-          NUMBER (&tm->tm_yday, 1, 366, -1);
+          NUMBER (&tm->tm_yday, 1, 366, -1, 3);
           mask |= MASK_YEARDAY;
           break;
 
         case 'm': /* Month (01-12) */
-          NUMBER (&tm->tm_mon, 1, 12, -1);
+          NUMBER (&tm->tm_mon, 1, 12, -1, 2);
           mask |= MASK_MONTH;
           break;
 
         case 'M': /* Minutes (00-59) */
-          NUMBER (&tm->tm_min, 0, 59, 0);
+          NUMBER (&tm->tm_min, 0, 59, 0, 2);
           mask |= MASK_MINUTE;
           break;
@@ -237,15 +242,17 @@
           break;
 
-        case 'p': /* am or pm */
+        case 'p': /* AM or PM */
           if (!(mask & MASK_HOUR)
            || (tm->tm_hour < 1)
            || (tm->tm_hour > 12))
             return NULL;
-          if ((t = parse_string (s, __libc_gLocaleTime.am)) != NULL)
+          if (   (t = parse_string (s, "AM")) != NULL
+              || (t = parse_string (s, __libc_gLocaleTime.am)) != NULL)
           {
             if (tm->tm_hour == 12)
               tm->tm_hour = 0;
           }
-          else if ((t = parse_string (s, __libc_gLocaleTime.pm)) != NULL)
+          else if (   (t = parse_string (s, "PM")) != NULL
+                   || (t = parse_string (s, __libc_gLocaleTime.pm)) != NULL)
           {
             if (tm->tm_hour != 12)
@@ -257,4 +264,26 @@
           break;
 
+        case 'P': /* am or pm */
+          if (!(mask & MASK_HOUR)
+           || (tm->tm_hour < 1)
+           || (tm->tm_hour > 12))
+            return NULL;
+          if (   (t = parse_string (s, "am")) != NULL
+              || (t = parse_string (s, __libc_gLocaleTime.am)) != NULL)
+          {
+            if (tm->tm_hour == 12)
+              tm->tm_hour = 0;
+          }
+          else if (   (t = parse_string (s, "pm")) != NULL
+                   || (t = parse_string (s, __libc_gLocaleTime.pm)) != NULL)
+          {
+            if (tm->tm_hour != 12)
+              tm->tm_hour += 12;
+          }
+          else
+            return NULL;
+          s = t;
+          break;
+
         case 'r': /* HH:MM:SS am/pm */
           RECURSE ("%I:%M:%S %p");
@@ -266,5 +295,5 @@
 
         case 'S': /* Seconds (00-61(?)) */
-          NUMBER (&tm->tm_sec, 0, 61, 0);
+          NUMBER (&tm->tm_sec, 0, 61, 0, 2);
           mask |= MASK_SECOND;
           break;
@@ -281,15 +310,15 @@
 
         case 'w': /* Weekday (0-6), 0 = Sunday */
-          NUMBER (&tm->tm_wday, 0, 6, 0);
+          NUMBER (&tm->tm_wday, 0, 6, 0, 1);
           mask |= MASK_WEEKDAY;
           break;
 
         case 'U': /* Week number (0-53), 0 = Sunday */
-          NUMBER (&week, 0, 53, 0);
+          NUMBER (&week, 0, 53, 0, 2);
           mask |= MASK_WEEKS;
           break;
 
         case 'W': /* Week number (0-53), 0 = Monday */
-          NUMBER (&week, 0, 53, 0);
+          NUMBER (&week, 0, 53, 0, 2);
           mask |= MASK_WEEKM;
           break;
@@ -304,5 +333,5 @@
 
         case 'y':
-          NUMBER (&tm->tm_year, 0, 99, 0);
+          NUMBER (&tm->tm_year, 0, 99, 0, 2);
           if (tm->tm_year < 69)
             tm->tm_year += 100;
@@ -311,8 +340,9 @@
 
         case 'Y':
-          NUMBER (&tm->tm_year, 1900, -1, -1900);
+          NUMBER (&tm->tm_year, 1900, -1, -1900, 4);
           mask |= MASK_YEAR4;
           /* Ignore century since it was explicitely given */
-          century = -1; mask &= ~MASK_CENTURY;
+          century = -1;
+          mask &= ~MASK_CENTURY;
           break;
 
@@ -325,5 +355,5 @@
   if (mask & MASK_CENTURY)
   {
-    if (!(mask & MASK_YEAR))
+    if (!(mask & MASK_YEAR_ANY))
       tm->tm_year = 0;
     tm->tm_year = (century - 19) * 100 + (tm->tm_year % 100);
@@ -335,5 +365,5 @@
     mask |= *retmask;
 
-  if ((mask & MASK_YEAR) && (mask & MASK_YEARDAY)
+  if ((mask & MASK_YEAR_ANY) && (mask & MASK_YEARDAY)
    && (mask & (MASK_MONTH | MASK_MONTHDAY)) != (MASK_MONTH | MASK_MONTHDAY))
   {
@@ -341,6 +371,6 @@
     const unsigned short *md = _leap_year (tm->tm_year + 1900) ?
       _month_day_leap : _month_day_non_leap;
-    for (tm->tm_mon = 0; tm->tm_mon < 12 && tm->tm_yday < md [tm->tm_mon];
-         tm->tm_mon++) ;
+    for (tm->tm_mon = 11; tm->tm_mon > 0 && tm->tm_yday < md [tm->tm_mon]; tm->tm_mon--)
+        /* nothing */;
     tm->tm_mday = 1 + tm->tm_yday - md [tm->tm_mon];
     mask |= MASK_MONTH | MASK_MONTHDAY;
@@ -349,17 +379,19 @@
   if (!(mask & MASK_YEARDAY))
   {
-    if ((mask & MASK_WEEK) && (mask & MASK_WEEKDAY) && (mask & MASK_YEAR)
+    if ((mask & MASK_WEEK_ANY) && (mask & MASK_WEEKDAY) && (mask & MASK_YEAR_ANY)
      && (tm->tm_year >= 70) && (tm->tm_year <= 206))
     {
       /* Compute day of the year given week number and weekday */
-      int dow = (4 + _year_day [tm->tm_year]) % 7;
-      if (mask & MASK_WEEKM)
-        dow--;
-      dow = (tm->tm_wday - dow) % 7;
-      if (dow < 0) dow += 7;
+      int dow = (mask & MASK_WEEKM) == MASK_WEEKM ? 3 : 4;
+      dow = (dow + _year_day [tm->tm_year]) % 7;
+      if (!dow)
+          week--;
+      dow = (tm->tm_wday - ((mask & MASK_WEEKM) == MASK_WEEKM) - dow) % 7;
+      if (dow < 0)
+        dow += 7;
       tm->tm_yday = week * 7 + dow;
       mask |= MASK_YEARDAY;
     }
-    else if ((mask & MASK_YEAR) && (mask & MASK_MONTH) && (mask & MASK_MONTHDAY))
+    else if ((mask & MASK_YEAR_ANY) && (mask & MASK_MONTH) && (mask & MASK_MONTHDAY))
     {
       /* Compute year day from month and day of the month */
@@ -371,5 +403,5 @@
   }
 
-  if (!(mask & MASK_WEEKDAY) && (mask & MASK_YEAR) && (mask & MASK_YEARDAY))
+  if (!(mask & MASK_WEEKDAY) && (mask & MASK_YEAR_ANY) && (mask & MASK_YEARDAY))
   {
     /* Compute day of the week if it was not given */
@@ -385,5 +417,5 @@
   }
 
-  if (((mask & (MASK_WEEK | MASK_WEEKDAY | MASK_YEAR)) == (MASK_WEEK | MASK_WEEKDAY | MASK_YEAR))
+  if (((mask & (MASK_WEEK_ANY | MASK_WEEKDAY | MASK_YEAR_ANY)) == (MASK_WEEK_ANY | MASK_WEEKDAY | MASK_YEAR_ANY))
    && ((mask & (MASK_MONTH | MASK_MONTHDAY)) != (MASK_MONTH | MASK_MONTHDAY)))
   {
@@ -393,8 +425,7 @@
     int days;
 
-    for (days = tm->tm_yday, tm->tm_mon = 0; days >= md [tm->tm_mon];
-         days -= md [tm->tm_mon], tm->tm_mon++)
-      ;
-    tm->tm_mday = 1 + days;
+    for (tm->tm_mon = 11; tm->tm_mon > 0 && tm->tm_yday < md [tm->tm_mon]; tm->tm_mon--)
+        /* nothing */;
+    tm->tm_mday = 1 + tm->tm_yday - md [tm->tm_mon];
     mask |= MASK_MONTH | MASK_MONTHDAY;
   }
@@ -403,5 +434,5 @@
      that are not located inside the tm structure. */
   if (retmask)
-    *retmask |= mask & ~(MASK_WEEK | MASK_CENTURY);
+    *retmask |= mask & ~(MASK_WEEKI | MASK_WEEKM | MASK_WEEKS | MASK_CENTURY);
 
   return s;
